Compare commits
3 Commits
3.2.0+131
...
baed28bef7
| Author | SHA1 | Date | |
|---|---|---|---|
| baed28bef7 | |||
| 7a6eecf628 | |||
| 6a63bc235b |
@@ -195,7 +195,6 @@
|
|||||||
"checkInResultLevel2": "A Normal Day",
|
"checkInResultLevel2": "A Normal Day",
|
||||||
"checkInResultLevel3": "Good Luck",
|
"checkInResultLevel3": "Good Luck",
|
||||||
"checkInResultLevel4": "Best Luck",
|
"checkInResultLevel4": "Best Luck",
|
||||||
"checkInResultLevel5": "Happy Birthday 🥳",
|
|
||||||
"checkInActivityTitle": "{} checked in on {} and got a {}",
|
"checkInActivityTitle": "{} checked in on {} and got a {}",
|
||||||
"eventCalander": "Event Calander",
|
"eventCalander": "Event Calander",
|
||||||
"eventCalanderEmpty": "No events on that day.",
|
"eventCalanderEmpty": "No events on that day.",
|
||||||
@@ -229,8 +228,6 @@
|
|||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
"accountLanguageHint": "This language will be used for email and push notifications.",
|
"accountLanguageHint": "This language will be used for email and push notifications.",
|
||||||
"region": "Region",
|
|
||||||
"accountRegionHint": "This region will be used for content delivery and localization.",
|
|
||||||
"settingsDisplayLanguage": "Display Language",
|
"settingsDisplayLanguage": "Display Language",
|
||||||
"languageFollowSystem": "Follow System",
|
"languageFollowSystem": "Follow System",
|
||||||
"postsCreatedCount": "Posts",
|
"postsCreatedCount": "Posts",
|
||||||
@@ -352,8 +349,6 @@
|
|||||||
"chatBreakNone": "None",
|
"chatBreakNone": "None",
|
||||||
"settingsRealmCompactView": "Compact Realm View",
|
"settingsRealmCompactView": "Compact Realm View",
|
||||||
"settingsMixedFeed": "Mixed Feed",
|
"settingsMixedFeed": "Mixed Feed",
|
||||||
"settingsDataSavingMode": "Data Saving Mode",
|
|
||||||
"dataSavingHint": "Data Saving Mode",
|
|
||||||
"settingsAutoTranslate": "Auto Translate",
|
"settingsAutoTranslate": "Auto Translate",
|
||||||
"settingsHideBottomNav": "Hide Bottom Navigation",
|
"settingsHideBottomNav": "Hide Bottom Navigation",
|
||||||
"settingsSoundEffects": "Sound Effects",
|
"settingsSoundEffects": "Sound Effects",
|
||||||
@@ -976,6 +971,5 @@
|
|||||||
"shuffle": "Shuffle",
|
"shuffle": "Shuffle",
|
||||||
"pinned": "Pinned",
|
"pinned": "Pinned",
|
||||||
"noResultsFound": "No results found",
|
"noResultsFound": "No results found",
|
||||||
"toggleFilters": "Toggle filters",
|
"toggleFilters": "Toggle filters"
|
||||||
"notableDayNext": "{} is in"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -158,12 +158,11 @@
|
|||||||
"checkIn": "签到",
|
"checkIn": "签到",
|
||||||
"checkInNone": "尚未签到",
|
"checkInNone": "尚未签到",
|
||||||
"checkInNoneHint": "通过签到获取您的财富提示和每日奖励。",
|
"checkInNoneHint": "通过签到获取您的财富提示和每日奖励。",
|
||||||
"checkInResultLevel0": "大凶",
|
"checkInResultLevel0": "最差运气",
|
||||||
"checkInResultLevel1": "凶",
|
"checkInResultLevel1": "坏运气",
|
||||||
"checkInResultLevel2": "中平",
|
"checkInResultLevel2": "一个普通的日常",
|
||||||
"checkInResultLevel3": "吉",
|
"checkInResultLevel3": "好运",
|
||||||
"checkInResultLevel4": "大吉",
|
"checkInResultLevel4": "最佳运气",
|
||||||
"checkInResultLevel5": "生日快乐 🥳",
|
|
||||||
"checkInActivityTitle": "{} 在 {} 签到并获得了 {}",
|
"checkInActivityTitle": "{} 在 {} 签到并获得了 {}",
|
||||||
"eventCalander": "活动日历",
|
"eventCalander": "活动日历",
|
||||||
"eventCalanderEmpty": "该日无活动。",
|
"eventCalanderEmpty": "该日无活动。",
|
||||||
@@ -316,8 +315,6 @@
|
|||||||
"chatBreakNone": "无",
|
"chatBreakNone": "无",
|
||||||
"settingsRealmCompactView": "紧凑领域视图",
|
"settingsRealmCompactView": "紧凑领域视图",
|
||||||
"settingsMixedFeed": "混合动态",
|
"settingsMixedFeed": "混合动态",
|
||||||
"settingsDataSavingMode": "流量节省模式",
|
|
||||||
"dataSavingHint": "流量节省模式",
|
|
||||||
"settingsAutoTranslate": "自动翻译",
|
"settingsAutoTranslate": "自动翻译",
|
||||||
"settingsHideBottomNav": "隐藏底部导航",
|
"settingsHideBottomNav": "隐藏底部导航",
|
||||||
"settingsSoundEffects": "音效",
|
"settingsSoundEffects": "音效",
|
||||||
@@ -863,6 +860,5 @@
|
|||||||
"statusPresent": "至今",
|
"statusPresent": "至今",
|
||||||
"accountAutomated": "机器人",
|
"accountAutomated": "机器人",
|
||||||
"openInBrowser": "在浏览器中打开",
|
"openInBrowser": "在浏览器中打开",
|
||||||
"highlightPost": "精选帖子",
|
"highlightPost": "精选帖子"
|
||||||
"notableDayNext": "距离 {} 还有"
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -315,8 +315,6 @@
|
|||||||
"settingsRealmCompactView": "緊湊領域視圖",
|
"settingsRealmCompactView": "緊湊領域視圖",
|
||||||
"settingsMixedFeed": "混合動態",
|
"settingsMixedFeed": "混合動態",
|
||||||
"settingsAutoTranslate": "自動翻譯",
|
"settingsAutoTranslate": "自動翻譯",
|
||||||
"settingsDataSavingMode": "低數據模式",
|
|
||||||
"dataSavingHint": "低數據模式",
|
|
||||||
"settingsHideBottomNav": "隱藏底部導航",
|
"settingsHideBottomNav": "隱藏底部導航",
|
||||||
"settingsSoundEffects": "音效",
|
"settingsSoundEffects": "音效",
|
||||||
"settingsAprilFoolFeatures": "愚人節功能",
|
"settingsAprilFoolFeatures": "愚人節功能",
|
||||||
|
|||||||
@@ -136,8 +136,6 @@ PODS:
|
|||||||
- OrderedSet (~> 6.0.3)
|
- OrderedSet (~> 6.0.3)
|
||||||
- flutter_keyboard_visibility (0.0.1):
|
- flutter_keyboard_visibility (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_local_notifications (0.0.1):
|
|
||||||
- Flutter
|
|
||||||
- flutter_native_splash (2.4.3):
|
- flutter_native_splash (2.4.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_platform_alert (0.0.1):
|
- flutter_platform_alert (0.0.1):
|
||||||
@@ -316,7 +314,6 @@ DEPENDENCIES:
|
|||||||
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
||||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
||||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
@@ -405,8 +402,6 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||||
flutter_keyboard_visibility:
|
flutter_keyboard_visibility:
|
||||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||||
flutter_local_notifications:
|
|
||||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
flutter_platform_alert:
|
flutter_platform_alert:
|
||||||
@@ -493,7 +488,6 @@ SPEC CHECKSUMS:
|
|||||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
||||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
|
||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
||||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||||
|
|||||||
@@ -240,7 +240,6 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
themeMode: ThemeMode.system,
|
themeMode: ThemeMode.system,
|
||||||
routerConfig: router,
|
routerConfig: router,
|
||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
scrollBehavior: AppScrollBehavior(),
|
|
||||||
localizationsDelegates: [
|
localizationsDelegates: [
|
||||||
...context.localizationDelegates,
|
...context.localizationDelegates,
|
||||||
CroppyLocalizations.delegate,
|
CroppyLocalizations.delegate,
|
||||||
|
|||||||
@@ -13,7 +13,6 @@ sealed class SnAccount with _$SnAccount {
|
|||||||
required String name,
|
required String name,
|
||||||
required String nick,
|
required String nick,
|
||||||
required String language,
|
required String language,
|
||||||
@Default("") String region,
|
|
||||||
required bool isSuperuser,
|
required bool isSuperuser,
|
||||||
required String? automatedId,
|
required String? automatedId,
|
||||||
required SnAccountProfile profile,
|
required SnAccountProfile profile,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAccount {
|
mixin _$SnAccount {
|
||||||
|
|
||||||
String get id; String get name; String get nick; String get language; String get region; bool get isSuperuser; String? get automatedId; SnAccountProfile get profile; SnWalletSubscriptionRef? get perkSubscription; List<SnAccountBadge> get badges; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String get name; String get nick; String get language; bool get isSuperuser; String? get automatedId; SnAccountProfile get profile; SnWalletSubscriptionRef? get perkSubscription; List<SnAccountBadge> get badges; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnAccount
|
/// Create a copy of SnAccount
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $SnAccountCopyWith<SnAccount> get copyWith => _$SnAccountCopyWithImpl<SnAccount>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.region, region) || other.region == region)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other.badges, badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other.badges, badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(badges),createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(badges),createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, region: $region, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ abstract mixin class $SnAccountCopyWith<$Res> {
|
|||||||
factory $SnAccountCopyWith(SnAccount value, $Res Function(SnAccount) _then) = _$SnAccountCopyWithImpl;
|
factory $SnAccountCopyWith(SnAccount value, $Res Function(SnAccount) _then) = _$SnAccountCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String nick, String language, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,13 +65,12 @@ class _$SnAccountCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccount
|
/// Create a copy of SnAccount
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? region = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
||||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||||
as String,region: null == region ? _self.region : region // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,automatedId: freezed == automatedId ? _self.automatedId : automatedId // ignore: cast_nullable_to_non_nullable
|
as bool,automatedId: freezed == automatedId ? _self.automatedId : automatedId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
as String?,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -183,10 +182,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccount() when $default != null:
|
case _SnAccount() when $default != null:
|
||||||
return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -204,10 +203,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccount():
|
case _SnAccount():
|
||||||
return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -221,10 +220,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String nick, String language, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccount() when $default != null:
|
case _SnAccount() when $default != null:
|
||||||
return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -236,14 +235,13 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.region,_that
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnAccount implements SnAccount {
|
class _SnAccount implements SnAccount {
|
||||||
const _SnAccount({required this.id, required this.name, required this.nick, required this.language, this.region = "", required this.isSuperuser, required this.automatedId, required this.profile, required this.perkSubscription, final List<SnAccountBadge> badges = const [], required this.createdAt, required this.updatedAt, required this.deletedAt}): _badges = badges;
|
const _SnAccount({required this.id, required this.name, required this.nick, required this.language, required this.isSuperuser, required this.automatedId, required this.profile, required this.perkSubscription, final List<SnAccountBadge> badges = const [], required this.createdAt, required this.updatedAt, required this.deletedAt}): _badges = badges;
|
||||||
factory _SnAccount.fromJson(Map<String, dynamic> json) => _$SnAccountFromJson(json);
|
factory _SnAccount.fromJson(Map<String, dynamic> json) => _$SnAccountFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@override final String name;
|
@override final String name;
|
||||||
@override final String nick;
|
@override final String nick;
|
||||||
@override final String language;
|
@override final String language;
|
||||||
@override@JsonKey() final String region;
|
|
||||||
@override final bool isSuperuser;
|
@override final bool isSuperuser;
|
||||||
@override final String? automatedId;
|
@override final String? automatedId;
|
||||||
@override final SnAccountProfile profile;
|
@override final SnAccountProfile profile;
|
||||||
@@ -272,16 +270,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.region, region) || other.region == region)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other._badges, _badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.automatedId, automatedId) || other.automatedId == automatedId)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other._badges, _badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(_badges),createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(_badges),createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, region: $region, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -292,7 +290,7 @@ abstract mixin class _$SnAccountCopyWith<$Res> implements $SnAccountCopyWith<$Re
|
|||||||
factory _$SnAccountCopyWith(_SnAccount value, $Res Function(_SnAccount) _then) = __$SnAccountCopyWithImpl;
|
factory _$SnAccountCopyWith(_SnAccount value, $Res Function(_SnAccount) _then) = __$SnAccountCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String nick, String language, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String nick, String language, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -309,13 +307,12 @@ class __$SnAccountCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccount
|
/// Create a copy of SnAccount
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? region = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? isSuperuser = null,Object? automatedId = freezed,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnAccount(
|
return _then(_SnAccount(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
||||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||||
as String,region: null == region ? _self.region : region // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,automatedId: freezed == automatedId ? _self.automatedId : automatedId // ignore: cast_nullable_to_non_nullable
|
as bool,automatedId: freezed == automatedId ? _self.automatedId : automatedId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
as String?,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||||
|
|||||||
@@ -11,7 +11,6 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
|||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
nick: json['nick'] as String,
|
nick: json['nick'] as String,
|
||||||
language: json['language'] as String,
|
language: json['language'] as String,
|
||||||
region: json['region'] as String? ?? "",
|
|
||||||
isSuperuser: json['is_superuser'] as bool,
|
isSuperuser: json['is_superuser'] as bool,
|
||||||
automatedId: json['automated_id'] as String?,
|
automatedId: json['automated_id'] as String?,
|
||||||
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
||||||
@@ -40,7 +39,6 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
|||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'nick': instance.nick,
|
'nick': instance.nick,
|
||||||
'language': instance.language,
|
'language': instance.language,
|
||||||
'region': instance.region,
|
|
||||||
'is_superuser': instance.isSuperuser,
|
'is_superuser': instance.isSuperuser,
|
||||||
'automated_id': instance.automatedId,
|
'automated_id': instance.automatedId,
|
||||||
'profile': instance.profile.toJson(),
|
'profile': instance.profile.toJson(),
|
||||||
|
|||||||
@@ -4,20 +4,6 @@ import 'package:island/models/account.dart';
|
|||||||
part 'activity.freezed.dart';
|
part 'activity.freezed.dart';
|
||||||
part 'activity.g.dart';
|
part 'activity.g.dart';
|
||||||
|
|
||||||
@freezed
|
|
||||||
sealed class SnNotableDay with _$SnNotableDay {
|
|
||||||
const factory SnNotableDay({
|
|
||||||
required DateTime date,
|
|
||||||
required String localName,
|
|
||||||
required String globalName,
|
|
||||||
required String countryCode,
|
|
||||||
required List<int> holidays,
|
|
||||||
}) = _SnNotableDay;
|
|
||||||
|
|
||||||
factory SnNotableDay.fromJson(Map<String, dynamic> json) =>
|
|
||||||
_$SnNotableDayFromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class SnActivity with _$SnActivity {
|
sealed class SnActivity with _$SnActivity {
|
||||||
const factory SnActivity({
|
const factory SnActivity({
|
||||||
|
|||||||
@@ -12,281 +12,6 @@ part of 'activity.dart';
|
|||||||
// dart format off
|
// dart format off
|
||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
mixin _$SnNotableDay {
|
|
||||||
|
|
||||||
DateTime get date; String get localName; String get globalName; String get countryCode; List<int> get holidays;
|
|
||||||
/// Create a copy of SnNotableDay
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnNotableDayCopyWith<SnNotableDay> get copyWith => _$SnNotableDayCopyWithImpl<SnNotableDay>(this as SnNotableDay, _$identity);
|
|
||||||
|
|
||||||
/// Serializes this SnNotableDay to a JSON map.
|
|
||||||
Map<String, dynamic> toJson();
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnNotableDay&&(identical(other.date, date) || other.date == date)&&(identical(other.localName, localName) || other.localName == localName)&&(identical(other.globalName, globalName) || other.globalName == globalName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&const DeepCollectionEquality().equals(other.holidays, holidays));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,date,localName,globalName,countryCode,const DeepCollectionEquality().hash(holidays));
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'SnNotableDay(date: $date, localName: $localName, globalName: $globalName, countryCode: $countryCode, holidays: $holidays)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class $SnNotableDayCopyWith<$Res> {
|
|
||||||
factory $SnNotableDayCopyWith(SnNotableDay value, $Res Function(SnNotableDay) _then) = _$SnNotableDayCopyWithImpl;
|
|
||||||
@useResult
|
|
||||||
$Res call({
|
|
||||||
DateTime date, String localName, String globalName, String countryCode, List<int> holidays
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class _$SnNotableDayCopyWithImpl<$Res>
|
|
||||||
implements $SnNotableDayCopyWith<$Res> {
|
|
||||||
_$SnNotableDayCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final SnNotableDay _self;
|
|
||||||
final $Res Function(SnNotableDay) _then;
|
|
||||||
|
|
||||||
/// Create a copy of SnNotableDay
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? localName = null,Object? globalName = null,Object? countryCode = null,Object? holidays = null,}) {
|
|
||||||
return _then(_self.copyWith(
|
|
||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,localName: null == localName ? _self.localName : localName // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,globalName: null == globalName ? _self.globalName : globalName // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,holidays: null == holidays ? _self.holidays : holidays // ignore: cast_nullable_to_non_nullable
|
|
||||||
as List<int>,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Adds pattern-matching-related methods to [SnNotableDay].
|
|
||||||
extension SnNotableDayPatterns on SnNotableDay {
|
|
||||||
/// A variant of `map` that fallback to returning `orElse`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SnNotableDay value)? $default,{required TResult orElse(),}){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _SnNotableDay() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// Callbacks receives the raw object, upcasted.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case final Subclass2 value:
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SnNotableDay value) $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _SnNotableDay():
|
|
||||||
return $default(_that);}
|
|
||||||
}
|
|
||||||
/// A variant of `map` that fallback to returning `null`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SnNotableDay value)? $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _SnNotableDay() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to an `orElse` callback.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, String localName, String globalName, String countryCode, List<int> holidays)? $default,{required TResult orElse(),}) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _SnNotableDay() when $default != null:
|
|
||||||
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// As opposed to `map`, this offers destructuring.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case Subclass2(:final field2):
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, String localName, String globalName, String countryCode, List<int> holidays) $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _SnNotableDay():
|
|
||||||
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to returning `null`
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, String localName, String globalName, String countryCode, List<int> holidays)? $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _SnNotableDay() when $default != null:
|
|
||||||
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
@JsonSerializable()
|
|
||||||
|
|
||||||
class _SnNotableDay implements SnNotableDay {
|
|
||||||
const _SnNotableDay({required this.date, required this.localName, required this.globalName, required this.countryCode, required final List<int> holidays}): _holidays = holidays;
|
|
||||||
factory _SnNotableDay.fromJson(Map<String, dynamic> json) => _$SnNotableDayFromJson(json);
|
|
||||||
|
|
||||||
@override final DateTime date;
|
|
||||||
@override final String localName;
|
|
||||||
@override final String globalName;
|
|
||||||
@override final String countryCode;
|
|
||||||
final List<int> _holidays;
|
|
||||||
@override List<int> get holidays {
|
|
||||||
if (_holidays is EqualUnmodifiableListView) return _holidays;
|
|
||||||
// ignore: implicit_dynamic_type
|
|
||||||
return EqualUnmodifiableListView(_holidays);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Create a copy of SnNotableDay
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$SnNotableDayCopyWith<_SnNotableDay> get copyWith => __$SnNotableDayCopyWithImpl<_SnNotableDay>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return _$SnNotableDayToJson(this, );
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnNotableDay&&(identical(other.date, date) || other.date == date)&&(identical(other.localName, localName) || other.localName == localName)&&(identical(other.globalName, globalName) || other.globalName == globalName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&const DeepCollectionEquality().equals(other._holidays, _holidays));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,date,localName,globalName,countryCode,const DeepCollectionEquality().hash(_holidays));
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'SnNotableDay(date: $date, localName: $localName, globalName: $globalName, countryCode: $countryCode, holidays: $holidays)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class _$SnNotableDayCopyWith<$Res> implements $SnNotableDayCopyWith<$Res> {
|
|
||||||
factory _$SnNotableDayCopyWith(_SnNotableDay value, $Res Function(_SnNotableDay) _then) = __$SnNotableDayCopyWithImpl;
|
|
||||||
@override @useResult
|
|
||||||
$Res call({
|
|
||||||
DateTime date, String localName, String globalName, String countryCode, List<int> holidays
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class __$SnNotableDayCopyWithImpl<$Res>
|
|
||||||
implements _$SnNotableDayCopyWith<$Res> {
|
|
||||||
__$SnNotableDayCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final _SnNotableDay _self;
|
|
||||||
final $Res Function(_SnNotableDay) _then;
|
|
||||||
|
|
||||||
/// Create a copy of SnNotableDay
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? date = null,Object? localName = null,Object? globalName = null,Object? countryCode = null,Object? holidays = null,}) {
|
|
||||||
return _then(_SnNotableDay(
|
|
||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,localName: null == localName ? _self.localName : localName // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,globalName: null == globalName ? _self.globalName : globalName // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,holidays: null == holidays ? _self._holidays : holidays // ignore: cast_nullable_to_non_nullable
|
|
||||||
as List<int>,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnActivity {
|
mixin _$SnActivity {
|
||||||
|
|
||||||
|
|||||||
@@ -6,27 +6,6 @@ part of 'activity.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
_SnNotableDay _$SnNotableDayFromJson(Map<String, dynamic> json) =>
|
|
||||||
_SnNotableDay(
|
|
||||||
date: DateTime.parse(json['date'] as String),
|
|
||||||
localName: json['local_name'] as String,
|
|
||||||
globalName: json['global_name'] as String,
|
|
||||||
countryCode: json['country_code'] as String,
|
|
||||||
holidays:
|
|
||||||
(json['holidays'] as List<dynamic>)
|
|
||||||
.map((e) => (e as num).toInt())
|
|
||||||
.toList(),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$SnNotableDayToJson(_SnNotableDay instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'date': instance.date.toIso8601String(),
|
|
||||||
'local_name': instance.localName,
|
|
||||||
'global_name': instance.globalName,
|
|
||||||
'country_code': instance.countryCode,
|
|
||||||
'holidays': instance.holidays,
|
|
||||||
};
|
|
||||||
|
|
||||||
_SnActivity _$SnActivityFromJson(Map<String, dynamic> json) => _SnActivity(
|
_SnActivity _$SnActivityFromJson(Map<String, dynamic> json) => _SnActivity(
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
type: json['type'] as String,
|
type: json['type'] as String,
|
||||||
|
|||||||
@@ -11,20 +11,6 @@ sealed class AppToken with _$AppToken {
|
|||||||
_$AppTokenFromJson(json);
|
_$AppTokenFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
|
||||||
sealed class GeoIpLocation with _$GeoIpLocation {
|
|
||||||
const factory GeoIpLocation({
|
|
||||||
required double latitude,
|
|
||||||
required double longitude,
|
|
||||||
required String countryCode,
|
|
||||||
required String country,
|
|
||||||
required String city,
|
|
||||||
}) = _GeoIpLocation;
|
|
||||||
|
|
||||||
factory GeoIpLocation.fromJson(Map<String, dynamic> json) =>
|
|
||||||
_$GeoIpLocationFromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class SnAuthChallenge with _$SnAuthChallenge {
|
sealed class SnAuthChallenge with _$SnAuthChallenge {
|
||||||
const factory SnAuthChallenge({
|
const factory SnAuthChallenge({
|
||||||
@@ -40,7 +26,7 @@ sealed class SnAuthChallenge with _$SnAuthChallenge {
|
|||||||
required String ipAddress,
|
required String ipAddress,
|
||||||
required String userAgent,
|
required String userAgent,
|
||||||
required String? nonce,
|
required String? nonce,
|
||||||
required GeoIpLocation? location,
|
required String? location,
|
||||||
required String accountId,
|
required String accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
|
|||||||
@@ -269,279 +269,10 @@ as String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
mixin _$GeoIpLocation {
|
|
||||||
|
|
||||||
double get latitude; double get longitude; String get countryCode; String get country; String get city;
|
|
||||||
/// Create a copy of GeoIpLocation
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$GeoIpLocationCopyWith<GeoIpLocation> get copyWith => _$GeoIpLocationCopyWithImpl<GeoIpLocation>(this as GeoIpLocation, _$identity);
|
|
||||||
|
|
||||||
/// Serializes this GeoIpLocation to a JSON map.
|
|
||||||
Map<String, dynamic> toJson();
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is GeoIpLocation&&(identical(other.latitude, latitude) || other.latitude == latitude)&&(identical(other.longitude, longitude) || other.longitude == longitude)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.country, country) || other.country == country)&&(identical(other.city, city) || other.city == city));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,latitude,longitude,countryCode,country,city);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'GeoIpLocation(latitude: $latitude, longitude: $longitude, countryCode: $countryCode, country: $country, city: $city)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class $GeoIpLocationCopyWith<$Res> {
|
|
||||||
factory $GeoIpLocationCopyWith(GeoIpLocation value, $Res Function(GeoIpLocation) _then) = _$GeoIpLocationCopyWithImpl;
|
|
||||||
@useResult
|
|
||||||
$Res call({
|
|
||||||
double latitude, double longitude, String countryCode, String country, String city
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class _$GeoIpLocationCopyWithImpl<$Res>
|
|
||||||
implements $GeoIpLocationCopyWith<$Res> {
|
|
||||||
_$GeoIpLocationCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final GeoIpLocation _self;
|
|
||||||
final $Res Function(GeoIpLocation) _then;
|
|
||||||
|
|
||||||
/// Create a copy of GeoIpLocation
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? latitude = null,Object? longitude = null,Object? countryCode = null,Object? country = null,Object? city = null,}) {
|
|
||||||
return _then(_self.copyWith(
|
|
||||||
latitude: null == latitude ? _self.latitude : latitude // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double,longitude: null == longitude ? _self.longitude : longitude // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Adds pattern-matching-related methods to [GeoIpLocation].
|
|
||||||
extension GeoIpLocationPatterns on GeoIpLocation {
|
|
||||||
/// A variant of `map` that fallback to returning `orElse`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _GeoIpLocation value)? $default,{required TResult orElse(),}){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoIpLocation() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// Callbacks receives the raw object, upcasted.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case final Subclass2 value:
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _GeoIpLocation value) $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoIpLocation():
|
|
||||||
return $default(_that);}
|
|
||||||
}
|
|
||||||
/// A variant of `map` that fallback to returning `null`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _GeoIpLocation value)? $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoIpLocation() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to an `orElse` callback.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( double latitude, double longitude, String countryCode, String country, String city)? $default,{required TResult orElse(),}) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoIpLocation() when $default != null:
|
|
||||||
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// As opposed to `map`, this offers destructuring.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case Subclass2(:final field2):
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( double latitude, double longitude, String countryCode, String country, String city) $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoIpLocation():
|
|
||||||
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to returning `null`
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( double latitude, double longitude, String countryCode, String country, String city)? $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _GeoIpLocation() when $default != null:
|
|
||||||
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
@JsonSerializable()
|
|
||||||
|
|
||||||
class _GeoIpLocation implements GeoIpLocation {
|
|
||||||
const _GeoIpLocation({required this.latitude, required this.longitude, required this.countryCode, required this.country, required this.city});
|
|
||||||
factory _GeoIpLocation.fromJson(Map<String, dynamic> json) => _$GeoIpLocationFromJson(json);
|
|
||||||
|
|
||||||
@override final double latitude;
|
|
||||||
@override final double longitude;
|
|
||||||
@override final String countryCode;
|
|
||||||
@override final String country;
|
|
||||||
@override final String city;
|
|
||||||
|
|
||||||
/// Create a copy of GeoIpLocation
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$GeoIpLocationCopyWith<_GeoIpLocation> get copyWith => __$GeoIpLocationCopyWithImpl<_GeoIpLocation>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return _$GeoIpLocationToJson(this, );
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GeoIpLocation&&(identical(other.latitude, latitude) || other.latitude == latitude)&&(identical(other.longitude, longitude) || other.longitude == longitude)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.country, country) || other.country == country)&&(identical(other.city, city) || other.city == city));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,latitude,longitude,countryCode,country,city);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'GeoIpLocation(latitude: $latitude, longitude: $longitude, countryCode: $countryCode, country: $country, city: $city)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class _$GeoIpLocationCopyWith<$Res> implements $GeoIpLocationCopyWith<$Res> {
|
|
||||||
factory _$GeoIpLocationCopyWith(_GeoIpLocation value, $Res Function(_GeoIpLocation) _then) = __$GeoIpLocationCopyWithImpl;
|
|
||||||
@override @useResult
|
|
||||||
$Res call({
|
|
||||||
double latitude, double longitude, String countryCode, String country, String city
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class __$GeoIpLocationCopyWithImpl<$Res>
|
|
||||||
implements _$GeoIpLocationCopyWith<$Res> {
|
|
||||||
__$GeoIpLocationCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final _GeoIpLocation _self;
|
|
||||||
final $Res Function(_GeoIpLocation) _then;
|
|
||||||
|
|
||||||
/// Create a copy of GeoIpLocation
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? latitude = null,Object? longitude = null,Object? countryCode = null,Object? country = null,Object? city = null,}) {
|
|
||||||
return _then(_GeoIpLocation(
|
|
||||||
latitude: null == latitude ? _self.latitude : latitude // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double,longitude: null == longitude ? _self.longitude : longitude // ignore: cast_nullable_to_non_nullable
|
|
||||||
as double,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,country: null == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,city: null == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAuthChallenge {
|
mixin _$SnAuthChallenge {
|
||||||
|
|
||||||
String get id; DateTime get expiredAt; int get stepRemain; int get stepTotal; int get failedAttempts; int get type; List<String> get blacklistFactors; List<dynamic> get audiences; List<dynamic> get scopes; String get ipAddress; String get userAgent; String? get nonce; GeoIpLocation? get location; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; DateTime get expiredAt; int get stepRemain; int get stepTotal; int get failedAttempts; int get type; List<String> get blacklistFactors; List<dynamic> get audiences; List<dynamic> get scopes; String get ipAddress; String get userAgent; String? get nonce; String? get location; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnAuthChallenge
|
/// Create a copy of SnAuthChallenge
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -574,11 +305,11 @@ abstract mixin class $SnAuthChallengeCopyWith<$Res> {
|
|||||||
factory $SnAuthChallengeCopyWith(SnAuthChallenge value, $Res Function(SnAuthChallenge) _then) = _$SnAuthChallengeCopyWithImpl;
|
factory $SnAuthChallengeCopyWith(SnAuthChallenge value, $Res Function(SnAuthChallenge) _then) = _$SnAuthChallengeCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$GeoIpLocationCopyWith<$Res>? get location;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -606,26 +337,14 @@ as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // i
|
|||||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
as GeoIpLocation?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnAuthChallenge
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$GeoIpLocationCopyWith<$Res>? get location {
|
|
||||||
if (_self.location == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $GeoIpLocationCopyWith<$Res>(_self.location!, (value) {
|
|
||||||
return _then(_self.copyWith(location: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -704,7 +423,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthChallenge() when $default != null:
|
case _SnAuthChallenge() when $default != null:
|
||||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
@@ -725,7 +444,7 @@ return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthChallenge():
|
case _SnAuthChallenge():
|
||||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||||
@@ -742,7 +461,7 @@ return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthChallenge() when $default != null:
|
case _SnAuthChallenge() when $default != null:
|
||||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
@@ -790,7 +509,7 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
|||||||
@override final String ipAddress;
|
@override final String ipAddress;
|
||||||
@override final String userAgent;
|
@override final String userAgent;
|
||||||
@override final String? nonce;
|
@override final String? nonce;
|
||||||
@override final GeoIpLocation? location;
|
@override final String? location;
|
||||||
@override final String accountId;
|
@override final String accountId;
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@@ -829,11 +548,11 @@ abstract mixin class _$SnAuthChallengeCopyWith<$Res> implements $SnAuthChallenge
|
|||||||
factory _$SnAuthChallengeCopyWith(_SnAuthChallenge value, $Res Function(_SnAuthChallenge) _then) = __$SnAuthChallengeCopyWithImpl;
|
factory _$SnAuthChallengeCopyWith(_SnAuthChallenge value, $Res Function(_SnAuthChallenge) _then) = __$SnAuthChallengeCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $GeoIpLocationCopyWith<$Res>? get location;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -861,7 +580,7 @@ as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // i
|
|||||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
as GeoIpLocation?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -869,19 +588,7 @@ as DateTime?,
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of SnAuthChallenge
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$GeoIpLocationCopyWith<$Res>? get location {
|
|
||||||
if (_self.location == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $GeoIpLocationCopyWith<$Res>(_self.location!, (value) {
|
|
||||||
return _then(_self.copyWith(location: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -13,24 +13,6 @@ Map<String, dynamic> _$AppTokenToJson(_AppToken instance) => <String, dynamic>{
|
|||||||
'token': instance.token,
|
'token': instance.token,
|
||||||
};
|
};
|
||||||
|
|
||||||
_GeoIpLocation _$GeoIpLocationFromJson(Map<String, dynamic> json) =>
|
|
||||||
_GeoIpLocation(
|
|
||||||
latitude: (json['latitude'] as num).toDouble(),
|
|
||||||
longitude: (json['longitude'] as num).toDouble(),
|
|
||||||
countryCode: json['country_code'] as String,
|
|
||||||
country: json['country'] as String,
|
|
||||||
city: json['city'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$GeoIpLocationToJson(_GeoIpLocation instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'latitude': instance.latitude,
|
|
||||||
'longitude': instance.longitude,
|
|
||||||
'country_code': instance.countryCode,
|
|
||||||
'country': instance.country,
|
|
||||||
'city': instance.city,
|
|
||||||
};
|
|
||||||
|
|
||||||
_SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
_SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||||
_SnAuthChallenge(
|
_SnAuthChallenge(
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
@@ -48,12 +30,7 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
|||||||
ipAddress: json['ip_address'] as String,
|
ipAddress: json['ip_address'] as String,
|
||||||
userAgent: json['user_agent'] as String,
|
userAgent: json['user_agent'] as String,
|
||||||
nonce: json['nonce'] as String?,
|
nonce: json['nonce'] as String?,
|
||||||
location:
|
location: json['location'] as String?,
|
||||||
json['location'] == null
|
|
||||||
? null
|
|
||||||
: GeoIpLocation.fromJson(
|
|
||||||
json['location'] as Map<String, dynamic>,
|
|
||||||
),
|
|
||||||
accountId: json['account_id'] as String,
|
accountId: json['account_id'] as String,
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
@@ -77,7 +54,7 @@ Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
|||||||
'ip_address': instance.ipAddress,
|
'ip_address': instance.ipAddress,
|
||||||
'user_agent': instance.userAgent,
|
'user_agent': instance.userAgent,
|
||||||
'nonce': instance.nonce,
|
'nonce': instance.nonce,
|
||||||
'location': instance.location?.toJson(),
|
'location': instance.location,
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
|
||||||
|
|
||||||
part 'call.g.dart';
|
part 'call.g.dart';
|
||||||
part 'call.freezed.dart';
|
part 'call.freezed.dart';
|
||||||
@@ -55,7 +54,7 @@ sealed class CallParticipantLive with _$CallParticipantLive {
|
|||||||
bool get hasAudio => remoteParticipant.hasAudio;
|
bool get hasAudio => remoteParticipant.hasAudio;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Riverpod(keepAlive: true)
|
@riverpod
|
||||||
class CallNotifier extends _$CallNotifier {
|
class CallNotifier extends _$CallNotifier {
|
||||||
Room? _room;
|
Room? _room;
|
||||||
LocalParticipant? _localParticipant;
|
LocalParticipant? _localParticipant;
|
||||||
@@ -278,27 +277,14 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
|
|
||||||
// Listen for connection updates
|
// Listen for connection updates
|
||||||
_room!.addListener(() {
|
_room!.addListener(() {
|
||||||
final wasConnected = state.isConnected;
|
|
||||||
final isNowConnected =
|
|
||||||
_room!.connectionState == ConnectionState.connected;
|
|
||||||
state = state.copyWith(
|
state = state.copyWith(
|
||||||
isConnected: isNowConnected,
|
isConnected: _room!.connectionState == ConnectionState.connected,
|
||||||
isMicrophoneEnabled: _localParticipant!.isMicrophoneEnabled(),
|
isMicrophoneEnabled: _localParticipant!.isMicrophoneEnabled(),
|
||||||
isCameraEnabled: _localParticipant!.isCameraEnabled(),
|
isCameraEnabled: _localParticipant!.isCameraEnabled(),
|
||||||
isScreenSharing: _localParticipant!.isScreenShareEnabled(),
|
isScreenSharing: _localParticipant!.isScreenShareEnabled(),
|
||||||
);
|
);
|
||||||
// Enable wakelock when call connects
|
|
||||||
if (!wasConnected && isNowConnected) {
|
|
||||||
WakelockPlus.enable();
|
|
||||||
}
|
|
||||||
// Disable wakelock when call disconnects
|
|
||||||
else if (wasConnected && !isNowConnected) {
|
|
||||||
WakelockPlus.disable();
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
state = state.copyWith(isConnected: true);
|
state = state.copyWith(isConnected: true);
|
||||||
// Enable wakelock when call connects
|
|
||||||
WakelockPlus.enable();
|
|
||||||
} else {
|
} else {
|
||||||
state = state.copyWith(error: 'Failed to join room');
|
state = state.copyWith(error: 'Failed to join room');
|
||||||
}
|
}
|
||||||
@@ -358,8 +344,6 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
isCameraEnabled: false,
|
isCameraEnabled: false,
|
||||||
isScreenSharing: false,
|
isScreenSharing: false,
|
||||||
);
|
);
|
||||||
// Disable wakelock when call disconnects
|
|
||||||
WakelockPlus.disable();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -397,7 +381,5 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
_durationTimer?.cancel();
|
_durationTimer?.cancel();
|
||||||
_roomId = null;
|
_roomId = null;
|
||||||
participantsVolumes = {};
|
participantsVolumes = {};
|
||||||
// Disable wakelock when disposing
|
|
||||||
WakelockPlus.disable();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,19 +6,22 @@ part of 'call.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$callNotifierHash() => r'eb9bd41b97e9b5e9d54007c8327edb6567458846';
|
String _$callNotifierHash() => r'18fb807f067eecd3ea42631c1426c3e5f1fb4280';
|
||||||
|
|
||||||
/// See also [CallNotifier].
|
/// See also [CallNotifier].
|
||||||
@ProviderFor(CallNotifier)
|
@ProviderFor(CallNotifier)
|
||||||
final callNotifierProvider = NotifierProvider<CallNotifier, CallState>.internal(
|
final callNotifierProvider =
|
||||||
CallNotifier.new,
|
AutoDisposeNotifierProvider<CallNotifier, CallState>.internal(
|
||||||
name: r'callNotifierProvider',
|
CallNotifier.new,
|
||||||
debugGetCreateSourceHash:
|
name: r'callNotifierProvider',
|
||||||
const bool.fromEnvironment('dart.vm.product') ? null : _$callNotifierHash,
|
debugGetCreateSourceHash:
|
||||||
dependencies: null,
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
allTransitiveDependencies: null,
|
? null
|
||||||
);
|
: _$callNotifierHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
typedef _$CallNotifier = Notifier<CallState>;
|
typedef _$CallNotifier = AutoDisposeNotifier<CallState>;
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ const kAppColorSchemeStoreKey = 'app_color_scheme';
|
|||||||
const kAppNotifyWithHaptic = 'app_notify_with_haptic';
|
const kAppNotifyWithHaptic = 'app_notify_with_haptic';
|
||||||
const kAppCustomFonts = 'app_custom_fonts';
|
const kAppCustomFonts = 'app_custom_fonts';
|
||||||
const kAppAutoTranslate = 'app_auto_translate';
|
const kAppAutoTranslate = 'app_auto_translate';
|
||||||
const kAppDataSavingMode = 'app_data_saving_mode';
|
|
||||||
const kAppSoundEffects = 'app_sound_effects';
|
const kAppSoundEffects = 'app_sound_effects';
|
||||||
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
||||||
const kAppWindowSize = 'app_window_size';
|
const kAppWindowSize = 'app_window_size';
|
||||||
@@ -56,7 +55,6 @@ final serverUrlProvider = Provider<String>((ref) {
|
|||||||
sealed class AppSettings with _$AppSettings {
|
sealed class AppSettings with _$AppSettings {
|
||||||
const factory AppSettings({
|
const factory AppSettings({
|
||||||
required bool autoTranslate,
|
required bool autoTranslate,
|
||||||
required bool dataSavingMode,
|
|
||||||
required bool soundEffects,
|
required bool soundEffects,
|
||||||
required bool aprilFoolFeatures,
|
required bool aprilFoolFeatures,
|
||||||
required bool enterToSend,
|
required bool enterToSend,
|
||||||
@@ -75,7 +73,6 @@ class AppSettingsNotifier extends _$AppSettingsNotifier {
|
|||||||
final prefs = ref.watch(sharedPreferencesProvider);
|
final prefs = ref.watch(sharedPreferencesProvider);
|
||||||
return AppSettings(
|
return AppSettings(
|
||||||
autoTranslate: prefs.getBool(kAppAutoTranslate) ?? false,
|
autoTranslate: prefs.getBool(kAppAutoTranslate) ?? false,
|
||||||
dataSavingMode: prefs.getBool(kAppDataSavingMode) ?? false,
|
|
||||||
soundEffects: prefs.getBool(kAppSoundEffects) ?? true,
|
soundEffects: prefs.getBool(kAppSoundEffects) ?? true,
|
||||||
aprilFoolFeatures: prefs.getBool(kAppAprilFoolFeatures) ?? true,
|
aprilFoolFeatures: prefs.getBool(kAppAprilFoolFeatures) ?? true,
|
||||||
enterToSend: prefs.getBool(kAppEnterToSend) ?? true,
|
enterToSend: prefs.getBool(kAppEnterToSend) ?? true,
|
||||||
@@ -110,12 +107,6 @@ class AppSettingsNotifier extends _$AppSettingsNotifier {
|
|||||||
state = state.copyWith(autoTranslate: value);
|
state = state.copyWith(autoTranslate: value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setDataSavingMode(bool value){
|
|
||||||
final prefs = ref.read(sharedPreferencesProvider);
|
|
||||||
prefs.setBool(kAppDataSavingMode, value);
|
|
||||||
state = state.copyWith(dataSavingMode: value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSoundEffects(bool value) {
|
void setSoundEffects(bool value) {
|
||||||
final prefs = ref.read(sharedPreferencesProvider);
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
prefs.setBool(kAppSoundEffects, value);
|
prefs.setBool(kAppSoundEffects, value);
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$AppSettings {
|
mixin _$AppSettings {
|
||||||
|
|
||||||
bool get autoTranslate; bool get dataSavingMode; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend; bool get appBarTransparent; bool get showBackgroundImage; String? get customFonts; int? get appColorScheme;// The color stored via the int type
|
bool get autoTranslate; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend; bool get appBarTransparent; bool get showBackgroundImage; String? get customFonts; int? get appColorScheme;// The color stored via the int type
|
||||||
Size? get windowSize;
|
Size? get windowSize;
|
||||||
/// Create a copy of AppSettings
|
/// Create a copy of AppSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -26,16 +26,16 @@ $AppSettingsCopyWith<AppSettings> get copyWith => _$AppSettingsCopyWithImpl<AppS
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize);
|
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> {
|
|||||||
factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl;
|
factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize
|
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -63,10 +63,9 @@ class _$AppSettingsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of AppSettings
|
/// Create a copy of AppSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -157,10 +156,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _AppSettings() when $default != null:
|
case _AppSettings() when $default != null:
|
||||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -178,10 +177,10 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _AppSettings():
|
case _AppSettings():
|
||||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);}
|
return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -195,10 +194,10 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _AppSettings() when $default != null:
|
case _AppSettings() when $default != null:
|
||||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -210,11 +209,10 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha
|
|||||||
|
|
||||||
|
|
||||||
class _AppSettings implements AppSettings {
|
class _AppSettings implements AppSettings {
|
||||||
const _AppSettings({required this.autoTranslate, required this.dataSavingMode, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.customFonts, required this.appColorScheme, required this.windowSize});
|
const _AppSettings({required this.autoTranslate, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.customFonts, required this.appColorScheme, required this.windowSize});
|
||||||
|
|
||||||
|
|
||||||
@override final bool autoTranslate;
|
@override final bool autoTranslate;
|
||||||
@override final bool dataSavingMode;
|
|
||||||
@override final bool soundEffects;
|
@override final bool soundEffects;
|
||||||
@override final bool aprilFoolFeatures;
|
@override final bool aprilFoolFeatures;
|
||||||
@override final bool enterToSend;
|
@override final bool enterToSend;
|
||||||
@@ -235,16 +233,16 @@ _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize);
|
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -255,7 +253,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith
|
|||||||
factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl;
|
factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize
|
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -272,10 +270,9 @@ class __$AppSettingsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of AppSettings
|
/// Create a copy of AppSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) {
|
||||||
return _then(_AppSettings(
|
return _then(_AppSettings(
|
||||||
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'config.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$appSettingsNotifierHash() =>
|
String _$appSettingsNotifierHash() =>
|
||||||
r'cd18bff2614a94e3523634e6c577cefad0367eba';
|
r'e3c13307eabb0201487b85ab67b1ab493e588e71';
|
||||||
|
|
||||||
/// See also [AppSettingsNotifier].
|
/// See also [AppSettingsNotifier].
|
||||||
@ProviderFor(AppSettingsNotifier)
|
@ProviderFor(AppSettingsNotifier)
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
const kServerSupportedLanguages = {'en-US': 'en-us', 'zh-CN': 'zh-hans'};
|
const kServerSupportedLanguages = {'en-US': 'en-us', 'zh-CN': 'zh-hans'};
|
||||||
const kServerSupportedRegions = ['US', 'JP', 'CN'];
|
|
||||||
|
|
||||||
class UpdateProfileScreen extends HookConsumerWidget {
|
class UpdateProfileScreen extends HookConsumerWidget {
|
||||||
const UpdateProfileScreen({super.key});
|
const UpdateProfileScreen({super.key});
|
||||||
@@ -98,7 +97,6 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
final usernameController = useTextEditingController(text: user.value!.name);
|
final usernameController = useTextEditingController(text: user.value!.name);
|
||||||
final nicknameController = useTextEditingController(text: user.value!.nick);
|
final nicknameController = useTextEditingController(text: user.value!.nick);
|
||||||
final language = useState(user.value!.language);
|
final language = useState(user.value!.language);
|
||||||
final region = useState(user.value!.region);
|
|
||||||
final links = useState<List<ProfileLink>>(user.value!.profile.links);
|
final links = useState<List<ProfileLink>>(user.value!.profile.links);
|
||||||
|
|
||||||
void updateBasicInfo() async {
|
void updateBasicInfo() async {
|
||||||
@@ -113,7 +111,6 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
'name': usernameController.text,
|
'name': usernameController.text,
|
||||||
'nick': nicknameController.text,
|
'nick': nicknameController.text,
|
||||||
'language': language.value,
|
'language': language.value,
|
||||||
'region': region.value,
|
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||||
@@ -294,32 +291,6 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
DropdownButtonFormField2<String>(
|
|
||||||
decoration: InputDecoration(
|
|
||||||
labelText: 'region'.tr(),
|
|
||||||
helperText: 'accountRegionHint'.tr(),
|
|
||||||
),
|
|
||||||
items: [
|
|
||||||
...kServerSupportedRegions.map(
|
|
||||||
(e) => DropdownMenuItem(value: e, child: Text(e)),
|
|
||||||
),
|
|
||||||
if (!kServerSupportedRegions.contains(region.value))
|
|
||||||
DropdownMenuItem(
|
|
||||||
value: region.value,
|
|
||||||
child: Text(region.value),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
value: region.value,
|
|
||||||
onChanged: (value) {
|
|
||||||
region.value = value ?? region.value;
|
|
||||||
},
|
|
||||||
customButton: Row(
|
|
||||||
children: [
|
|
||||||
Expanded(child: Text(region.value)),
|
|
||||||
Icon(Symbols.arrow_drop_down),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: TextButton.icon(
|
child: TextButton.icon(
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -762,127 +762,5 @@ class _AccountBotDeveloperProviderElement
|
|||||||
String get uname => (origin as AccountBotDeveloperProvider).uname;
|
String get uname => (origin as AccountBotDeveloperProvider).uname;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$accountPublishersHash() => r'25f5695b4a5154163d77f1769876d826bf736609';
|
|
||||||
|
|
||||||
/// See also [accountPublishers].
|
|
||||||
@ProviderFor(accountPublishers)
|
|
||||||
const accountPublishersProvider = AccountPublishersFamily();
|
|
||||||
|
|
||||||
/// See also [accountPublishers].
|
|
||||||
class AccountPublishersFamily extends Family<AsyncValue<List<SnPublisher>>> {
|
|
||||||
/// See also [accountPublishers].
|
|
||||||
const AccountPublishersFamily();
|
|
||||||
|
|
||||||
/// See also [accountPublishers].
|
|
||||||
AccountPublishersProvider call(String id) {
|
|
||||||
return AccountPublishersProvider(id);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
AccountPublishersProvider getProviderOverride(
|
|
||||||
covariant AccountPublishersProvider provider,
|
|
||||||
) {
|
|
||||||
return call(provider.id);
|
|
||||||
}
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
|
||||||
_allTransitiveDependencies;
|
|
||||||
|
|
||||||
@override
|
|
||||||
String? get name => r'accountPublishersProvider';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// See also [accountPublishers].
|
|
||||||
class AccountPublishersProvider
|
|
||||||
extends AutoDisposeFutureProvider<List<SnPublisher>> {
|
|
||||||
/// See also [accountPublishers].
|
|
||||||
AccountPublishersProvider(String id)
|
|
||||||
: this._internal(
|
|
||||||
(ref) => accountPublishers(ref as AccountPublishersRef, id),
|
|
||||||
from: accountPublishersProvider,
|
|
||||||
name: r'accountPublishersProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$accountPublishersHash,
|
|
||||||
dependencies: AccountPublishersFamily._dependencies,
|
|
||||||
allTransitiveDependencies:
|
|
||||||
AccountPublishersFamily._allTransitiveDependencies,
|
|
||||||
id: id,
|
|
||||||
);
|
|
||||||
|
|
||||||
AccountPublishersProvider._internal(
|
|
||||||
super._createNotifier, {
|
|
||||||
required super.name,
|
|
||||||
required super.dependencies,
|
|
||||||
required super.allTransitiveDependencies,
|
|
||||||
required super.debugGetCreateSourceHash,
|
|
||||||
required super.from,
|
|
||||||
required this.id,
|
|
||||||
}) : super.internal();
|
|
||||||
|
|
||||||
final String id;
|
|
||||||
|
|
||||||
@override
|
|
||||||
Override overrideWith(
|
|
||||||
FutureOr<List<SnPublisher>> Function(AccountPublishersRef provider) create,
|
|
||||||
) {
|
|
||||||
return ProviderOverride(
|
|
||||||
origin: this,
|
|
||||||
override: AccountPublishersProvider._internal(
|
|
||||||
(ref) => create(ref as AccountPublishersRef),
|
|
||||||
from: from,
|
|
||||||
name: null,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
debugGetCreateSourceHash: null,
|
|
||||||
id: id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
AutoDisposeFutureProviderElement<List<SnPublisher>> createElement() {
|
|
||||||
return _AccountPublishersProviderElement(this);
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return other is AccountPublishersProvider && other.id == id;
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
int get hashCode {
|
|
||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
|
||||||
hash = _SystemHash.combine(hash, id.hashCode);
|
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
mixin AccountPublishersRef on AutoDisposeFutureProviderRef<List<SnPublisher>> {
|
|
||||||
/// The parameter `id` of this provider.
|
|
||||||
String get id;
|
|
||||||
}
|
|
||||||
|
|
||||||
class _AccountPublishersProviderElement
|
|
||||||
extends AutoDisposeFutureProviderElement<List<SnPublisher>>
|
|
||||||
with AccountPublishersRef {
|
|
||||||
_AccountPublishersProviderElement(super.provider);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String get id => (origin as AccountPublishersProvider).id;
|
|
||||||
}
|
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'explore.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$activityListNotifierHash() =>
|
String _$activityListNotifierHash() =>
|
||||||
r'167021cada54da7c8d8437eef1ffb387a92ea2e3';
|
r'a4968856ac34b59d47cfd4a7cbb39289aef2a1b1';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|||||||
@@ -1,26 +1,15 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/screens/posts/compose.dart';
|
|
||||||
import 'package:island/widgets/alert.dart';
|
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/extended_refresh_indicator.dart';
|
|
||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
import 'package:island/widgets/post/post_pin_sheet.dart';
|
|
||||||
import 'package:island/widgets/post/post_quick_reply.dart';
|
import 'package:island/widgets/post/post_quick_reply.dart';
|
||||||
import 'package:island/widgets/post/post_replies.dart';
|
import 'package:island/widgets/post/post_replies.dart';
|
||||||
import 'package:island/widgets/response.dart';
|
import 'package:island/widgets/response.dart';
|
||||||
import 'package:island/utils/share_utils.dart';
|
|
||||||
import 'package:island/widgets/safety/abuse_report_helper.dart';
|
|
||||||
import 'package:island/widgets/share/share_sheet.dart';
|
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
@@ -57,321 +46,6 @@ class PostState extends StateNotifier<AsyncValue<SnPost?>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostActionButtons extends HookConsumerWidget {
|
|
||||||
final SnPost post;
|
|
||||||
final EdgeInsets renderingPadding;
|
|
||||||
final VoidCallback? onRefresh;
|
|
||||||
final Function(SnPost)? onUpdate;
|
|
||||||
|
|
||||||
const PostActionButtons({
|
|
||||||
super.key,
|
|
||||||
required this.post,
|
|
||||||
this.renderingPadding = EdgeInsets.zero,
|
|
||||||
this.onRefresh,
|
|
||||||
this.onUpdate,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final user = ref.watch(userInfoProvider);
|
|
||||||
final isAuthor =
|
|
||||||
user.value != null && user.value?.id == post.publisher.accountId;
|
|
||||||
|
|
||||||
final actions = <Widget>[];
|
|
||||||
|
|
||||||
const kButtonHeight = 40.0;
|
|
||||||
const kButtonRadius = 20.0;
|
|
||||||
|
|
||||||
// 1. Author-only actions first
|
|
||||||
if (isAuthor) {
|
|
||||||
// Combined edit/delete actions using custom segmented-style buttons
|
|
||||||
final editButtons = <Widget>[
|
|
||||||
FilledButton.tonal(
|
|
||||||
onPressed: () {
|
|
||||||
context.pushNamed('postEdit', pathParameters: {'id': post.id}).then(
|
|
||||||
(value) {
|
|
||||||
if (value != null) {
|
|
||||||
onRefresh?.call();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(kButtonRadius),
|
|
||||||
bottomLeft: Radius.circular(kButtonRadius),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.edit, size: 18),
|
|
||||||
const Gap(4),
|
|
||||||
Text('edit'.tr()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Tooltip(
|
|
||||||
message: 'delete'.tr(),
|
|
||||||
child: FilledButton.tonal(
|
|
||||||
onPressed: () {
|
|
||||||
showConfirmAlert('deletePostHint'.tr(), 'deletePost'.tr()).then((
|
|
||||||
confirm,
|
|
||||||
) {
|
|
||||||
if (confirm) {
|
|
||||||
final client = ref.watch(apiClientProvider);
|
|
||||||
client
|
|
||||||
.delete('/sphere/posts/${post.id}')
|
|
||||||
.catchError((err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
return err;
|
|
||||||
})
|
|
||||||
.then((_) {
|
|
||||||
onRefresh?.call();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topRight: Radius.circular(kButtonRadius),
|
|
||||||
bottomRight: Radius.circular(kButtonRadius),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: const Icon(Symbols.delete, size: 18),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
actions.add(
|
|
||||||
Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children:
|
|
||||||
editButtons
|
|
||||||
.map((e) => SizedBox(height: kButtonHeight, child: e))
|
|
||||||
.expand((widget) => [widget, const VerticalDivider(width: 1)])
|
|
||||||
.toList()
|
|
||||||
..removeLast(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Pin/Unpin actions (also author-only)
|
|
||||||
if (post.pinMode == null) {
|
|
||||||
actions.add(
|
|
||||||
FilledButton.tonalIcon(
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder: (context) => PostPinSheet(post: post),
|
|
||||||
).then((value) {
|
|
||||||
if (value is int) {
|
|
||||||
onUpdate?.call(post.copyWith(pinMode: value));
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.keep),
|
|
||||||
label: Text('pinPost'.tr()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
actions.add(
|
|
||||||
FilledButton.tonalIcon(
|
|
||||||
onPressed: () {
|
|
||||||
showConfirmAlert('unpinPostHint'.tr(), 'unpinPost'.tr()).then((
|
|
||||||
confirm,
|
|
||||||
) async {
|
|
||||||
if (confirm) {
|
|
||||||
final client = ref.watch(apiClientProvider);
|
|
||||||
try {
|
|
||||||
if (context.mounted) showLoadingModal(context);
|
|
||||||
await client.delete('/sphere/posts/${post.id}/pin');
|
|
||||||
onUpdate?.call(post.copyWith(pinMode: null));
|
|
||||||
} catch (err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
} finally {
|
|
||||||
if (context.mounted) hideLoadingModal(context);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.keep_off),
|
|
||||||
label: Text('unpinPost'.tr()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 2. Replies and forwards
|
|
||||||
final replyButtons = <Widget>[
|
|
||||||
FilledButton.tonal(
|
|
||||||
onPressed: () {
|
|
||||||
context.pushNamed(
|
|
||||||
'postCompose',
|
|
||||||
extra: PostComposeInitialState(replyingTo: post),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(kButtonRadius),
|
|
||||||
bottomLeft: Radius.circular(kButtonRadius),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.reply, size: 18),
|
|
||||||
const Gap(4),
|
|
||||||
Text('reply'.tr()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Tooltip(
|
|
||||||
message: 'forward'.tr(),
|
|
||||||
child: FilledButton.tonal(
|
|
||||||
onPressed: () {
|
|
||||||
context.pushNamed(
|
|
||||||
'postCompose',
|
|
||||||
extra: PostComposeInitialState(forwardingTo: post),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topRight: Radius.circular(kButtonRadius),
|
|
||||||
bottomRight: Radius.circular(kButtonRadius),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: const Icon(Symbols.forward, size: 18),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
actions.add(
|
|
||||||
Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children:
|
|
||||||
replyButtons
|
|
||||||
.map((e) => SizedBox(height: kButtonHeight, child: e))
|
|
||||||
.toList(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// 3. Share, copy link, and report
|
|
||||||
final shareButtons = <Widget>[
|
|
||||||
FilledButton.tonal(
|
|
||||||
onPressed: () {
|
|
||||||
showShareSheetLink(
|
|
||||||
context: context,
|
|
||||||
link: 'https://solian.app/posts/${post.id}',
|
|
||||||
title: 'sharePost'.tr(),
|
|
||||||
toSystem: true,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topLeft: Radius.circular(kButtonRadius),
|
|
||||||
bottomLeft: Radius.circular(kButtonRadius),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.share, size: 18),
|
|
||||||
const Gap(4),
|
|
||||||
Text('share'.tr()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
|
||||||
|
|
||||||
if (!kIsWeb) {
|
|
||||||
shareButtons.add(
|
|
||||||
Tooltip(
|
|
||||||
message: 'sharePostPhoto'.tr(),
|
|
||||||
child: FilledButton.tonal(
|
|
||||||
onPressed: () => sharePostAsScreenshot(context, ref, post),
|
|
||||||
style: FilledButton.styleFrom(
|
|
||||||
shape: const RoundedRectangleBorder(
|
|
||||||
borderRadius: BorderRadius.only(
|
|
||||||
topRight: Radius.circular(kButtonRadius),
|
|
||||||
bottomRight: Radius.circular(kButtonRadius),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
child: const Icon(Symbols.share_reviews, size: 18),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
actions.add(
|
|
||||||
Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children:
|
|
||||||
shareButtons
|
|
||||||
.map((e) => SizedBox(height: kButtonHeight, child: e))
|
|
||||||
.expand((widget) => [widget, const VerticalDivider(width: 1)])
|
|
||||||
.toList()
|
|
||||||
..removeLast(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
actions.add(
|
|
||||||
FilledButton.tonalIcon(
|
|
||||||
onPressed: () {
|
|
||||||
Clipboard.setData(
|
|
||||||
ClipboardData(text: 'https://solian.app/posts/${post.id}'),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.link),
|
|
||||||
label: Text('copyLink'.tr()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
actions.add(
|
|
||||||
FilledButton.tonalIcon(
|
|
||||||
onPressed: () {
|
|
||||||
showAbuseReportSheet(context, resourceIdentifier: 'post/${post.id}');
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.flag),
|
|
||||||
label: Text('abuseReport'.tr()),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Add gaps between actions (excluding first one) using FP style
|
|
||||||
final children =
|
|
||||||
actions.asMap().entries.expand((entry) {
|
|
||||||
final index = entry.key;
|
|
||||||
final action = entry.value;
|
|
||||||
if (index == 0) {
|
|
||||||
return [action];
|
|
||||||
} else {
|
|
||||||
return [const Gap(8), action];
|
|
||||||
}
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
return Container(
|
|
||||||
height: kButtonHeight,
|
|
||||||
margin: const EdgeInsets.only(bottom: 12),
|
|
||||||
child: ListView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: renderingPadding.horizontal),
|
|
||||||
children: children,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class PostDetailScreen extends HookConsumerWidget {
|
class PostDetailScreen extends HookConsumerWidget {
|
||||||
final String id;
|
final String id;
|
||||||
const PostDetailScreen({super.key, required this.id});
|
const PostDetailScreen({super.key, required this.id});
|
||||||
@@ -392,58 +66,29 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
return Stack(
|
return Stack(
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [
|
||||||
ExtendedRefreshIndicator(
|
CustomScrollView(
|
||||||
onRefresh: () async {
|
slivers: [
|
||||||
ref.invalidate(postProvider(id));
|
SliverToBoxAdapter(
|
||||||
ref.invalidate(postRepliesNotifierProvider(id));
|
child: Center(
|
||||||
},
|
child: ConstrainedBox(
|
||||||
child: CustomScrollView(
|
constraints: BoxConstraints(maxWidth: 600),
|
||||||
physics: const AlwaysScrollableScrollPhysics(),
|
child: PostItem(
|
||||||
slivers: [
|
item: post!,
|
||||||
SliverToBoxAdapter(
|
isFullPost: true,
|
||||||
child: Center(
|
isEmbedReply: false,
|
||||||
child: ConstrainedBox(
|
onUpdate: (newItem) {
|
||||||
constraints: BoxConstraints(maxWidth: 600),
|
// Update the local state with the new post data
|
||||||
child: PostItem(
|
ref
|
||||||
item: post!,
|
.read(postStateProvider(id).notifier)
|
||||||
isFullPost: true,
|
.updatePost(newItem);
|
||||||
isEmbedReply: false,
|
},
|
||||||
onUpdate: (newItem) {
|
|
||||||
// Update the local state with the new post data
|
|
||||||
ref
|
|
||||||
.read(postStateProvider(id).notifier)
|
|
||||||
.updatePost(newItem);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
),
|
||||||
child: Center(
|
PostRepliesList(postId: id, maxWidth: 600),
|
||||||
child: ConstrainedBox(
|
SliverGap(MediaQuery.of(context).padding.bottom + 80),
|
||||||
constraints: BoxConstraints(maxWidth: 600),
|
],
|
||||||
child: PostActionButtons(
|
|
||||||
post: post,
|
|
||||||
renderingPadding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 8,
|
|
||||||
),
|
|
||||||
onRefresh: () {
|
|
||||||
ref.invalidate(postProvider(id));
|
|
||||||
ref.invalidate(postRepliesNotifierProvider(id));
|
|
||||||
},
|
|
||||||
onUpdate: (newItem) {
|
|
||||||
ref
|
|
||||||
.read(postStateProvider(id).notifier)
|
|
||||||
.updatePost(newItem);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
PostRepliesList(postId: id, maxWidth: 600),
|
|
||||||
SliverGap(MediaQuery.of(context).padding.bottom + 80),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (user.value != null)
|
if (user.value != null)
|
||||||
Positioned(
|
Positioned(
|
||||||
@@ -481,7 +126,7 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
error:
|
error:
|
||||||
(e, _) => ResponseErrorWidget(
|
(e, _) => ResponseErrorWidget(
|
||||||
error: e,
|
error: e,
|
||||||
onRetry: () => ref.invalidate(postProvider(id)),
|
onRetry: () => ref.invalidate(postStateProvider(id)),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,224 +27,6 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
|
|
||||||
part 'pub_profile.g.dart';
|
part 'pub_profile.g.dart';
|
||||||
|
|
||||||
class _PublisherBasisWidget extends StatelessWidget {
|
|
||||||
final SnPublisher data;
|
|
||||||
final AsyncValue<SnSubscriptionStatus> subStatus;
|
|
||||||
final ValueNotifier<bool> subscribing;
|
|
||||||
final VoidCallback subscribe;
|
|
||||||
final VoidCallback unsubscribe;
|
|
||||||
|
|
||||||
const _PublisherBasisWidget({
|
|
||||||
required this.data,
|
|
||||||
required this.subStatus,
|
|
||||||
required this.subscribing,
|
|
||||||
required this.subscribe,
|
|
||||||
required this.unsubscribe,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
spacing: 20,
|
|
||||||
children: [
|
|
||||||
GestureDetector(
|
|
||||||
child: Badge(
|
|
||||||
isLabelVisible: data.type == 0,
|
|
||||||
padding: EdgeInsets.all(4),
|
|
||||||
label: Icon(
|
|
||||||
Symbols.launch,
|
|
||||||
size: 16,
|
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
|
||||||
),
|
|
||||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
|
||||||
offset: Offset(0, 48),
|
|
||||||
child: ProfilePictureWidget(
|
|
||||||
file: data.picture,
|
|
||||||
radius: 32,
|
|
||||||
borderRadius: data.type == 0 ? null : 12,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
if (data.account?.name != null) {
|
|
||||||
Navigator.pop(context, true);
|
|
||||||
context.pushNamed(
|
|
||||||
'accountProfile',
|
|
||||||
pathParameters: {'name': data.account!.name},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
spacing: 6,
|
|
||||||
children: [
|
|
||||||
Text(data.nick).fontSize(20),
|
|
||||||
if (data.verification != null)
|
|
||||||
VerificationMark(mark: data.verification!),
|
|
||||||
Expanded(
|
|
||||||
child: Text(
|
|
||||||
'@${data.name}',
|
|
||||||
maxLines: 1,
|
|
||||||
overflow: TextOverflow.ellipsis,
|
|
||||||
).fontSize(14).opacity(0.85),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (data.type == 0 && data.account != null)
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
spacing: 6,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
data.type == 0 ? Symbols.person : Symbols.workspaces,
|
|
||||||
fill: 1,
|
|
||||||
size: 17,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'publisherBelongsTo'.tr(args: ['@${data.account!.name}']),
|
|
||||||
).fontSize(14),
|
|
||||||
],
|
|
||||||
).opacity(0.85),
|
|
||||||
const Gap(4),
|
|
||||||
if (data.type == 0 && data.account != null)
|
|
||||||
AccountStatusWidget(
|
|
||||||
uname: data.account!.name,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
),
|
|
||||||
subStatus
|
|
||||||
.when(
|
|
||||||
data:
|
|
||||||
(status) => FilledButton.icon(
|
|
||||||
onPressed:
|
|
||||||
subscribing.value
|
|
||||||
? null
|
|
||||||
: (status.isSubscribed
|
|
||||||
? unsubscribe
|
|
||||||
: subscribe),
|
|
||||||
icon: Icon(
|
|
||||||
status.isSubscribed
|
|
||||||
? Symbols.remove_circle
|
|
||||||
: Symbols.add_circle,
|
|
||||||
),
|
|
||||||
label:
|
|
||||||
Text(
|
|
||||||
status.isSubscribed
|
|
||||||
? 'unsubscribe'
|
|
||||||
: 'subscribe',
|
|
||||||
).tr(),
|
|
||||||
style: ButtonStyle(
|
|
||||||
visualDensity: VisualDensity(vertical: -2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
error: (_, _) => const SizedBox(),
|
|
||||||
loading:
|
|
||||||
() => const SizedBox(
|
|
||||||
height: 36,
|
|
||||||
child: Center(
|
|
||||||
child: SizedBox(
|
|
||||||
width: 20,
|
|
||||||
height: 20,
|
|
||||||
child: CircularProgressIndicator(strokeWidth: 2),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.padding(top: 8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 24, top: 24);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PublisherBadgesWidget extends StatelessWidget {
|
|
||||||
final SnPublisher data;
|
|
||||||
final AsyncValue<List<SnAccountBadge>> badges;
|
|
||||||
|
|
||||||
const _PublisherBadgesWidget({required this.data, required this.badges});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return (badges.value?.isNotEmpty ?? false)
|
|
||||||
? Card(
|
|
||||||
child: BadgeList(
|
|
||||||
badges: badges.value!,
|
|
||||||
).padding(horizontal: 26, vertical: 20),
|
|
||||||
).padding(horizontal: 4)
|
|
||||||
: const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PublisherVerificationWidget extends StatelessWidget {
|
|
||||||
final SnPublisher data;
|
|
||||||
|
|
||||||
const _PublisherVerificationWidget({required this.data});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return (data.verification != null)
|
|
||||||
? Card(
|
|
||||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
child: VerificationStatusCard(mark: data.verification!),
|
|
||||||
)
|
|
||||||
: const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PublisherBioWidget extends StatelessWidget {
|
|
||||||
final SnPublisher data;
|
|
||||||
|
|
||||||
const _PublisherBioWidget({required this.data});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Card(
|
|
||||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text('bio').tr().bold().fontSize(15).padding(bottom: 8),
|
|
||||||
if (data.bio.isEmpty)
|
|
||||||
Text('descriptionNone').tr().italic()
|
|
||||||
else
|
|
||||||
MarkdownTextContent(
|
|
||||||
content: data.bio,
|
|
||||||
linesMargin: EdgeInsets.zero,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 20, vertical: 16),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _PublisherCategoryTabWidget extends StatelessWidget {
|
|
||||||
final TabController categoryTabController;
|
|
||||||
|
|
||||||
const _PublisherCategoryTabWidget({required this.categoryTabController});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Card(
|
|
||||||
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
child: TabBar(
|
|
||||||
controller: categoryTabController,
|
|
||||||
dividerColor: Colors.transparent,
|
|
||||||
splashBorderRadius: const BorderRadius.all(Radius.circular(8)),
|
|
||||||
tabs: [
|
|
||||||
Tab(text: 'all'.tr()),
|
|
||||||
Tab(text: 'postTypePost'.tr()),
|
|
||||||
Tab(text: 'postArticle'.tr()),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<SnPublisher> publisher(Ref ref, String uname) async {
|
Future<SnPublisher> publisher(Ref ref, String uname) async {
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
@@ -350,6 +132,170 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
offset: Offset(1.0, 1.0),
|
offset: Offset(1.0, 1.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Widget publisherBasisWidget(SnPublisher data) => Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
spacing: 20,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
child: Badge(
|
||||||
|
isLabelVisible: data.type == 0,
|
||||||
|
padding: EdgeInsets.all(4),
|
||||||
|
label: Icon(
|
||||||
|
Symbols.launch,
|
||||||
|
size: 16,
|
||||||
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
|
),
|
||||||
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
|
offset: Offset(0, 48),
|
||||||
|
child: ProfilePictureWidget(
|
||||||
|
file: data.picture,
|
||||||
|
radius: 32,
|
||||||
|
borderRadius: data.type == 0 ? null : 12,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Navigator.pop(context, true);
|
||||||
|
if (data.account?.name != null) {
|
||||||
|
context.pushNamed(
|
||||||
|
'accountProfile',
|
||||||
|
pathParameters: {'name': data.account!.name},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Text(data.nick).fontSize(20),
|
||||||
|
if (data.verification != null)
|
||||||
|
VerificationMark(mark: data.verification!),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'@${data.name}',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).fontSize(14).opacity(0.85),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (data.type == 0 && data.account != null)
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
data.type == 0 ? Symbols.person : Symbols.workspaces,
|
||||||
|
fill: 1,
|
||||||
|
size: 17,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'publisherBelongsTo'.tr(args: ['@${data.account!.name}']),
|
||||||
|
).fontSize(14),
|
||||||
|
],
|
||||||
|
).opacity(0.85),
|
||||||
|
const Gap(4),
|
||||||
|
if (data.type == 0 && data.account != null)
|
||||||
|
AccountStatusWidget(
|
||||||
|
uname: data.account!.name,
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
subStatus
|
||||||
|
.when(
|
||||||
|
data:
|
||||||
|
(status) => FilledButton.icon(
|
||||||
|
onPressed:
|
||||||
|
subscribing.value
|
||||||
|
? null
|
||||||
|
: (status.isSubscribed
|
||||||
|
? unsubscribe
|
||||||
|
: subscribe),
|
||||||
|
icon: Icon(
|
||||||
|
status.isSubscribed
|
||||||
|
? Symbols.remove_circle
|
||||||
|
: Symbols.add_circle,
|
||||||
|
),
|
||||||
|
label:
|
||||||
|
Text(
|
||||||
|
status.isSubscribed
|
||||||
|
? 'unsubscribe'
|
||||||
|
: 'subscribe',
|
||||||
|
).tr(),
|
||||||
|
style: ButtonStyle(
|
||||||
|
visualDensity: VisualDensity(vertical: -2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
error: (_, _) => const SizedBox(),
|
||||||
|
loading:
|
||||||
|
() => const SizedBox(
|
||||||
|
height: 36,
|
||||||
|
child: Center(
|
||||||
|
child: SizedBox(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.padding(top: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24, top: 24);
|
||||||
|
|
||||||
|
Widget publisherBadgesWidget(SnPublisher data) =>
|
||||||
|
(badges.value?.isNotEmpty ?? false)
|
||||||
|
? Card(
|
||||||
|
child: BadgeList(
|
||||||
|
badges: badges.value!,
|
||||||
|
).padding(horizontal: 26, vertical: 20),
|
||||||
|
).padding(horizontal: 4)
|
||||||
|
: const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget publisherVerificationWidget(SnPublisher data) =>
|
||||||
|
(data.verification != null)
|
||||||
|
? Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: VerificationStatusCard(mark: data.verification!),
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink();
|
||||||
|
|
||||||
|
Widget publisherBioWidget(SnPublisher data) => Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text('bio').tr().bold().fontSize(15).padding(bottom: 8),
|
||||||
|
if (data.bio.isEmpty)
|
||||||
|
Text('descriptionNone').tr().italic()
|
||||||
|
else
|
||||||
|
MarkdownTextContent(
|
||||||
|
content: data.bio,
|
||||||
|
linesMargin: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20, vertical: 16),
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget publisherCategoryTabWidget() => Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: TabBar(
|
||||||
|
controller: categoryTabController,
|
||||||
|
dividerColor: Colors.transparent,
|
||||||
|
splashBorderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
tabs: [
|
||||||
|
Tab(text: 'all'.tr()),
|
||||||
|
Tab(text: 'postTypePost'.tr()),
|
||||||
|
Tab(text: 'postArticle'.tr()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
return publisher.when(
|
return publisher.when(
|
||||||
data:
|
data:
|
||||||
(data) => AppScaffold(
|
(data) => AppScaffold(
|
||||||
@@ -405,9 +351,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
SliverGap(16),
|
SliverGap(16),
|
||||||
SliverPostList(pubName: name, pinned: true),
|
SliverPostList(pubName: name, pinned: true),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: _PublisherCategoryTabWidget(
|
child: publisherCategoryTabWidget(),
|
||||||
categoryTabController: categoryTabController,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
SliverPostList(
|
SliverPostList(
|
||||||
key: ValueKey(categoryTab.value),
|
key: ValueKey(categoryTab.value),
|
||||||
@@ -433,19 +377,10 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
_PublisherBasisWidget(
|
publisherBasisWidget(data).padding(bottom: 8),
|
||||||
data: data,
|
publisherBadgesWidget(data),
|
||||||
subStatus: subStatus,
|
publisherVerificationWidget(data),
|
||||||
subscribing: subscribing,
|
publisherBioWidget(data),
|
||||||
subscribe: subscribe,
|
|
||||||
unsubscribe: unsubscribe,
|
|
||||||
).padding(bottom: 8),
|
|
||||||
_PublisherBadgesWidget(
|
|
||||||
data: data,
|
|
||||||
badges: badges,
|
|
||||||
),
|
|
||||||
_PublisherVerificationWidget(data: data),
|
|
||||||
_PublisherBioWidget(data: data),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -497,32 +432,15 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: _PublisherBasisWidget(
|
child: publisherBasisWidget(data).padding(bottom: 8),
|
||||||
data: data,
|
|
||||||
subStatus: subStatus,
|
|
||||||
subscribing: subscribing,
|
|
||||||
subscribe: subscribe,
|
|
||||||
unsubscribe: unsubscribe,
|
|
||||||
).padding(bottom: 8),
|
|
||||||
),
|
),
|
||||||
|
SliverToBoxAdapter(child: publisherBadgesWidget(data)),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: _PublisherBadgesWidget(
|
child: publisherVerificationWidget(data),
|
||||||
data: data,
|
|
||||||
badges: badges,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: _PublisherVerificationWidget(data: data),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: _PublisherBioWidget(data: data),
|
|
||||||
),
|
),
|
||||||
|
SliverToBoxAdapter(child: publisherBioWidget(data)),
|
||||||
SliverPostList(pubName: name, pinned: true),
|
SliverPostList(pubName: name, pinned: true),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(child: publisherCategoryTabWidget()),
|
||||||
child: _PublisherCategoryTabWidget(
|
|
||||||
categoryTabController: categoryTabController,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverPostList(
|
SliverPostList(
|
||||||
key: ValueKey(categoryTab.value),
|
key: ValueKey(categoryTab.value),
|
||||||
pubName: name,
|
pubName: name,
|
||||||
|
|||||||
@@ -450,20 +450,6 @@ class SettingsScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
ListTile(
|
|
||||||
minLeadingWidth: 48,
|
|
||||||
title: Text('settingsDataSavingMode').tr(),
|
|
||||||
contentPadding: const EdgeInsets.only(left: 24, right: 17),
|
|
||||||
leading: const Icon(Symbols.data_saver_on_rounded),
|
|
||||||
trailing: Switch(
|
|
||||||
value: settings.dataSavingMode,
|
|
||||||
onChanged: (value) {
|
|
||||||
ref
|
|
||||||
.read(appSettingsNotifierProvider.notifier)
|
|
||||||
.setDataSavingMode(value);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
];
|
];
|
||||||
|
|
||||||
// Desktop-specific settings
|
// Desktop-specific settings
|
||||||
|
|||||||
@@ -48,11 +48,7 @@ class TrayService {
|
|||||||
void handleAction(MenuItem item) {
|
void handleAction(MenuItem item) {
|
||||||
switch (item.key) {
|
switch (item.key) {
|
||||||
case 'show_window':
|
case 'show_window':
|
||||||
if (appWindow.isVisible) {
|
appWindow.show();
|
||||||
appWindow.restore();
|
|
||||||
} else {
|
|
||||||
appWindow.show();
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'exit_app':
|
case 'exit_app':
|
||||||
appWindow.close();
|
appWindow.close();
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import 'dart:async';
|
|||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:archive/archive.dart';
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -11,9 +10,6 @@ import 'package:flutter_app_update/update_model.dart';
|
|||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:path_provider/path_provider.dart';
|
|
||||||
import 'package:path/path.dart' as path;
|
|
||||||
import 'package:process_run/process_run.dart';
|
|
||||||
import 'package:collection/collection.dart'; // Added for firstWhereOrNull
|
import 'package:collection/collection.dart'; // Added for firstWhereOrNull
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
@@ -184,13 +180,9 @@ class UpdateService {
|
|||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
builder: (ctx) {
|
builder: (ctx) {
|
||||||
String? androidUpdateUrl;
|
String? androidUpdateUrl;
|
||||||
String? windowsUpdateUrl;
|
|
||||||
if (Platform.isAndroid) {
|
if (Platform.isAndroid) {
|
||||||
androidUpdateUrl = _getAndroidUpdateUrl(release.assets);
|
androidUpdateUrl = _getAndroidUpdateUrl(release.assets);
|
||||||
}
|
}
|
||||||
if (Platform.isWindows) {
|
|
||||||
windowsUpdateUrl = _getWindowsUpdateUrl();
|
|
||||||
}
|
|
||||||
return _UpdateSheet(
|
return _UpdateSheet(
|
||||||
release: release,
|
release: release,
|
||||||
onOpen: () async {
|
onOpen: () async {
|
||||||
@@ -200,7 +192,6 @@ class UpdateService {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
androidUpdateUrl: androidUpdateUrl,
|
androidUpdateUrl: androidUpdateUrl,
|
||||||
windowsUpdateUrl: windowsUpdateUrl,
|
|
||||||
useProxy: useProxy, // Pass the useProxy flag
|
useProxy: useProxy, // Pass the useProxy flag
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -220,270 +211,15 @@ class UpdateService {
|
|||||||
|
|
||||||
// Prioritize arm64, then armeabi, then x86_64
|
// Prioritize arm64, then armeabi, then x86_64
|
||||||
if (arm64 != null) {
|
if (arm64 != null) {
|
||||||
return 'https://fs.solsynth.dev/d/official/solian/${arm64.name}';
|
return arm64.browserDownloadUrl;
|
||||||
} else if (armeabi != null) {
|
} else if (armeabi != null) {
|
||||||
return 'https://fs.solsynth.dev/d/official/solian/${armeabi.name}';
|
return armeabi.browserDownloadUrl;
|
||||||
} else if (x86_64 != null) {
|
} else if (x86_64 != null) {
|
||||||
return 'https://fs.solsynth.dev/d/official/solian/${x86_64.name}';
|
return x86_64.browserDownloadUrl;
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _getWindowsUpdateUrl() {
|
|
||||||
return 'https://fs.solsynth.dev/d/official/solian/build-output-windows-installer.zip';
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Downloads the Windows installer ZIP file
|
|
||||||
Future<String?> _downloadWindowsInstaller(String url) async {
|
|
||||||
try {
|
|
||||||
log('[Update] Starting Windows installer download from: $url');
|
|
||||||
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
|
||||||
final fileName =
|
|
||||||
'solian-installer-${DateTime.now().millisecondsSinceEpoch}.zip';
|
|
||||||
final filePath = path.join(tempDir.path, fileName);
|
|
||||||
|
|
||||||
final response = await _dio.download(
|
|
||||||
url,
|
|
||||||
filePath,
|
|
||||||
onReceiveProgress: (received, total) {
|
|
||||||
if (total != -1) {
|
|
||||||
log(
|
|
||||||
'[Update] Download progress: ${(received / total * 100).toStringAsFixed(1)}%',
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
if (response.statusCode == 200) {
|
|
||||||
log('[Update] Windows installer downloaded successfully to: $filePath');
|
|
||||||
return filePath;
|
|
||||||
} else {
|
|
||||||
log(
|
|
||||||
'[Update] Failed to download Windows installer. Status: ${response.statusCode}',
|
|
||||||
);
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log('[Update] Error downloading Windows installer: $e');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Extracts the ZIP file to a temporary directory
|
|
||||||
Future<String?> _extractWindowsInstaller(String zipPath) async {
|
|
||||||
try {
|
|
||||||
log('[Update] Extracting Windows installer from: $zipPath');
|
|
||||||
|
|
||||||
final tempDir = await getTemporaryDirectory();
|
|
||||||
final extractDir = path.join(
|
|
||||||
tempDir.path,
|
|
||||||
'solian-installer-${DateTime.now().millisecondsSinceEpoch}',
|
|
||||||
);
|
|
||||||
|
|
||||||
final zipFile = File(zipPath);
|
|
||||||
final bytes = await zipFile.readAsBytes();
|
|
||||||
final archive = ZipDecoder().decodeBytes(bytes);
|
|
||||||
|
|
||||||
for (final file in archive) {
|
|
||||||
final filename = file.name;
|
|
||||||
if (file.isFile) {
|
|
||||||
final data = file.content as List<int>;
|
|
||||||
final filePath = path.join(extractDir, filename);
|
|
||||||
await Directory(path.dirname(filePath)).create(recursive: true);
|
|
||||||
await File(filePath).writeAsBytes(data);
|
|
||||||
} else {
|
|
||||||
final dirPath = path.join(extractDir, filename);
|
|
||||||
await Directory(dirPath).create(recursive: true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
log('[Update] Windows installer extracted successfully to: $extractDir');
|
|
||||||
return extractDir;
|
|
||||||
} catch (e) {
|
|
||||||
log('[Update] Error extracting Windows installer: $e');
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Runs the setup.exe file
|
|
||||||
Future<bool> _runWindowsInstaller(String extractDir) async {
|
|
||||||
try {
|
|
||||||
log('[Update] Running Windows installer from: $extractDir');
|
|
||||||
|
|
||||||
final setupExePath = path.join(extractDir, 'setup.exe');
|
|
||||||
|
|
||||||
if (!await File(setupExePath).exists()) {
|
|
||||||
log('[Update] setup.exe not found in extracted directory');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
final shell = Shell();
|
|
||||||
final results = await shell.run(setupExePath);
|
|
||||||
final result = results.first;
|
|
||||||
|
|
||||||
if (result.exitCode == 0) {
|
|
||||||
log('[Update] Windows installer completed successfully');
|
|
||||||
return true;
|
|
||||||
} else {
|
|
||||||
log(
|
|
||||||
'[Update] Windows installer failed with exit code: ${result.exitCode}',
|
|
||||||
);
|
|
||||||
log('[Update] Installer output: ${result.stdout}');
|
|
||||||
log('[Update] Installer errors: ${result.stderr}');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
log('[Update] Error running Windows installer: $e');
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Performs automatic Windows update: download, extract, and install
|
|
||||||
Future<void> _performAutomaticWindowsUpdate(
|
|
||||||
BuildContext context,
|
|
||||||
String url,
|
|
||||||
) async {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
|
|
||||||
// Show progress dialog
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder:
|
|
||||||
(context) => const AlertDialog(
|
|
||||||
title: Text('Installing Update'),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
CircularProgressIndicator(),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
Text('Downloading installer...'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Step 1: Download
|
|
||||||
if (!context.mounted) return;
|
|
||||||
Navigator.of(context).pop(); // Close progress dialog
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder:
|
|
||||||
(context) => const AlertDialog(
|
|
||||||
title: Text('Installing Update'),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
CircularProgressIndicator(),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
Text('Extracting installer...'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
final zipPath = await _downloadWindowsInstaller(url);
|
|
||||||
if (zipPath == null) {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
_showErrorDialog(context, 'Failed to download installer');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 2: Extract
|
|
||||||
if (!context.mounted) return;
|
|
||||||
Navigator.of(context).pop(); // Close progress dialog
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
barrierDismissible: false,
|
|
||||||
builder:
|
|
||||||
(context) => const AlertDialog(
|
|
||||||
title: Text('Installing Update'),
|
|
||||||
content: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
CircularProgressIndicator(),
|
|
||||||
SizedBox(height: 16),
|
|
||||||
Text('Running installer...'),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
|
|
||||||
final extractDir = await _extractWindowsInstaller(zipPath);
|
|
||||||
if (extractDir == null) {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
_showErrorDialog(context, 'Failed to extract installer');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Step 3: Run installer
|
|
||||||
if (!context.mounted) return;
|
|
||||||
Navigator.of(context).pop(); // Close progress dialog
|
|
||||||
|
|
||||||
final success = await _runWindowsInstaller(extractDir);
|
|
||||||
if (!context.mounted) return;
|
|
||||||
|
|
||||||
if (success) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => AlertDialog(
|
|
||||||
title: const Text('Update Complete'),
|
|
||||||
content: const Text(
|
|
||||||
'The application has been updated successfully. Please restart the application.',
|
|
||||||
),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
// Close the update sheet
|
|
||||||
Navigator.of(context).pop();
|
|
||||||
},
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
_showErrorDialog(context, 'Failed to run installer');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Cleanup
|
|
||||||
try {
|
|
||||||
await File(zipPath).delete();
|
|
||||||
await Directory(extractDir).delete(recursive: true);
|
|
||||||
} catch (e) {
|
|
||||||
log('[Update] Error cleaning up temporary files: $e');
|
|
||||||
}
|
|
||||||
} catch (e) {
|
|
||||||
if (!context.mounted) return;
|
|
||||||
Navigator.of(context).pop(); // Close any open dialogs
|
|
||||||
_showErrorDialog(context, 'Update failed: $e');
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void _showErrorDialog(BuildContext context, String message) {
|
|
||||||
showDialog(
|
|
||||||
context: context,
|
|
||||||
builder:
|
|
||||||
(context) => AlertDialog(
|
|
||||||
title: const Text('Update Failed'),
|
|
||||||
content: Text(message),
|
|
||||||
actions: [
|
|
||||||
TextButton(
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
|
||||||
child: const Text('OK'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Fetch the latest release info from GitHub.
|
/// Fetch the latest release info from GitHub.
|
||||||
/// Public so other screens (e.g., About) can manually trigger update checks.
|
/// Public so other screens (e.g., About) can manually trigger update checks.
|
||||||
Future<GithubReleaseInfo?> fetchLatestRelease() async {
|
Future<GithubReleaseInfo?> fetchLatestRelease() async {
|
||||||
@@ -541,12 +277,10 @@ class _UpdateSheet extends StatefulWidget {
|
|||||||
required this.release,
|
required this.release,
|
||||||
required this.onOpen,
|
required this.onOpen,
|
||||||
this.androidUpdateUrl,
|
this.androidUpdateUrl,
|
||||||
this.windowsUpdateUrl,
|
|
||||||
this.useProxy = false,
|
this.useProxy = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
final String? androidUpdateUrl;
|
final String? androidUpdateUrl;
|
||||||
final String? windowsUpdateUrl;
|
|
||||||
final bool useProxy;
|
final bool useProxy;
|
||||||
final GithubReleaseInfo release;
|
final GithubReleaseInfo release;
|
||||||
final VoidCallback onOpen;
|
final VoidCallback onOpen;
|
||||||
@@ -565,11 +299,8 @@ class _UpdateSheetState extends State<_UpdateSheet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _installUpdate(String url) async {
|
Future<void> _installUpdate(String url) async {
|
||||||
String downloadUrl = url;
|
final downloadUrl =
|
||||||
if (_useProxy) {
|
_useProxy ? 'https://ghfast.top/${Uri.encodeComponent(url)}' : url;
|
||||||
final fileName = url.split('/').last;
|
|
||||||
downloadUrl = 'https://fs.solsynth.dev/d/rainyun02/solian/$fileName';
|
|
||||||
}
|
|
||||||
|
|
||||||
UpdateModel model = UpdateModel(
|
UpdateModel model = UpdateModel(
|
||||||
downloadUrl,
|
downloadUrl,
|
||||||
@@ -619,7 +350,7 @@ class _UpdateSheetState extends State<_UpdateSheet> {
|
|||||||
),
|
),
|
||||||
if (!kIsWeb && Platform.isAndroid)
|
if (!kIsWeb && Platform.isAndroid)
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: const Text('Use secondary source for download'),
|
title: const Text('Use GitHub Proxy for Download'),
|
||||||
value: _useProxy,
|
value: _useProxy,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -645,25 +376,6 @@ class _UpdateSheetState extends State<_UpdateSheet> {
|
|||||||
label: const Text('Install update'),
|
label: const Text('Install update'),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
if (!kIsWeb &&
|
|
||||||
Platform.isWindows &&
|
|
||||||
widget.windowsUpdateUrl != null)
|
|
||||||
Expanded(
|
|
||||||
child: FilledButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
// Access the UpdateService instance to call the automatic update method
|
|
||||||
final updateService = UpdateService(
|
|
||||||
useProxy: widget.useProxy,
|
|
||||||
);
|
|
||||||
updateService._performAutomaticWindowsUpdate(
|
|
||||||
context,
|
|
||||||
widget.windowsUpdateUrl!,
|
|
||||||
);
|
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.update),
|
|
||||||
label: const Text('Install update'),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FilledButton.icon(
|
child: FilledButton.icon(
|
||||||
onPressed: widget.onOpen,
|
onPressed: widget.onOpen,
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:island/models/post.dart';
|
|
||||||
import 'package:island/pods/config.dart';
|
|
||||||
import 'package:island/widgets/alert.dart';
|
|
||||||
import 'package:island/widgets/post/post_item_screenshot.dart';
|
|
||||||
import 'package:path_provider/path_provider.dart' show getTemporaryDirectory;
|
|
||||||
import 'package:screenshot/screenshot.dart';
|
|
||||||
import 'package:share_plus/share_plus.dart';
|
|
||||||
|
|
||||||
/// Shares a post as a screenshot image
|
|
||||||
Future<void> sharePostAsScreenshot(
|
|
||||||
BuildContext context,
|
|
||||||
WidgetRef ref,
|
|
||||||
SnPost post,
|
|
||||||
) async {
|
|
||||||
if (kIsWeb) return;
|
|
||||||
|
|
||||||
final screenshotController = ScreenshotController();
|
|
||||||
|
|
||||||
showLoadingModal(context);
|
|
||||||
await screenshotController
|
|
||||||
.captureFromWidget(
|
|
||||||
ProviderScope(
|
|
||||||
overrides: [
|
|
||||||
sharedPreferencesProvider.overrideWithValue(
|
|
||||||
ref.watch(sharedPreferencesProvider),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
child: Directionality(
|
|
||||||
textDirection: TextDirection.ltr,
|
|
||||||
child: SizedBox(
|
|
||||||
width: 520,
|
|
||||||
child: PostItemScreenshot(item: post, isFullPost: true),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
context: context,
|
|
||||||
pixelRatio: MediaQuery.of(context).devicePixelRatio,
|
|
||||||
delay: const Duration(seconds: 1),
|
|
||||||
)
|
|
||||||
.then((Uint8List? image) async {
|
|
||||||
if (image == null) return;
|
|
||||||
final directory = await getTemporaryDirectory();
|
|
||||||
final imagePath = await File('${directory.path}/image.png').create();
|
|
||||||
await imagePath.writeAsBytes(image);
|
|
||||||
|
|
||||||
if (!context.mounted) return;
|
|
||||||
hideLoadingModal(context);
|
|
||||||
final box = context.findRenderObject() as RenderBox?;
|
|
||||||
await Share.shareXFiles([
|
|
||||||
XFile(imagePath.path),
|
|
||||||
], sharePositionOrigin: box!.localToGlobal(Offset.zero) & box.size);
|
|
||||||
})
|
|
||||||
.catchError((err) {
|
|
||||||
if (context.mounted) hideLoadingModal(context);
|
|
||||||
showErrorAlert(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -46,10 +46,6 @@ class EventDetailsWidget extends StatelessWidget {
|
|||||||
size: 12,
|
size: 12,
|
||||||
fill: 1,
|
fill: 1,
|
||||||
).padding(top: 4, right: 4),
|
).padding(top: 4, right: 4),
|
||||||
Icon(
|
|
||||||
tip.isPositive ? Symbols.thumb_up : Symbols.thumb_down,
|
|
||||||
size: 14,
|
|
||||||
).padding(top: 2.5),
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'dart:ui';
|
|
||||||
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@@ -16,15 +15,6 @@ import 'package:material_symbols_icons/material_symbols_icons.dart';
|
|||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
class AppScrollBehavior extends MaterialScrollBehavior {
|
|
||||||
@override
|
|
||||||
Set<PointerDeviceKind> get dragDevices => {
|
|
||||||
PointerDeviceKind.touch, // default
|
|
||||||
PointerDeviceKind.trackpad, // default
|
|
||||||
PointerDeviceKind.mouse, // add mouse dragging
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
class WindowScaffold extends HookConsumerWidget {
|
class WindowScaffold extends HookConsumerWidget {
|
||||||
final Widget child;
|
final Widget child;
|
||||||
const WindowScaffold({super.key, required this.child});
|
const WindowScaffold({super.key, required this.child});
|
||||||
|
|||||||
@@ -63,11 +63,7 @@ class AppWrapper extends HookConsumerWidget with TrayListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _trayIconPrimaryAction() {
|
void _trayIconPrimaryAction() {
|
||||||
if (appWindow.isVisible) {
|
appWindow.show();
|
||||||
appWindow.restore();
|
|
||||||
} else {
|
|
||||||
appWindow.show();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _trayIconSecondaryAction() {
|
void _trayIconSecondaryAction() {
|
||||||
|
|||||||
@@ -3,7 +3,6 @@ import 'dart:convert';
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@@ -15,7 +14,6 @@ import 'package:island/widgets/alert.dart';
|
|||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:slide_countdown/slide_countdown.dart';
|
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
part 'check_in.g.dart';
|
part 'check_in.g.dart';
|
||||||
@@ -36,17 +34,6 @@ Future<SnCheckInResult?> checkInResultToday(Ref ref) async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
|
||||||
Future<SnNotableDay?> nextNotableDay(Ref ref) async {
|
|
||||||
final client = ref.watch(apiClientProvider);
|
|
||||||
try {
|
|
||||||
final resp = await client.get('/id/notable/me/next');
|
|
||||||
return SnNotableDay.fromJson(resp.data);
|
|
||||||
} catch (err) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class CheckInWidget extends HookConsumerWidget {
|
class CheckInWidget extends HookConsumerWidget {
|
||||||
final EdgeInsets? margin;
|
final EdgeInsets? margin;
|
||||||
final VoidCallback? onChecked;
|
final VoidCallback? onChecked;
|
||||||
@@ -55,22 +42,6 @@ class CheckInWidget extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final todayResult = ref.watch(checkInResultTodayProvider);
|
final todayResult = ref.watch(checkInResultTodayProvider);
|
||||||
final nextNotableDay = ref.watch(nextNotableDayProvider);
|
|
||||||
|
|
||||||
final userinfo = ref.watch(userInfoProvider);
|
|
||||||
final isAdult = useMemoized(() {
|
|
||||||
final birthday = userinfo.value?.profile.birthday;
|
|
||||||
if (birthday == null) return false;
|
|
||||||
final now = DateTime.now();
|
|
||||||
final age =
|
|
||||||
now.year -
|
|
||||||
birthday.year -
|
|
||||||
((now.month < birthday.month ||
|
|
||||||
(now.month == birthday.month && now.day < birthday.day))
|
|
||||||
? 1
|
|
||||||
: 0);
|
|
||||||
return age >= 18;
|
|
||||||
}, [userinfo]);
|
|
||||||
|
|
||||||
Future<void> checkIn({String? captchatTk}) async {
|
Future<void> checkIn({String? captchatTk}) async {
|
||||||
final client = ref.read(apiClientProvider);
|
final client = ref.read(apiClientProvider);
|
||||||
@@ -100,147 +71,98 @@ class CheckInWidget extends HookConsumerWidget {
|
|||||||
return Card(
|
return Card(
|
||||||
margin:
|
margin:
|
||||||
margin ?? EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
margin ?? EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
||||||
child: Column(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
spacing: 8,
|
spacing: 16,
|
||||||
children: [
|
children: [
|
||||||
Column(
|
ClipRRect(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
borderRadius: BorderRadius.circular(8),
|
||||||
children: [
|
child: Container(
|
||||||
Row(
|
color: Theme.of(context).colorScheme.secondaryContainer,
|
||||||
spacing: 8,
|
width: 56,
|
||||||
mainAxisSize: MainAxisSize.min,
|
height: 56,
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
child:
|
||||||
children: [
|
Column(
|
||||||
Icon(
|
mainAxisSize: MainAxisSize.min,
|
||||||
switch (DateTime.now().weekday) {
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
6 || 7 => Symbols.weekend,
|
children: [
|
||||||
_ => isAdult ? Symbols.work : Symbols.school,
|
Text(DateFormat('EEE').format(DateTime.now()))
|
||||||
},
|
.fontSize(16)
|
||||||
fill: 1,
|
.bold()
|
||||||
size: 16,
|
.textColor(
|
||||||
).padding(right: 2),
|
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
Text(DateFormat('EEE').format(DateTime.now()))
|
|
||||||
.fontSize(16)
|
|
||||||
.bold()
|
|
||||||
.textColor(
|
|
||||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
|
||||||
),
|
|
||||||
Text(DateFormat('MM/dd').format(DateTime.now()))
|
|
||||||
.fontSize(12)
|
|
||||||
.textColor(
|
|
||||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
|
||||||
)
|
|
||||||
.padding(top: 2),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
Row(
|
|
||||||
spacing: 5,
|
|
||||||
children: [
|
|
||||||
Text('notableDayNext')
|
|
||||||
.tr(args: [nextNotableDay.value?.localName ?? 'idk'])
|
|
||||||
.fontSize(12),
|
|
||||||
SlideCountdown(
|
|
||||||
decoration: const BoxDecoration(),
|
|
||||||
style: const TextStyle(fontSize: 12),
|
|
||||||
separatorStyle: const TextStyle(fontSize: 12),
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
duration: nextNotableDay.value?.date.difference(
|
|
||||||
DateTime.now(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 16, top: 8),
|
|
||||||
const Divider(height: 1),
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: AnimatedSwitcher(
|
|
||||||
duration: const Duration(milliseconds: 300),
|
|
||||||
child: todayResult.when(
|
|
||||||
data: (result) {
|
|
||||||
if (result == null) return _CheckInNoneWidget();
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'checkInResultLevel${result.level}',
|
|
||||||
).tr().fontSize(15).bold(),
|
|
||||||
Wrap(
|
|
||||||
children:
|
|
||||||
result.tips
|
|
||||||
.map((e) {
|
|
||||||
return Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
e.isPositive
|
|
||||||
? Symbols.thumb_up
|
|
||||||
: Symbols.thumb_down,
|
|
||||||
size: 12,
|
|
||||||
),
|
|
||||||
const Gap(4),
|
|
||||||
Text(e.title).fontSize(11),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
})
|
|
||||||
.toList()
|
|
||||||
.expand(
|
|
||||||
(widget) => [
|
|
||||||
widget,
|
|
||||||
Text(' · ').fontSize(11),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
.toList()
|
|
||||||
..removeLast(),
|
|
||||||
),
|
),
|
||||||
],
|
Text(DateFormat('MM/dd').format(DateTime.now()))
|
||||||
);
|
.fontSize(12)
|
||||||
},
|
.textColor(
|
||||||
loading: () => _CheckInNoneWidget(),
|
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
error:
|
),
|
||||||
(err, stack) => Column(
|
],
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
).center(),
|
||||||
children: [
|
),
|
||||||
Text('error').tr().fontSize(15).bold(),
|
),
|
||||||
Text(err.toString()).fontSize(11),
|
Expanded(
|
||||||
],
|
child: AnimatedSwitcher(
|
||||||
),
|
duration: const Duration(milliseconds: 300),
|
||||||
),
|
child: todayResult.when(
|
||||||
),
|
data: (result) {
|
||||||
),
|
if (result == null) return _CheckInNoneWidget();
|
||||||
IconButton.outlined(
|
return Column(
|
||||||
onPressed: () {
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
if (todayResult.valueOrNull == null) {
|
children: [
|
||||||
checkIn();
|
Text(
|
||||||
} else {
|
'checkInResultLevel${result.level}',
|
||||||
context.pushNamed(
|
).tr().fontSize(15).bold(),
|
||||||
'accountCalendar',
|
Text(
|
||||||
pathParameters: {'name': 'me'},
|
result.tips
|
||||||
);
|
.map(
|
||||||
}
|
(e) => '${e.isPositive ? '宜' : '忌'} ${e.title}',
|
||||||
|
)
|
||||||
|
.join(' · '),
|
||||||
|
).fontSize(11),
|
||||||
|
],
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: AnimatedSwitcher(
|
loading: () => _CheckInNoneWidget(),
|
||||||
duration: const Duration(milliseconds: 300),
|
error:
|
||||||
child: todayResult.when(
|
(err, stack) => Column(
|
||||||
data:
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
(result) => Icon(
|
children: [
|
||||||
result == null
|
Text('error').tr().fontSize(15).bold(),
|
||||||
? Symbols.local_fire_department
|
Text(err.toString()).fontSize(11),
|
||||||
: Symbols.event,
|
],
|
||||||
key: ValueKey(result != null),
|
),
|
||||||
),
|
|
||||||
loading: () => const Icon(Symbols.refresh),
|
|
||||||
error: (_, _) => const Icon(Symbols.error),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
).padding(horizontal: 16, bottom: 12, top: 4),
|
),
|
||||||
|
IconButton.outlined(
|
||||||
|
onPressed: () {
|
||||||
|
if (todayResult.valueOrNull == null) {
|
||||||
|
checkIn();
|
||||||
|
} else {
|
||||||
|
context.pushNamed(
|
||||||
|
'accountCalendar',
|
||||||
|
pathParameters: {'name': 'me'},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
icon: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: todayResult.when(
|
||||||
|
data:
|
||||||
|
(result) => Icon(
|
||||||
|
result == null
|
||||||
|
? Symbols.local_fire_department
|
||||||
|
: Symbols.event,
|
||||||
|
key: ValueKey(result != null),
|
||||||
|
),
|
||||||
|
loading: () => const Icon(Symbols.refresh),
|
||||||
|
error: (_, _) => const Icon(Symbols.error),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
).padding(horizontal: 16, vertical: 12),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,24 +26,5 @@ final checkInResultTodayProvider =
|
|||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
typedef CheckInResultTodayRef = AutoDisposeFutureProviderRef<SnCheckInResult?>;
|
typedef CheckInResultTodayRef = AutoDisposeFutureProviderRef<SnCheckInResult?>;
|
||||||
String _$nextNotableDayHash() => r'698370bec4be28774d332412c5a701f914064c90';
|
|
||||||
|
|
||||||
/// See also [nextNotableDay].
|
|
||||||
@ProviderFor(nextNotableDay)
|
|
||||||
final nextNotableDayProvider =
|
|
||||||
AutoDisposeFutureProvider<SnNotableDay?>.internal(
|
|
||||||
nextNotableDay,
|
|
||||||
name: r'nextNotableDayProvider',
|
|
||||||
debugGetCreateSourceHash:
|
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
|
||||||
? null
|
|
||||||
: _$nextNotableDayHash,
|
|
||||||
dependencies: null,
|
|
||||||
allTransitiveDependencies: null,
|
|
||||||
);
|
|
||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
|
||||||
// ignore: unused_element
|
|
||||||
typedef NextNotableDayRef = AutoDisposeFutureProviderRef<SnNotableDay?>;
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
|||||||
@@ -321,7 +321,7 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Icon(fallbackIcon),
|
Icon(fallbackIcon),
|
||||||
const Gap(6),
|
const Gap(6),
|
||||||
Text(file.name, textAlign: TextAlign.center),
|
Text(file.name),
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: file.length(),
|
future: file.length(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
|||||||
@@ -5,11 +5,11 @@ import 'dart:ui';
|
|||||||
|
|
||||||
import 'package:dismissible_page/dismissible_page.dart';
|
import 'package:dismissible_page/dismissible_page.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter_blurhash/flutter_blurhash.dart';
|
|
||||||
import 'package:file_saver/file_saver.dart';
|
import 'package:file_saver/file_saver.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_blurhash/flutter_blurhash.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:gal/gal.dart';
|
import 'package:gal/gal.dart';
|
||||||
@@ -804,213 +804,164 @@ class _CloudFileListEntry extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final dataSaving = ref.watch(
|
|
||||||
appSettingsNotifierProvider.select((s) => s.dataSavingMode),
|
|
||||||
);
|
|
||||||
final showMature = useState(false);
|
final showMature = useState(false);
|
||||||
final showDataSaving = useState(!dataSaving);
|
|
||||||
final lockedByDS = dataSaving && !showDataSaving.value;
|
|
||||||
final lockedByMature = file.sensitiveMarks.isNotEmpty && !showMature.value;
|
|
||||||
final meta = file.fileMeta is Map ? file.fileMeta as Map : const {};
|
|
||||||
final hasRatio =
|
|
||||||
meta.containsKey('ratio') &&
|
|
||||||
(meta['ratio'] is num && (meta['ratio'] as num) != 0);
|
|
||||||
final ratio =
|
|
||||||
(meta['ratio'] is num && (meta['ratio'] as num) != 0)
|
|
||||||
? (meta['ratio'] as num).toDouble()
|
|
||||||
: 1.0;
|
|
||||||
|
|
||||||
final fit = hasRatio ? BoxFit.cover : BoxFit.contain;
|
var content = Stack(
|
||||||
|
|
||||||
Widget bg = const SizedBox.shrink();
|
|
||||||
if (isImage) {
|
|
||||||
if (meta['blur'] is String) {
|
|
||||||
bg = BlurHash(hash: meta['blur'] as String);
|
|
||||||
} else if (!lockedByDS && !lockedByMature) {
|
|
||||||
bg = ImageFiltered(
|
|
||||||
imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
|
||||||
child: CloudFileWidget(
|
|
||||||
fit: fit,
|
|
||||||
item: file,
|
|
||||||
noBlurhash: true,
|
|
||||||
useInternalGate: false,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
bg = const ColoredBox(color: Colors.black26);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
final bool fullyUnlocked = !lockedByDS && !lockedByMature;
|
|
||||||
Widget fg =
|
|
||||||
fullyUnlocked
|
|
||||||
? (isImage
|
|
||||||
? CloudFileWidget(
|
|
||||||
item: file,
|
|
||||||
heroTag: heroTag,
|
|
||||||
noBlurhash: true,
|
|
||||||
fit: fit,
|
|
||||||
useInternalGate: false,
|
|
||||||
)
|
|
||||||
: CloudFileWidget(
|
|
||||||
item: file,
|
|
||||||
heroTag: heroTag,
|
|
||||||
fit: fit,
|
|
||||||
useInternalGate: false,
|
|
||||||
))
|
|
||||||
: AspectRatio(aspectRatio: ratio, child: const SizedBox.shrink());
|
|
||||||
|
|
||||||
Widget overlays;
|
|
||||||
if (lockedByDS) {
|
|
||||||
overlays = _DataSavingOverlay();
|
|
||||||
} else if (file.sensitiveMarks.isNotEmpty) {
|
|
||||||
overlays = _SensitiveOverlay(
|
|
||||||
file: file,
|
|
||||||
isRevealed: showMature.value,
|
|
||||||
onHide: () => showMature.value = false,
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
overlays = const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
final content = Stack(
|
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [if (isImage) Positioned.fill(child: bg), fg, overlays],
|
children: [
|
||||||
);
|
if (isImage)
|
||||||
|
Positioned.fill(
|
||||||
return InkWell(
|
child:
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
file.fileMeta?['blur'] is String
|
||||||
onTap: () {
|
? BlurHash(hash: file.fileMeta?['blur'])
|
||||||
if (lockedByDS) {
|
: ImageFiltered(
|
||||||
showDataSaving.value = true;
|
imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
||||||
} else if (lockedByMature) {
|
child: CloudFileWidget(item: file, noBlurhash: true),
|
||||||
showMature.value = true;
|
),
|
||||||
} else {
|
|
||||||
onTap?.call();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
child: content,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _SensitiveOverlay extends StatelessWidget {
|
|
||||||
final SnCloudFile file;
|
|
||||||
final VoidCallback? onHide;
|
|
||||||
final bool isRevealed;
|
|
||||||
|
|
||||||
const _SensitiveOverlay({
|
|
||||||
required this.file,
|
|
||||||
this.onHide,
|
|
||||||
this.isRevealed = false,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
if (isRevealed) {
|
|
||||||
return Positioned(
|
|
||||||
top: 3,
|
|
||||||
left: 4,
|
|
||||||
child: IconButton(
|
|
||||||
iconSize: 16,
|
|
||||||
constraints: const BoxConstraints(),
|
|
||||||
icon: const Icon(
|
|
||||||
Icons.visibility_off,
|
|
||||||
color: Colors.white,
|
|
||||||
shadows: [
|
|
||||||
Shadow(
|
|
||||||
color: Colors.black,
|
|
||||||
blurRadius: 5.0,
|
|
||||||
offset: Offset(1.0, 1.0),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
tooltip: 'Blur content',
|
if (isImage)
|
||||||
onPressed: onHide,
|
CloudFileWidget(
|
||||||
),
|
item: file,
|
||||||
|
heroTag: heroTag,
|
||||||
|
noBlurhash: true,
|
||||||
|
fit: BoxFit.contain,
|
||||||
|
)
|
||||||
|
else
|
||||||
|
CloudFileWidget(item: file, heroTag: heroTag, fit: BoxFit.contain),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
if (file.sensitiveMarks.isNotEmpty) {
|
||||||
|
// Show a blurred overlay only when not revealed yet, with a smooth transition
|
||||||
|
content = Stack(
|
||||||
|
children: [
|
||||||
|
content,
|
||||||
|
// Toggle blur overlay with animation
|
||||||
|
Positioned.fill(
|
||||||
|
child: AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 250),
|
||||||
|
switchInCurve: Curves.easeOut,
|
||||||
|
switchOutCurve: Curves.easeIn,
|
||||||
|
layoutBuilder:
|
||||||
|
(currentChild, previousChildren) => Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
...previousChildren,
|
||||||
|
if (currentChild != null) currentChild,
|
||||||
|
],
|
||||||
|
),
|
||||||
|
child:
|
||||||
|
showMature.value
|
||||||
|
? const SizedBox.shrink(key: ValueKey('revealed'))
|
||||||
|
: ColoredBox(
|
||||||
|
key: const ValueKey('blurred'),
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: BackdropFilter(
|
||||||
|
filter: ImageFilter.blur(sigmaX: 64, sigmaY: 64),
|
||||||
|
child: Stack(
|
||||||
|
fit: StackFit.expand,
|
||||||
|
children: [
|
||||||
|
const ColoredBox(color: Colors.transparent),
|
||||||
|
Center(
|
||||||
|
child: Container(
|
||||||
|
margin: const EdgeInsets.all(12),
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.black54,
|
||||||
|
borderRadius: BorderRadius.circular(12),
|
||||||
|
),
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(
|
||||||
|
maxWidth: 280,
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Icons.warning,
|
||||||
|
color: Colors.white,
|
||||||
|
fill: 1,
|
||||||
|
size: 24,
|
||||||
|
),
|
||||||
|
const Gap(4),
|
||||||
|
Text(
|
||||||
|
file.sensitiveMarks
|
||||||
|
.map(
|
||||||
|
(e) =>
|
||||||
|
SensitiveCategory
|
||||||
|
.values[e]
|
||||||
|
.i18nKey
|
||||||
|
.tr(),
|
||||||
|
)
|
||||||
|
.join(' · '),
|
||||||
|
style: const TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontWeight: FontWeight.w600,
|
||||||
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
'Sensitive Content',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 13,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(4),
|
||||||
|
Text(
|
||||||
|
'Tap to Reveal',
|
||||||
|
style: TextStyle(
|
||||||
|
color: Colors.white,
|
||||||
|
fontSize: 11,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).padding(horizontal: 24, vertical: 16),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// When revealed (no blur), show a small control at top-left to re-enable blur
|
||||||
|
if (showMature.value)
|
||||||
|
Positioned(
|
||||||
|
top: 3,
|
||||||
|
left: 4,
|
||||||
|
child: IconButton(
|
||||||
|
iconSize: 16,
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
icon: const Icon(Icons.visibility_off, color: Colors.white),
|
||||||
|
tooltip: 'Blur content',
|
||||||
|
onPressed: () {
|
||||||
|
showMature.value = false;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return BackdropFilter(
|
if (onTap != null) {
|
||||||
filter: ImageFilter.blur(sigmaX: 64, sigmaY: 64),
|
return InkWell(
|
||||||
child: Container(
|
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||||
color: Colors.transparent,
|
onTap: () {
|
||||||
child: Center(
|
if (!showMature.value) {
|
||||||
child: _OverlayCard(
|
showMature.value = true;
|
||||||
icon: Icons.warning,
|
} else {
|
||||||
title: file.sensitiveMarks
|
onTap?.call();
|
||||||
.map((e) => SensitiveCategory.values[e].i18nKey.tr())
|
}
|
||||||
.join(' · '),
|
},
|
||||||
subtitle: 'Sensitive Content',
|
child: content,
|
||||||
hint: 'Tap to Reveal',
|
);
|
||||||
),
|
}
|
||||||
),
|
|
||||||
),
|
return content;
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _DataSavingOverlay extends StatelessWidget {
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return ColoredBox(
|
|
||||||
color: Colors.black38,
|
|
||||||
child: Center(
|
|
||||||
child: _OverlayCard(
|
|
||||||
icon: Symbols.image,
|
|
||||||
title: 'Data Saving Mode',
|
|
||||||
subtitle: '',
|
|
||||||
hint: 'Tap to Load',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class _OverlayCard extends StatelessWidget {
|
|
||||||
final IconData icon;
|
|
||||||
final String title;
|
|
||||||
final String subtitle;
|
|
||||||
final String hint;
|
|
||||||
|
|
||||||
const _OverlayCard({
|
|
||||||
required this.icon,
|
|
||||||
required this.title,
|
|
||||||
required this.subtitle,
|
|
||||||
required this.hint,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return Container(
|
|
||||||
margin: const EdgeInsets.all(12),
|
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 12, vertical: 8),
|
|
||||||
decoration: BoxDecoration(
|
|
||||||
color: Colors.black54,
|
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
),
|
|
||||||
constraints: const BoxConstraints(maxWidth: 280),
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(icon, color: Colors.white, size: 24),
|
|
||||||
const Gap(4),
|
|
||||||
Text(
|
|
||||||
title,
|
|
||||||
style: const TextStyle(
|
|
||||||
color: Colors.white,
|
|
||||||
fontWeight: FontWeight.w600,
|
|
||||||
),
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
subtitle,
|
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 13),
|
|
||||||
),
|
|
||||||
const Gap(4),
|
|
||||||
Text(hint, style: const TextStyle(color: Colors.white, fontSize: 11)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,7 +14,6 @@ import 'package:island/widgets/content/audio.dart';
|
|||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
import 'package:island/widgets/data_saving_gate.dart';
|
|
||||||
|
|
||||||
import 'image.dart';
|
import 'image.dart';
|
||||||
import 'video.dart';
|
import 'video.dart';
|
||||||
@@ -24,97 +23,86 @@ class CloudFileWidget extends HookConsumerWidget {
|
|||||||
final BoxFit fit;
|
final BoxFit fit;
|
||||||
final String? heroTag;
|
final String? heroTag;
|
||||||
final bool noBlurhash;
|
final bool noBlurhash;
|
||||||
final bool useInternalGate;
|
|
||||||
const CloudFileWidget({
|
const CloudFileWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.item,
|
required this.item,
|
||||||
this.fit = BoxFit.cover,
|
this.fit = BoxFit.cover,
|
||||||
this.heroTag,
|
this.heroTag,
|
||||||
this.noBlurhash = false,
|
this.noBlurhash = false,
|
||||||
this.useInternalGate = true,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final dataSaving = ref.watch(
|
|
||||||
appSettingsNotifierProvider.select((s) => s.dataSavingMode),
|
|
||||||
);
|
|
||||||
final serverUrl = ref.watch(serverUrlProvider);
|
final serverUrl = ref.watch(serverUrlProvider);
|
||||||
final uri = '$serverUrl/drive/files/${item.id}';
|
final uri = '$serverUrl/drive/files/${item.id}';
|
||||||
|
|
||||||
final unlocked = useState(false);
|
var ratio =
|
||||||
|
item.fileMeta?['ratio'] is num
|
||||||
final meta = item.fileMeta is Map ? (item.fileMeta as Map) : const {};
|
? item.fileMeta!['ratio'].toDouble()
|
||||||
final blurHash = noBlurhash ? null : (meta['blur'] as String?);
|
: 1.0;
|
||||||
var ratio = meta['ratio'] is num ? (meta['ratio'] as num).toDouble() : 1.0;
|
|
||||||
if (ratio == 0) ratio = 1.0;
|
if (ratio == 0) ratio = 1.0;
|
||||||
|
|
||||||
Widget cloudImage() => UniversalImage(uri: uri, blurHash: blurHash, fit: fit);
|
|
||||||
Widget cloudVideo() => CloudVideoWidget(item: item);
|
|
||||||
|
|
||||||
Widget dataPlaceHolder(IconData icon) => _DataSavingPlaceholder(
|
|
||||||
icon: icon,
|
|
||||||
onTap: () {
|
|
||||||
unlocked.value = true;
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
var content = switch (item.mimeType?.split('/').firstOrNull) {
|
var content = switch (item.mimeType?.split('/').firstOrNull) {
|
||||||
'image' => AspectRatio(
|
"image" => AspectRatio(
|
||||||
aspectRatio: ratio,
|
aspectRatio: ratio,
|
||||||
child: (useInternalGate && dataSaving && !unlocked.value) ? dataPlaceHolder(Symbols.image) : cloudImage(),
|
child: UniversalImage(
|
||||||
|
uri: uri,
|
||||||
|
blurHash:
|
||||||
|
noBlurhash
|
||||||
|
? null
|
||||||
|
: (item.fileMeta is String ? item.fileMeta!['blur'] : null),
|
||||||
),
|
),
|
||||||
'video' => AspectRatio(
|
),
|
||||||
aspectRatio: ratio,
|
"video" => AspectRatio(
|
||||||
child: (useInternalGate && dataSaving && !unlocked.value) ? dataPlaceHolder(Symbols.play_arrow) : cloudVideo(),
|
aspectRatio: ratio,
|
||||||
),
|
child: CloudVideoWidget(item: item),
|
||||||
'audio' => Center(
|
),
|
||||||
child: ConstrainedBox(
|
"audio" => Center(
|
||||||
constraints: BoxConstraints(
|
child: ConstrainedBox(
|
||||||
maxWidth: math.min(360, MediaQuery.of(context).size.width * 0.8),
|
constraints: BoxConstraints(
|
||||||
),
|
maxWidth: math.min(360, MediaQuery.of(context).size.width * 0.8),
|
||||||
child: UniversalAudio(uri: uri, filename: item.name),
|
|
||||||
),
|
),
|
||||||
|
child: UniversalAudio(uri: uri, filename: item.name),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
_ => Column(
|
_ => Column(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
Symbols.insert_drive_file,
|
Symbols.insert_drive_file,
|
||||||
size: 48,
|
size: 48,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
item.name,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
),
|
),
|
||||||
const Gap(8),
|
),
|
||||||
Text(
|
Text(
|
||||||
item.name,
|
formatFileSize(item.size),
|
||||||
maxLines: 1,
|
style: TextStyle(
|
||||||
overflow: TextOverflow.ellipsis,
|
fontSize: 12,
|
||||||
style: TextStyle(
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
fontSize: 14,
|
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
Text(
|
),
|
||||||
formatFileSize(item.size),
|
const Gap(8),
|
||||||
style: TextStyle(
|
TextButton.icon(
|
||||||
fontSize: 12,
|
onPressed: () {
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
launchUrlString(
|
||||||
),
|
'https://fs.solian.app/files/${item.id}',
|
||||||
),
|
mode: LaunchMode.externalApplication,
|
||||||
const Gap(8),
|
);
|
||||||
TextButton.icon(
|
},
|
||||||
onPressed: () {
|
icon: const Icon(Symbols.launch),
|
||||||
launchUrlString(
|
label: Text('openInBrowser').tr(),
|
||||||
'https://fs.solian.app/files/${item.id}',
|
),
|
||||||
mode: LaunchMode.externalApplication,
|
],
|
||||||
);
|
).padding(all: 8),
|
||||||
},
|
|
||||||
icon: const Icon(Symbols.launch),
|
|
||||||
label: Text('openInBrowser').tr(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(all: 8),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (heroTag != null) {
|
if (heroTag != null) {
|
||||||
@@ -125,35 +113,6 @@ class CloudFileWidget extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _DataSavingPlaceholder extends StatelessWidget {
|
|
||||||
final IconData icon;
|
|
||||||
final VoidCallback onTap;
|
|
||||||
const _DataSavingPlaceholder({required this.icon, required this.onTap});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return GestureDetector(
|
|
||||||
onTap: onTap,
|
|
||||||
child: Container(
|
|
||||||
color: Colors.black26,
|
|
||||||
alignment: Alignment.center,
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(icon, size: 36,
|
|
||||||
color: Theme.of(context).colorScheme.onSurfaceVariant),
|
|
||||||
const Gap(8),
|
|
||||||
Text(
|
|
||||||
'dataSavingHint'.tr(),
|
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
class CloudVideoWidget extends HookConsumerWidget {
|
class CloudVideoWidget extends HookConsumerWidget {
|
||||||
final SnCloudFile item;
|
final SnCloudFile item;
|
||||||
const CloudVideoWidget({super.key, required this.item});
|
const CloudVideoWidget({super.key, required this.item});
|
||||||
@@ -352,35 +311,32 @@ class ProfilePictureWidget extends ConsumerWidget {
|
|||||||
this.fallbackColor,
|
this.fallbackColor,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final serverUrl = ref.watch(serverUrlProvider);
|
final serverUrl = ref.watch(serverUrlProvider);
|
||||||
final String? id = file?.id ?? fileId;
|
final uri = '$serverUrl/drive/files/${file?.id ?? fileId}';
|
||||||
|
|
||||||
final fallback = Icon(
|
|
||||||
fallbackIcon ?? Symbols.account_circle,
|
|
||||||
size: radius,
|
|
||||||
color: fallbackColor ?? Theme.of(context).colorScheme.onPrimaryContainer,
|
|
||||||
).center();
|
|
||||||
|
|
||||||
return ClipRRect(
|
return ClipRRect(
|
||||||
borderRadius: borderRadius == null
|
borderRadius:
|
||||||
? BorderRadius.all(Radius.circular(radius))
|
borderRadius == null
|
||||||
: BorderRadius.all(Radius.circular(borderRadius!)),
|
? BorderRadius.all(Radius.circular(radius))
|
||||||
|
: BorderRadius.all(Radius.circular(borderRadius!)),
|
||||||
child: Container(
|
child: Container(
|
||||||
width: radius * 2,
|
width: radius * 2,
|
||||||
height: radius * 2,
|
height: radius * 2,
|
||||||
color: Theme.of(context).colorScheme.primaryContainer,
|
color: Theme.of(context).colorScheme.primaryContainer,
|
||||||
child: id == null
|
child:
|
||||||
? fallback
|
file != null
|
||||||
: DataSavingGate(
|
? CloudFileWidget(item: file!, fit: BoxFit.cover)
|
||||||
bypass: true,
|
: fileId == null
|
||||||
placeholder: fallback,
|
? Icon(
|
||||||
content: () => UniversalImage(
|
fallbackIcon ?? Symbols.account_circle,
|
||||||
uri: '$serverUrl/drive/files/$id',
|
size: radius,
|
||||||
fit: BoxFit.cover,
|
color:
|
||||||
),
|
fallbackColor ??
|
||||||
),
|
Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
|
).center()
|
||||||
|
: UniversalImage(uri: uri, fit: BoxFit.cover),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,27 +0,0 @@
|
|||||||
import 'package:flutter/material.dart';
|
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|
||||||
import 'package:island/pods/config.dart';
|
|
||||||
|
|
||||||
|
|
||||||
typedef WidgetBuilder0 = Widget Function();
|
|
||||||
|
|
||||||
class DataSavingGate extends ConsumerWidget {
|
|
||||||
final bool bypass;
|
|
||||||
final WidgetBuilder0 content;
|
|
||||||
final Widget placeholder;
|
|
||||||
|
|
||||||
const DataSavingGate({
|
|
||||||
super.key,
|
|
||||||
required this.bypass,
|
|
||||||
required this.content,
|
|
||||||
required this.placeholder,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final dataSaving =
|
|
||||||
ref.watch(appSettingsNotifierProvider.select((s) => s.dataSavingMode));
|
|
||||||
if (bypass || !dataSaving) return content();
|
|
||||||
return placeholder;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
28
pubspec.lock
28
pubspec.lock
@@ -50,7 +50,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.3"
|
||||||
archive:
|
archive:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
|
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
|
||||||
@@ -1789,14 +1789,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.0"
|
version: "2.3.0"
|
||||||
pausable_timer:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: pausable_timer
|
|
||||||
sha256: "6ef1a95441ec3439de6fb63f39a011b67e693198e7dae14e20675c3c00e86074"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.1.0+3"
|
|
||||||
petitparser:
|
petitparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1885,14 +1877,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.0.3"
|
version: "6.0.3"
|
||||||
process_run:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: process_run
|
|
||||||
sha256: "6ec839cdd3e6de4685318e7686cd4abb523c3d3a55af0e8d32a12ae19bc66622"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.4"
|
|
||||||
protobuf:
|
protobuf:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2266,14 +2250,6 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
slide_countdown:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: slide_countdown
|
|
||||||
sha256: "363914f96389502467d4dc9c0f26e88f93df3d8e37de2d5ff05b16d981fe973d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.2"
|
|
||||||
source_gen:
|
source_gen:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2701,7 +2677,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.4.0"
|
version: "3.4.0"
|
||||||
wakelock_plus:
|
wakelock_plus:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: wakelock_plus
|
name: wakelock_plus
|
||||||
sha256: a474e314c3e8fb5adef1f9ae2d247e57467ad557fa7483a2b895bc1b421c5678
|
sha256: a474e314c3e8fb5adef1f9ae2d247e57467ad557fa7483a2b895bc1b421c5678
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ publish_to: "none" # Remove this line if you wish to publish to pub.dev
|
|||||||
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
# https://developer.apple.com/library/archive/documentation/General/Reference/InfoPlistKeyReference/Articles/CoreFoundationKeys.html
|
||||||
# In Windows, build-name is used as the major, minor, and patch parts
|
# In Windows, build-name is used as the major, minor, and patch parts
|
||||||
# of the product and file versions while build-number is used as the build suffix.
|
# of the product and file versions while build-number is used as the build suffix.
|
||||||
version: 3.2.0+131
|
version: 3.2.0+129
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
@@ -132,8 +132,6 @@ dependencies:
|
|||||||
flutter_typeahead: ^5.2.0
|
flutter_typeahead: ^5.2.0
|
||||||
waveform_flutter: ^1.2.0
|
waveform_flutter: ^1.2.0
|
||||||
flutter_app_update: ^3.2.2
|
flutter_app_update: ^3.2.2
|
||||||
archive: ^4.0.7
|
|
||||||
process_run: ^1.2.0
|
|
||||||
firebase_crashlytics: ^5.0.1
|
firebase_crashlytics: ^5.0.1
|
||||||
firebase_analytics: ^12.0.1
|
firebase_analytics: ^12.0.1
|
||||||
material_color_utilities: ^0.11.1
|
material_color_utilities: ^0.11.1
|
||||||
@@ -143,8 +141,6 @@ dependencies:
|
|||||||
tray_manager: ^0.5.1
|
tray_manager: ^0.5.1
|
||||||
flutter_webrtc: ^1.1.0
|
flutter_webrtc: ^1.1.0
|
||||||
flutter_local_notifications: ^19.4.1
|
flutter_local_notifications: ^19.4.1
|
||||||
wakelock_plus: ^1.3.2
|
|
||||||
slide_countdown: ^2.0.2
|
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
|||||||
Reference in New Issue
Block a user