Compare commits
12 Commits
77b6ce9937
...
3.2.0+131
| Author | SHA1 | Date | |
|---|---|---|---|
|
6f9d51673b
|
|||
|
f8c6887769
|
|||
|
cd2a507b7f
|
|||
|
3cafce00a2
|
|||
|
837f3fbe98
|
|||
|
ca7cc5d7ee
|
|||
|
ef2c14daa2
|
|||
|
3a17837cc6
|
|||
|
2617a64acf
|
|||
|
afe1e12a3b
|
|||
|
be80f5ff85
|
|||
|
3281d69eba
|
@@ -195,6 +195,7 @@
|
|||||||
"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.",
|
||||||
@@ -228,6 +229,8 @@
|
|||||||
"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",
|
||||||
@@ -973,5 +976,6 @@
|
|||||||
"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,11 +158,12 @@
|
|||||||
"checkIn": "签到",
|
"checkIn": "签到",
|
||||||
"checkInNone": "尚未签到",
|
"checkInNone": "尚未签到",
|
||||||
"checkInNoneHint": "通过签到获取您的财富提示和每日奖励。",
|
"checkInNoneHint": "通过签到获取您的财富提示和每日奖励。",
|
||||||
"checkInResultLevel0": "最差运气",
|
"checkInResultLevel0": "大凶",
|
||||||
"checkInResultLevel1": "坏运气",
|
"checkInResultLevel1": "凶",
|
||||||
"checkInResultLevel2": "一个普通的日常",
|
"checkInResultLevel2": "中平",
|
||||||
"checkInResultLevel3": "好运",
|
"checkInResultLevel3": "吉",
|
||||||
"checkInResultLevel4": "最佳运气",
|
"checkInResultLevel4": "大吉",
|
||||||
|
"checkInResultLevel5": "生日快乐 🥳",
|
||||||
"checkInActivityTitle": "{} 在 {} 签到并获得了 {}",
|
"checkInActivityTitle": "{} 在 {} 签到并获得了 {}",
|
||||||
"eventCalander": "活动日历",
|
"eventCalander": "活动日历",
|
||||||
"eventCalanderEmpty": "该日无活动。",
|
"eventCalanderEmpty": "该日无活动。",
|
||||||
@@ -862,5 +863,6 @@
|
|||||||
"statusPresent": "至今",
|
"statusPresent": "至今",
|
||||||
"accountAutomated": "机器人",
|
"accountAutomated": "机器人",
|
||||||
"openInBrowser": "在浏览器中打开",
|
"openInBrowser": "在浏览器中打开",
|
||||||
"highlightPost": "精选帖子"
|
"highlightPost": "精选帖子",
|
||||||
|
"notableDayNext": "距离 {} 还有"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,8 @@ 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):
|
||||||
@@ -314,6 +316,7 @@ 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`)
|
||||||
@@ -402,6 +405,8 @@ 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:
|
||||||
@@ -488,6 +493,7 @@ 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
|
||||||
|
|||||||
@@ -13,6 +13,7 @@ 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; 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; 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;
|
||||||
/// 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.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.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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(badges),createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,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, 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, region: $region, 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, 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, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,12 +65,13 @@ 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? 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? 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,}) {
|
||||||
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
|
||||||
@@ -182,10 +183,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@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;
|
@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;
|
||||||
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.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.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -203,10 +204,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@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;
|
@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;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccount():
|
case _SnAccount():
|
||||||
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);}
|
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);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -220,10 +221,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@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;
|
@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;
|
||||||
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.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.region,_that.isSuperuser,_that.automatedId,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -235,13 +236,14 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnAccount implements SnAccount {
|
class _SnAccount implements SnAccount {
|
||||||
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;
|
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;
|
||||||
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;
|
||||||
@@ -270,16 +272,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.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.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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,automatedId,profile,perkSubscription,const DeepCollectionEquality().hash(_badges),createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,nick,language,region,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, 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, region: $region, isSuperuser: $isSuperuser, automatedId: $automatedId, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -290,7 +292,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, 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, String region, bool isSuperuser, String? automatedId, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -307,12 +309,13 @@ 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? 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? 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,}) {
|
||||||
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,6 +11,7 @@ _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>),
|
||||||
@@ -39,6 +40,7 @@ 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,6 +4,20 @@ 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,6 +12,281 @@ 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,6 +6,27 @@ 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,6 +11,20 @@ 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({
|
||||||
@@ -26,7 +40,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 String? location,
|
required GeoIpLocation? location,
|
||||||
required String accountId,
|
required String accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
|
|||||||
@@ -269,10 +269,279 @@ 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; String? 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; GeoIpLocation? 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)
|
||||||
@@ -305,11 +574,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, String? 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, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$GeoIpLocationCopyWith<$Res>? get location;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -337,14 +606,26 @@ 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 String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as GeoIpLocation?,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));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -423,7 +704,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, String? 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, GeoIpLocation? 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 _:
|
||||||
@@ -444,7 +725,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, String? 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, GeoIpLocation? 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);}
|
||||||
@@ -461,7 +742,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, String? 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, GeoIpLocation? 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 _:
|
||||||
@@ -509,7 +790,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 String? location;
|
@override final GeoIpLocation? 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;
|
||||||
@@ -548,11 +829,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, String? 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, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $GeoIpLocationCopyWith<$Res>? get location;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -580,7 +861,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 String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as GeoIpLocation?,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
|
||||||
@@ -588,7 +869,19 @@ 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,6 +13,24 @@ 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,
|
||||||
@@ -30,7 +48,12 @@ _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: json['location'] as String?,
|
location:
|
||||||
|
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),
|
||||||
@@ -54,7 +77,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,
|
'location': instance.location?.toJson(),
|
||||||
'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(),
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ 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});
|
||||||
@@ -97,6 +98,7 @@ 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 {
|
||||||
@@ -111,6 +113,7 @@ 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);
|
||||||
@@ -291,6 +294,32 @@ 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(
|
||||||
|
|||||||
@@ -59,12 +59,14 @@ class PostState extends StateNotifier<AsyncValue<SnPost?>> {
|
|||||||
|
|
||||||
class PostActionButtons extends HookConsumerWidget {
|
class PostActionButtons extends HookConsumerWidget {
|
||||||
final SnPost post;
|
final SnPost post;
|
||||||
|
final EdgeInsets renderingPadding;
|
||||||
final VoidCallback? onRefresh;
|
final VoidCallback? onRefresh;
|
||||||
final Function(SnPost)? onUpdate;
|
final Function(SnPost)? onUpdate;
|
||||||
|
|
||||||
const PostActionButtons({
|
const PostActionButtons({
|
||||||
super.key,
|
super.key,
|
||||||
required this.post,
|
required this.post,
|
||||||
|
this.renderingPadding = EdgeInsets.zero,
|
||||||
this.onRefresh,
|
this.onRefresh,
|
||||||
this.onUpdate,
|
this.onUpdate,
|
||||||
});
|
});
|
||||||
@@ -151,7 +153,9 @@ class PostActionButtons extends HookConsumerWidget {
|
|||||||
children:
|
children:
|
||||||
editButtons
|
editButtons
|
||||||
.map((e) => SizedBox(height: kButtonHeight, child: e))
|
.map((e) => SizedBox(height: kButtonHeight, child: e))
|
||||||
.toList(),
|
.expand((widget) => [widget, const VerticalDivider(width: 1)])
|
||||||
|
.toList()
|
||||||
|
..removeLast(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -316,7 +320,9 @@ class PostActionButtons extends HookConsumerWidget {
|
|||||||
children:
|
children:
|
||||||
shareButtons
|
shareButtons
|
||||||
.map((e) => SizedBox(height: kButtonHeight, child: e))
|
.map((e) => SizedBox(height: kButtonHeight, child: e))
|
||||||
.toList(),
|
.expand((widget) => [widget, const VerticalDivider(width: 1)])
|
||||||
|
.toList()
|
||||||
|
..removeLast(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -359,7 +365,7 @@ class PostActionButtons extends HookConsumerWidget {
|
|||||||
margin: const EdgeInsets.only(bottom: 12),
|
margin: const EdgeInsets.only(bottom: 12),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
padding: EdgeInsets.symmetric(horizontal: renderingPadding.horizontal),
|
||||||
children: children,
|
children: children,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -418,6 +424,9 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
constraints: BoxConstraints(maxWidth: 600),
|
constraints: BoxConstraints(maxWidth: 600),
|
||||||
child: PostActionButtons(
|
child: PostActionButtons(
|
||||||
post: post,
|
post: post,
|
||||||
|
renderingPadding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
onRefresh: () {
|
onRefresh: () {
|
||||||
ref.invalidate(postProvider(id));
|
ref.invalidate(postProvider(id));
|
||||||
ref.invalidate(postRepliesNotifierProvider(id));
|
ref.invalidate(postRepliesNotifierProvider(id));
|
||||||
|
|||||||
@@ -48,7 +48,11 @@ class TrayService {
|
|||||||
void handleAction(MenuItem item) {
|
void handleAction(MenuItem item) {
|
||||||
switch (item.key) {
|
switch (item.key) {
|
||||||
case 'show_window':
|
case 'show_window':
|
||||||
appWindow.show();
|
if (appWindow.isVisible) {
|
||||||
|
appWindow.restore();
|
||||||
|
} else {
|
||||||
|
appWindow.show();
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
case 'exit_app':
|
case 'exit_app':
|
||||||
appWindow.close();
|
appWindow.close();
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ 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';
|
||||||
@@ -10,6 +11,9 @@ 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';
|
||||||
@@ -180,9 +184,13 @@ 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 {
|
||||||
@@ -192,6 +200,7 @@ class UpdateService {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
androidUpdateUrl: androidUpdateUrl,
|
androidUpdateUrl: androidUpdateUrl,
|
||||||
|
windowsUpdateUrl: windowsUpdateUrl,
|
||||||
useProxy: useProxy, // Pass the useProxy flag
|
useProxy: useProxy, // Pass the useProxy flag
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -211,15 +220,270 @@ class UpdateService {
|
|||||||
|
|
||||||
// Prioritize arm64, then armeabi, then x86_64
|
// Prioritize arm64, then armeabi, then x86_64
|
||||||
if (arm64 != null) {
|
if (arm64 != null) {
|
||||||
return arm64.browserDownloadUrl;
|
return 'https://fs.solsynth.dev/d/official/solian/${arm64.name}';
|
||||||
} else if (armeabi != null) {
|
} else if (armeabi != null) {
|
||||||
return armeabi.browserDownloadUrl;
|
return 'https://fs.solsynth.dev/d/official/solian/${armeabi.name}';
|
||||||
} else if (x86_64 != null) {
|
} else if (x86_64 != null) {
|
||||||
return x86_64.browserDownloadUrl;
|
return 'https://fs.solsynth.dev/d/official/solian/${x86_64.name}';
|
||||||
}
|
}
|
||||||
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 {
|
||||||
@@ -277,10 +541,12 @@ 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;
|
||||||
@@ -299,8 +565,11 @@ class _UpdateSheetState extends State<_UpdateSheet> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _installUpdate(String url) async {
|
Future<void> _installUpdate(String url) async {
|
||||||
final downloadUrl =
|
String downloadUrl = url;
|
||||||
_useProxy ? 'https://ghfast.top/${Uri.encodeComponent(url)}' : url;
|
if (_useProxy) {
|
||||||
|
final fileName = url.split('/').last;
|
||||||
|
downloadUrl = 'https://fs.solsynth.dev/d/rainyun02/solian/$fileName';
|
||||||
|
}
|
||||||
|
|
||||||
UpdateModel model = UpdateModel(
|
UpdateModel model = UpdateModel(
|
||||||
downloadUrl,
|
downloadUrl,
|
||||||
@@ -350,7 +619,7 @@ class _UpdateSheetState extends State<_UpdateSheet> {
|
|||||||
),
|
),
|
||||||
if (!kIsWeb && Platform.isAndroid)
|
if (!kIsWeb && Platform.isAndroid)
|
||||||
SwitchListTile(
|
SwitchListTile(
|
||||||
title: const Text('Use GitHub Proxy for Download'),
|
title: const Text('Use secondary source for download'),
|
||||||
value: _useProxy,
|
value: _useProxy,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
setState(() {
|
setState(() {
|
||||||
@@ -376,6 +645,25 @@ 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,
|
||||||
|
|||||||
@@ -46,6 +46,10 @@ 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,
|
||||||
|
|||||||
@@ -63,7 +63,11 @@ class AppWrapper extends HookConsumerWidget with TrayListener {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _trayIconPrimaryAction() {
|
void _trayIconPrimaryAction() {
|
||||||
appWindow.show();
|
if (appWindow.isVisible) {
|
||||||
|
appWindow.restore();
|
||||||
|
} else {
|
||||||
|
appWindow.show();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void _trayIconSecondaryAction() {
|
void _trayIconSecondaryAction() {
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ 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';
|
||||||
@@ -14,6 +15,7 @@ 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';
|
||||||
@@ -34,6 +36,17 @@ 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;
|
||||||
@@ -42,6 +55,22 @@ 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);
|
||||||
@@ -71,98 +100,147 @@ 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: Row(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
spacing: 16,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
ClipRRect(
|
Column(
|
||||||
borderRadius: BorderRadius.circular(8),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Container(
|
children: [
|
||||||
color: Theme.of(context).colorScheme.secondaryContainer,
|
Row(
|
||||||
width: 56,
|
spacing: 8,
|
||||||
height: 56,
|
mainAxisSize: MainAxisSize.min,
|
||||||
child:
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
Column(
|
children: [
|
||||||
mainAxisSize: MainAxisSize.min,
|
Icon(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
switch (DateTime.now().weekday) {
|
||||||
children: [
|
6 || 7 => Symbols.weekend,
|
||||||
Text(DateFormat('EEE').format(DateTime.now()))
|
_ => isAdult ? Symbols.work : Symbols.school,
|
||||||
.fontSize(16)
|
},
|
||||||
.bold()
|
fill: 1,
|
||||||
.textColor(
|
size: 16,
|
||||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
).padding(right: 2),
|
||||||
|
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(
|
},
|
||||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
loading: () => _CheckInNoneWidget(),
|
||||||
),
|
error:
|
||||||
],
|
(err, stack) => Column(
|
||||||
).center(),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
),
|
children: [
|
||||||
),
|
Text('error').tr().fontSize(15).bold(),
|
||||||
Expanded(
|
Text(err.toString()).fontSize(11),
|
||||||
child: AnimatedSwitcher(
|
],
|
||||||
duration: const Duration(milliseconds: 300),
|
),
|
||||||
child: todayResult.when(
|
),
|
||||||
data: (result) {
|
),
|
||||||
if (result == null) return _CheckInNoneWidget();
|
),
|
||||||
return Column(
|
IconButton.outlined(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
onPressed: () {
|
||||||
children: [
|
if (todayResult.valueOrNull == null) {
|
||||||
Text(
|
checkIn();
|
||||||
'checkInResultLevel${result.level}',
|
} else {
|
||||||
).tr().fontSize(15).bold(),
|
context.pushNamed(
|
||||||
Text(
|
'accountCalendar',
|
||||||
result.tips
|
pathParameters: {'name': 'me'},
|
||||||
.map(
|
);
|
||||||
(e) => '${e.isPositive ? '宜' : '忌'} ${e.title}',
|
}
|
||||||
)
|
|
||||||
.join(' · '),
|
|
||||||
).fontSize(11),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
loading: () => _CheckInNoneWidget(),
|
icon: AnimatedSwitcher(
|
||||||
error:
|
duration: const Duration(milliseconds: 300),
|
||||||
(err, stack) => Column(
|
child: todayResult.when(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
data:
|
||||||
children: [
|
(result) => Icon(
|
||||||
Text('error').tr().fontSize(15).bold(),
|
result == null
|
||||||
Text(err.toString()).fontSize(11),
|
? Symbols.local_fire_department
|
||||||
],
|
: 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,5 +26,24 @@ 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),
|
Text(file.name, textAlign: TextAlign.center),
|
||||||
FutureBuilder(
|
FutureBuilder(
|
||||||
future: file.length(),
|
future: file.length(),
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
|
|||||||
@@ -802,97 +802,135 @@ class _CloudFileListEntry extends HookConsumerWidget {
|
|||||||
this.onTap,
|
this.onTap,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final dataSaving = ref.watch(
|
final dataSaving = ref.watch(
|
||||||
appSettingsNotifierProvider.select((s) => s.dataSavingMode),
|
appSettingsNotifierProvider.select((s) => s.dataSavingMode),
|
||||||
);
|
);
|
||||||
final showMature = useState(false);
|
final showMature = useState(false);
|
||||||
final showDataSaving = useState(!dataSaving);
|
final showDataSaving = useState(!dataSaving);
|
||||||
final lockedByDS = dataSaving && !showDataSaving.value;
|
final lockedByDS = dataSaving && !showDataSaving.value;
|
||||||
final lockedByMature = file.sensitiveMarks.isNotEmpty && !showMature.value;
|
final lockedByMature = file.sensitiveMarks.isNotEmpty && !showMature.value;
|
||||||
final meta = file.fileMeta is Map ? file.fileMeta as Map : const {};
|
final meta = file.fileMeta is Map ? file.fileMeta as Map : const {};
|
||||||
final ratio = (meta['ratio'] is num && (meta['ratio'] as num) != 0)
|
final hasRatio =
|
||||||
? (meta['ratio'] as num).toDouble()
|
meta.containsKey('ratio') &&
|
||||||
: 1.0;
|
(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;
|
||||||
|
|
||||||
Widget bg = const SizedBox.shrink();
|
Widget bg = const SizedBox.shrink();
|
||||||
if (isImage) {
|
if (isImage) {
|
||||||
if (meta['blur'] is String) {
|
if (meta['blur'] is String) {
|
||||||
bg = BlurHash(hash: meta['blur'] as String);
|
bg = BlurHash(hash: meta['blur'] as String);
|
||||||
} else if (!lockedByDS && !lockedByMature) {
|
} else if (!lockedByDS && !lockedByMature) {
|
||||||
bg = ImageFiltered(
|
bg = ImageFiltered(
|
||||||
imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
imageFilter: ImageFilter.blur(sigmaX: 10, sigmaY: 10),
|
||||||
child: CloudFileWidget(
|
child: CloudFileWidget(
|
||||||
item: file,
|
fit: fit,
|
||||||
noBlurhash: true,
|
item: file,
|
||||||
useInternalGate: false,
|
noBlurhash: true,
|
||||||
),
|
useInternalGate: false,
|
||||||
);
|
),
|
||||||
} else {
|
);
|
||||||
bg = const ColoredBox(color: Colors.black26);
|
} else {
|
||||||
}
|
bg = const ColoredBox(color: Colors.black26);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final bool fullyUnlocked = !lockedByDS && !lockedByMature;
|
final bool fullyUnlocked = !lockedByDS && !lockedByMature;
|
||||||
Widget fg = fullyUnlocked
|
Widget fg =
|
||||||
? (isImage
|
fullyUnlocked
|
||||||
? CloudFileWidget(
|
? (isImage
|
||||||
item: file,
|
? CloudFileWidget(
|
||||||
heroTag: heroTag,
|
item: file,
|
||||||
noBlurhash: true,
|
heroTag: heroTag,
|
||||||
fit: BoxFit.contain,
|
noBlurhash: true,
|
||||||
useInternalGate: false,
|
fit: fit,
|
||||||
)
|
useInternalGate: false,
|
||||||
: CloudFileWidget(
|
)
|
||||||
item: file,
|
: CloudFileWidget(
|
||||||
heroTag: heroTag,
|
item: file,
|
||||||
fit: BoxFit.contain,
|
heroTag: heroTag,
|
||||||
useInternalGate: false,
|
fit: fit,
|
||||||
)
|
useInternalGate: false,
|
||||||
)
|
))
|
||||||
: AspectRatio(aspectRatio: ratio, child: const SizedBox.shrink());
|
: AspectRatio(aspectRatio: ratio, child: const SizedBox.shrink());
|
||||||
|
|
||||||
Widget overlays;
|
Widget overlays;
|
||||||
if (lockedByDS) {
|
if (lockedByDS) {
|
||||||
overlays = _DataSavingOverlay();
|
overlays = _DataSavingOverlay();
|
||||||
} else if (lockedByMature) {
|
} else if (file.sensitiveMarks.isNotEmpty) {
|
||||||
overlays = _SensitiveOverlay(file: file);
|
overlays = _SensitiveOverlay(
|
||||||
|
file: file,
|
||||||
|
isRevealed: showMature.value,
|
||||||
|
onHide: () => showMature.value = false,
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
overlays = const SizedBox.shrink();
|
overlays = const SizedBox.shrink();
|
||||||
}
|
}
|
||||||
|
|
||||||
final content = Stack(
|
final content = Stack(
|
||||||
fit: StackFit.expand,
|
fit: StackFit.expand,
|
||||||
children: [
|
children: [if (isImage) Positioned.fill(child: bg), fg, overlays],
|
||||||
if (isImage) Positioned.fill(child: bg),
|
|
||||||
fg,
|
|
||||||
overlays,
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
|
|
||||||
return InkWell(
|
return InkWell(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (lockedByDS) {
|
if (lockedByDS) {
|
||||||
showDataSaving.value = true;
|
showDataSaving.value = true;
|
||||||
} else if (lockedByMature) {
|
} else if (lockedByMature) {
|
||||||
showMature.value = true;
|
showMature.value = true;
|
||||||
} else {
|
} else {
|
||||||
onTap?.call();
|
onTap?.call();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: content,
|
child: content,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _SensitiveOverlay extends StatelessWidget {
|
class _SensitiveOverlay extends StatelessWidget {
|
||||||
final SnCloudFile file;
|
final SnCloudFile file;
|
||||||
const _SensitiveOverlay({required this.file});
|
final VoidCallback? onHide;
|
||||||
|
final bool isRevealed;
|
||||||
|
|
||||||
|
const _SensitiveOverlay({
|
||||||
|
required this.file,
|
||||||
|
this.onHide,
|
||||||
|
this.isRevealed = false,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
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',
|
||||||
|
onPressed: onHide,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
return BackdropFilter(
|
return BackdropFilter(
|
||||||
filter: ImageFilter.blur(sigmaX: 64, sigmaY: 64),
|
filter: ImageFilter.blur(sigmaX: 64, sigmaY: 64),
|
||||||
child: Container(
|
child: Container(
|
||||||
@@ -928,6 +966,7 @@ class _DataSavingOverlay extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _OverlayCard extends StatelessWidget {
|
class _OverlayCard extends StatelessWidget {
|
||||||
final IconData icon;
|
final IconData icon;
|
||||||
final String title;
|
final String title;
|
||||||
@@ -956,15 +995,20 @@ class _OverlayCard extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Icon(icon, color: Colors.white, size: 24),
|
Icon(icon, color: Colors.white, size: 24),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
Text(title,
|
Text(
|
||||||
style: const TextStyle(
|
title,
|
||||||
color: Colors.white, fontWeight: FontWeight.w600),
|
style: const TextStyle(
|
||||||
textAlign: TextAlign.center),
|
color: Colors.white,
|
||||||
Text(subtitle,
|
fontWeight: FontWeight.w600,
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 13)),
|
),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
subtitle,
|
||||||
|
style: const TextStyle(color: Colors.white, fontSize: 13),
|
||||||
|
),
|
||||||
const Gap(4),
|
const Gap(4),
|
||||||
Text(hint,
|
Text(hint, style: const TextStyle(color: Colors.white, fontSize: 11)),
|
||||||
style: const TextStyle(color: Colors.white, fontSize: 11)),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
26
pubspec.lock
26
pubspec.lock
@@ -50,7 +50,7 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.3"
|
version: "2.0.3"
|
||||||
archive:
|
archive:
|
||||||
dependency: transitive
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: archive
|
name: archive
|
||||||
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
|
sha256: "2fde1607386ab523f7a36bb3e7edb43bd58e6edaf2ffb29d8a6d578b297fdbbd"
|
||||||
@@ -1789,6 +1789,14 @@ 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:
|
||||||
@@ -1877,6 +1885,14 @@ 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:
|
||||||
@@ -2250,6 +2266,14 @@ 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:
|
||||||
|
|||||||
@@ -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+129
|
version: 3.2.0+131
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
@@ -132,6 +132,8 @@ 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
|
||||||
@@ -142,6 +144,7 @@ dependencies:
|
|||||||
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
|
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