Compare commits

...

9 Commits

Author SHA1 Message Date
28b6eade48 🚀 Launch 3.2.0+134 2025-09-24 22:37:16 +08:00
1de7ef8c96 🐛 Fix bugs 2025-09-24 22:34:05 +08:00
67eac5dcf5 Optimized rpc 2025-09-24 22:14:40 +08:00
7a44bfa075 ⬆️ Upgrade packages 2025-09-24 21:29:21 +08:00
1c2f25a152 💄 Optimize leveling page 2025-09-24 21:21:51 +08:00
be26ea280e 🌐 Make file info localizable 2025-09-24 21:20:00 +08:00
b4996d069f 🐛 Fix bugs 2025-09-24 21:03:53 +08:00
bf4892b34d 🐛 Fix bugs 2025-09-24 20:52:56 +08:00
5f84751fd5 🐛 Fix file upload 2025-09-24 20:29:30 +08:00
29 changed files with 576 additions and 318 deletions

View File

@@ -264,14 +264,14 @@
"createStickerPack": "Create a Sticker Pack", "createStickerPack": "Create a Sticker Pack",
"editStickerPack": "Edit Sticker Pack", "editStickerPack": "Edit Sticker Pack",
"deleteStickerPack": "Delete Sticker Pack", "deleteStickerPack": "Delete Sticker Pack",
"deleteStickerPackHint": "Are you sure to delete this sticker pack? This action cannot be undone.", "deleteStickerPackHint": "Are you sure you want to delete this sticker pack? This action cannot be undone.",
"stickerPackPrefix": "Prefix", "stickerPackPrefix": "Prefix",
"stickerPackPrefixHint": "The prefix will be added before each stickers' slug in this pack.", "stickerPackPrefixHint": "The prefix will be added before each stickers' slug in this pack.",
"stickers": "Stickers", "stickers": "Stickers",
"createSticker": "Create a Sticker", "createSticker": "Create a Sticker",
"editSticker": "Edit Sticker", "editSticker": "Edit Sticker",
"deleteSticker": "Delete Sticker", "deleteSticker": "Delete Sticker",
"deleteStickerHint": "Are you sure to delete this sticker? This action cannot be undone.", "deleteStickerHint": "Are you sure you want to delete this sticker? This action cannot be undone.",
"stickerImage": "Image", "stickerImage": "Image",
"stickerSlug": "Slug", "stickerSlug": "Slug",
"stickerSlugHint": "The slug will be combined with the prefix to form the sticker's unique identifier.", "stickerSlugHint": "The slug will be combined with the prefix to form the sticker's unique identifier.",
@@ -350,11 +350,11 @@
"levelingStage12": "Transcendent", "levelingStage12": "Transcendent",
"fileUploadingProgress": "Uploading file #{}: {}%", "fileUploadingProgress": "Uploading file #{}: {}%",
"removeChatMember": "Remove Chat Room Member", "removeChatMember": "Remove Chat Room Member",
"removeChatMemberHint": "Are you sure to remove this member from the room?", "removeChatMemberHint": "Are you sure you want to remove this member from the room?",
"removeRealmMember": "Remove Realm Member", "removeRealmMember": "Remove Realm Member",
"removeRealmMemberHint": "Are you sure to remove this member from the realm?", "removeRealmMemberHint": "Are you sure you want to remove this member from the realm?",
"removePublisherMember": "Remove Publisher Member", "removePublisherMember": "Remove Publisher Member",
"removePublisherMemberHint": "Are you sure to remove this member from the publisher?", "removePublisherMemberHint": "Are you sure you want to remove this member from the publisher?",
"memberRole": "Member Role", "memberRole": "Member Role",
"memberRoleHint": "Greater number has higher permission.", "memberRoleHint": "Greater number has higher permission.",
"memberRoleEdit": "Edit role for @{}", "memberRoleEdit": "Edit role for @{}",
@@ -363,9 +363,9 @@
"brokenLink": "Unable open link {}... It might be broken or missing uri parts...", "brokenLink": "Unable open link {}... It might be broken or missing uri parts...",
"copyToClipboard": "Copy to clipboard", "copyToClipboard": "Copy to clipboard",
"leaveChatRoom": "Leave Chat Room", "leaveChatRoom": "Leave Chat Room",
"leaveChatRoomHint": "Are you sure to leave this chat room?", "leaveChatRoomHint": "Are you sure you want to leave this chat room?",
"leaveRealm": "Leave Realm", "leaveRealm": "Leave Realm",
"leaveRealmHint": "Are you sure to leave this realm?", "leaveRealmHint": "Are you sure you want to leave this realm?",
"walletNotFound": "Wallet not found", "walletNotFound": "Wallet not found",
"walletCreateHint": "You don't have a wallet yet. Create one to start using the Solar Network eWallet.", "walletCreateHint": "You don't have a wallet yet. Create one to start using the Solar Network eWallet.",
"walletCreate": "Create a Wallet", "walletCreate": "Create a Wallet",
@@ -468,7 +468,7 @@
"one": "{} is typing...", "one": "{} is typing...",
"other": "{} are typing..." "other": "{} are typing..."
}, },
"authDeviceEditLabel": "Edit Label", "authDeviceEditLabel": "Edit Device Label",
"authDeviceLabelTitle": "Edit Device Label", "authDeviceLabelTitle": "Edit Device Label",
"authDeviceLabelHint": "Enter a name for this device", "authDeviceLabelHint": "Enter a name for this device",
"authDeviceSwipeEditHint": "Swipe left to edit label", "authDeviceSwipeEditHint": "Swipe left to edit label",
@@ -536,7 +536,7 @@
"contactMethodPrimary": "Primary", "contactMethodPrimary": "Primary",
"contactMethodSetPrimary": "Set as Primary", "contactMethodSetPrimary": "Set as Primary",
"contactMethodSetPrimaryHint": "Set this contact method as your primary contact method for account recovery and notifications", "contactMethodSetPrimaryHint": "Set this contact method as your primary contact method for account recovery and notifications",
"contactMethodDeleteHint": "Are you sure to delete this contact method? This action cannot be undone.", "contactMethodDeleteHint": "Are you sure you want to delete this contact method? This action cannot be undone.",
"contactMethodMakePublic": "Make Public", "contactMethodMakePublic": "Make Public",
"contactMethodMakePrivate": "Make Private", "contactMethodMakePrivate": "Make Private",
"contactMethodPublic": "Public", "contactMethodPublic": "Public",
@@ -570,6 +570,7 @@
"checkInResultT2": "Mid", "checkInResultT2": "Mid",
"checkInResultT3": "Good", "checkInResultT3": "Good",
"checkInResultT4": "Best", "checkInResultT4": "Best",
"checkInResultT5": "Birthday",
"accountProfileView": "View Profile", "accountProfileView": "View Profile",
"unspecified": "Unspecified", "unspecified": "Unspecified",
"added": "Added", "added": "Added",
@@ -662,8 +663,6 @@
"abuseReportSuccess": "Report submitted successfully. Thank you for helping keep our community safe.", "abuseReportSuccess": "Report submitted successfully. Thank you for helping keep our community safe.",
"abuseReportError": "Failed to submit report. Please try again.", "abuseReportError": "Failed to submit report. Please try again.",
"abuseReportReasonRequired": "Please provide details about the issue", "abuseReportReasonRequired": "Please provide details about the issue",
"abuseReportSuccessTitle": "Report Submitted",
"abuseReportErrorTitle": "Error",
"abuseReportTypeSpam": "Spam or Misleading", "abuseReportTypeSpam": "Spam or Misleading",
"abuseReportTypeHarassment": "Harassment or Abuse", "abuseReportTypeHarassment": "Harassment or Abuse",
"abuseReportTypeInappropriate": "Inappropriate Content", "abuseReportTypeInappropriate": "Inappropriate Content",
@@ -845,11 +844,6 @@
"postCategorySports": "Sports", "postCategorySports": "Sports",
"postCategoryFinance": "Finance", "postCategoryFinance": "Finance",
"postCategoryLife": "Life", "postCategoryLife": "Life",
"postCategoryArt": "Art",
"postCategoryStudy": "Study",
"postCategoryGaming": "Gaming",
"postCategoryProgramming": "Programming",
"postCategoryMusic": "Music",
"links": "Links", "links": "Links",
"addLink": "Add link", "addLink": "Add link",
"linkKey": "Link Name", "linkKey": "Link Name",
@@ -1062,5 +1056,12 @@
"deleteRecycledFiles": "Delete Recycled Files", "deleteRecycledFiles": "Delete Recycled Files",
"recycledFilesDeleted": "Recycled files deleted successfully", "recycledFilesDeleted": "Recycled files deleted successfully",
"failedToDeleteRecycledFiles": "Failed to delete recycled files", "failedToDeleteRecycledFiles": "Failed to delete recycled files",
"upload": "Upload" "upload": "Upload",
"fileInfoTitle": "File Information",
"fileHashCopied": "File hash copied to clipboard",
"fileIdCopied": "File ID copied to clipboard",
"fileNameCopied": "File name copied to clipboard",
"fileMetadata": "File Metadata",
"userMetadata": "User Metadata",
"valueCopied": "Value copied to clipboard"
} }

View File

@@ -50,18 +50,18 @@ PODS:
- Firebase/Messaging (12.2.0): - Firebase/Messaging (12.2.0):
- Firebase/CoreOnly - Firebase/CoreOnly
- FirebaseMessaging (~> 12.2.0) - FirebaseMessaging (~> 12.2.0)
- firebase_analytics (12.0.1): - firebase_analytics (12.0.2):
- firebase_core - firebase_core
- FirebaseAnalytics (= 12.2.0) - FirebaseAnalytics (= 12.2.0)
- Flutter - Flutter
- firebase_core (4.1.0): - firebase_core (4.1.1):
- Firebase/CoreOnly (= 12.2.0) - Firebase/CoreOnly (= 12.2.0)
- Flutter - Flutter
- firebase_crashlytics (5.0.1): - firebase_crashlytics (5.0.2):
- Firebase/Crashlytics (= 12.2.0) - Firebase/Crashlytics (= 12.2.0)
- firebase_core - firebase_core
- Flutter - Flutter
- firebase_messaging (16.0.1): - firebase_messaging (16.0.2):
- Firebase/Messaging (= 12.2.0) - Firebase/Messaging (= 12.2.0)
- firebase_core - firebase_core
- Flutter - Flutter
@@ -476,10 +476,10 @@ SPEC CHECKSUMS:
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6 file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1 Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
firebase_analytics: 111ff65791a430356bd6c7e4d7339537fc6a15ae firebase_analytics: 8c78ce6224e0623152379d6cc7ef3d9098477b7e
firebase_core: 3ff52146406557dddd01d570e807e203ec7e1302 firebase_core: dfc4bd142bee4bc53a5d482397ca322c2dd3165d
firebase_crashlytics: 3637078b718a52dc9fb4d64e37c969e86b87ff6f firebase_crashlytics: e55dcf895eed0dd87c447dd5aff8db7f1bb8bbdb
firebase_messaging: 3dcc998dd98e1e54af75d0cccae8606eba43553c firebase_messaging: 38c66c1184695b0c87abe51d40fc590718abed1a
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8 FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5 FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5

View File

@@ -33,17 +33,27 @@ class AppDatabase extends _$AppDatabase {
await _migrateToVersion6(m); await _migrateToVersion6(m);
} }
if (from < 7) { if (from < 7) {
// Add new columns from SnChatMessage // Add new columns from SnChatMessage, ignore if they already exist
await m.addColumn(chatMessages, chatMessages.updatedAt); final columnsToAdd = [
await m.addColumn(chatMessages, chatMessages.deletedAt); chatMessages.updatedAt,
await m.addColumn(chatMessages, chatMessages.type); chatMessages.deletedAt,
await m.addColumn(chatMessages, chatMessages.meta); chatMessages.type,
await m.addColumn(chatMessages, chatMessages.membersMentioned); chatMessages.meta,
await m.addColumn(chatMessages, chatMessages.editedAt); chatMessages.membersMentioned,
await m.addColumn(chatMessages, chatMessages.attachments); chatMessages.editedAt,
await m.addColumn(chatMessages, chatMessages.reactions); chatMessages.attachments,
await m.addColumn(chatMessages, chatMessages.repliedMessageId); chatMessages.reactions,
await m.addColumn(chatMessages, chatMessages.forwardedMessageId); chatMessages.repliedMessageId,
chatMessages.forwardedMessageId,
];
for (final column in columnsToAdd) {
try {
await m.addColumn(chatMessages, column);
} catch (e) {
// Column already exists, skip
}
}
} }
}, },
); );

View File

@@ -98,6 +98,7 @@ sealed class SnAccountStatus with _$SnAccountStatus {
required bool isNotDisturb, required bool isNotDisturb,
required bool isCustomized, required bool isCustomized,
@Default("") String label, @Default("") String label,
required Map<String, dynamic>? meta,
required DateTime? clearedAt, required DateTime? clearedAt,
required String accountId, required String accountId,
required DateTime createdAt, required DateTime createdAt,

View File

@@ -1053,7 +1053,7 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
/// @nodoc /// @nodoc
mixin _$SnAccountStatus { mixin _$SnAccountStatus {
String get id; int get attitude; bool get isOnline; bool get isInvisible; bool get isNotDisturb; bool get isCustomized; String get label; DateTime? get clearedAt; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; int get attitude; bool get isOnline; bool get isInvisible; bool get isNotDisturb; bool get isCustomized; String get label; Map<String, dynamic>? get meta; DateTime? get clearedAt; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
/// Create a copy of SnAccountStatus /// Create a copy of SnAccountStatus
/// 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)
@@ -1066,16 +1066,16 @@ $SnAccountStatusCopyWith<SnAccountStatus> get copyWith => _$SnAccountStatusCopyW
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountStatus&&(identical(other.id, id) || other.id == id)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.isOnline, isOnline) || other.isOnline == isOnline)&&(identical(other.isInvisible, isInvisible) || other.isInvisible == isInvisible)&&(identical(other.isNotDisturb, isNotDisturb) || other.isNotDisturb == isNotDisturb)&&(identical(other.isCustomized, isCustomized) || other.isCustomized == isCustomized)&&(identical(other.label, label) || other.label == label)&&(identical(other.clearedAt, clearedAt) || other.clearedAt == clearedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(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 SnAccountStatus&&(identical(other.id, id) || other.id == id)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.isOnline, isOnline) || other.isOnline == isOnline)&&(identical(other.isInvisible, isInvisible) || other.isInvisible == isInvisible)&&(identical(other.isNotDisturb, isNotDisturb) || other.isNotDisturb == isNotDisturb)&&(identical(other.isCustomized, isCustomized) || other.isCustomized == isCustomized)&&(identical(other.label, label) || other.label == label)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.clearedAt, clearedAt) || other.clearedAt == clearedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(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,attitude,isOnline,isInvisible,isNotDisturb,isCustomized,label,clearedAt,accountId,createdAt,updatedAt,deletedAt); int get hashCode => Object.hash(runtimeType,id,attitude,isOnline,isInvisible,isNotDisturb,isCustomized,label,const DeepCollectionEquality().hash(meta),clearedAt,accountId,createdAt,updatedAt,deletedAt);
@override @override
String toString() { String toString() {
return 'SnAccountStatus(id: $id, attitude: $attitude, isOnline: $isOnline, isInvisible: $isInvisible, isNotDisturb: $isNotDisturb, isCustomized: $isCustomized, label: $label, clearedAt: $clearedAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; return 'SnAccountStatus(id: $id, attitude: $attitude, isOnline: $isOnline, isInvisible: $isInvisible, isNotDisturb: $isNotDisturb, isCustomized: $isCustomized, label: $label, meta: $meta, clearedAt: $clearedAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
} }
@@ -1086,7 +1086,7 @@ abstract mixin class $SnAccountStatusCopyWith<$Res> {
factory $SnAccountStatusCopyWith(SnAccountStatus value, $Res Function(SnAccountStatus) _then) = _$SnAccountStatusCopyWithImpl; factory $SnAccountStatusCopyWith(SnAccountStatus value, $Res Function(SnAccountStatus) _then) = _$SnAccountStatusCopyWithImpl;
@useResult @useResult
$Res call({ $Res call({
String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, Map<String, dynamic>? meta, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
}); });
@@ -1103,7 +1103,7 @@ class _$SnAccountStatusCopyWithImpl<$Res>
/// Create a copy of SnAccountStatus /// Create a copy of SnAccountStatus
/// 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? attitude = null,Object? isOnline = null,Object? isInvisible = null,Object? isNotDisturb = null,Object? isCustomized = null,Object? label = null,Object? clearedAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? attitude = null,Object? isOnline = null,Object? isInvisible = null,Object? isNotDisturb = null,Object? isCustomized = null,Object? label = null,Object? meta = freezed,Object? clearedAt = freezed,Object? accountId = 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,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable as String,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
@@ -1112,7 +1112,8 @@ as bool,isInvisible: null == isInvisible ? _self.isInvisible : isInvisible // ig
as bool,isNotDisturb: null == isNotDisturb ? _self.isNotDisturb : isNotDisturb // ignore: cast_nullable_to_non_nullable as bool,isNotDisturb: null == isNotDisturb ? _self.isNotDisturb : isNotDisturb // ignore: cast_nullable_to_non_nullable
as bool,isCustomized: null == isCustomized ? _self.isCustomized : isCustomized // ignore: cast_nullable_to_non_nullable as bool,isCustomized: null == isCustomized ? _self.isCustomized : isCustomized // ignore: cast_nullable_to_non_nullable
as bool,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable as bool,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
as String,clearedAt: freezed == clearedAt ? _self.clearedAt : clearedAt // ignore: cast_nullable_to_non_nullable as String,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,clearedAt: freezed == clearedAt ? _self.clearedAt : clearedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable as DateTime?,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
@@ -1199,10 +1200,10 @@ return $default(_that);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, DateTime? clearedAt, 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, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, Map<String, dynamic>? meta, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) { switch (_that) {
case _SnAccountStatus() when $default != null: case _SnAccountStatus() when $default != null:
return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.isNotDisturb,_that.isCustomized,_that.label,_that.clearedAt,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.isNotDisturb,_that.isCustomized,_that.label,_that.meta,_that.clearedAt,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return orElse(); return orElse();
} }
@@ -1220,10 +1221,10 @@ return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.i
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; @optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, Map<String, dynamic>? meta, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
switch (_that) { switch (_that) {
case _SnAccountStatus(): case _SnAccountStatus():
return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.isNotDisturb,_that.isCustomized,_that.label,_that.clearedAt,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);} return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.isNotDisturb,_that.isCustomized,_that.label,_that.meta,_that.clearedAt,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
} }
/// A variant of `when` that fallback to returning `null` /// A variant of `when` that fallback to returning `null`
/// ///
@@ -1237,10 +1238,10 @@ return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.i
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, Map<String, dynamic>? meta, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
switch (_that) { switch (_that) {
case _SnAccountStatus() when $default != null: case _SnAccountStatus() when $default != null:
return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.isNotDisturb,_that.isCustomized,_that.label,_that.clearedAt,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.isNotDisturb,_that.isCustomized,_that.label,_that.meta,_that.clearedAt,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return null; return null;
} }
@@ -1252,7 +1253,7 @@ return $default(_that.id,_that.attitude,_that.isOnline,_that.isInvisible,_that.i
@JsonSerializable() @JsonSerializable()
class _SnAccountStatus implements SnAccountStatus { class _SnAccountStatus implements SnAccountStatus {
const _SnAccountStatus({required this.id, required this.attitude, required this.isOnline, required this.isInvisible, required this.isNotDisturb, required this.isCustomized, this.label = "", required this.clearedAt, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}); const _SnAccountStatus({required this.id, required this.attitude, required this.isOnline, required this.isInvisible, required this.isNotDisturb, required this.isCustomized, this.label = "", required final Map<String, dynamic>? meta, required this.clearedAt, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta;
factory _SnAccountStatus.fromJson(Map<String, dynamic> json) => _$SnAccountStatusFromJson(json); factory _SnAccountStatus.fromJson(Map<String, dynamic> json) => _$SnAccountStatusFromJson(json);
@override final String id; @override final String id;
@@ -1262,6 +1263,15 @@ class _SnAccountStatus implements SnAccountStatus {
@override final bool isNotDisturb; @override final bool isNotDisturb;
@override final bool isCustomized; @override final bool isCustomized;
@override@JsonKey() final String label; @override@JsonKey() final String label;
final Map<String, dynamic>? _meta;
@override Map<String, dynamic>? get meta {
final value = _meta;
if (value == null) return null;
if (_meta is EqualUnmodifiableMapView) return _meta;
// ignore: implicit_dynamic_type
return EqualUnmodifiableMapView(value);
}
@override final DateTime? clearedAt; @override final DateTime? clearedAt;
@override final String accountId; @override final String accountId;
@override final DateTime createdAt; @override final DateTime createdAt;
@@ -1281,16 +1291,16 @@ Map<String, dynamic> toJson() {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountStatus&&(identical(other.id, id) || other.id == id)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.isOnline, isOnline) || other.isOnline == isOnline)&&(identical(other.isInvisible, isInvisible) || other.isInvisible == isInvisible)&&(identical(other.isNotDisturb, isNotDisturb) || other.isNotDisturb == isNotDisturb)&&(identical(other.isCustomized, isCustomized) || other.isCustomized == isCustomized)&&(identical(other.label, label) || other.label == label)&&(identical(other.clearedAt, clearedAt) || other.clearedAt == clearedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(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 _SnAccountStatus&&(identical(other.id, id) || other.id == id)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.isOnline, isOnline) || other.isOnline == isOnline)&&(identical(other.isInvisible, isInvisible) || other.isInvisible == isInvisible)&&(identical(other.isNotDisturb, isNotDisturb) || other.isNotDisturb == isNotDisturb)&&(identical(other.isCustomized, isCustomized) || other.isCustomized == isCustomized)&&(identical(other.label, label) || other.label == label)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.clearedAt, clearedAt) || other.clearedAt == clearedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(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,attitude,isOnline,isInvisible,isNotDisturb,isCustomized,label,clearedAt,accountId,createdAt,updatedAt,deletedAt); int get hashCode => Object.hash(runtimeType,id,attitude,isOnline,isInvisible,isNotDisturb,isCustomized,label,const DeepCollectionEquality().hash(_meta),clearedAt,accountId,createdAt,updatedAt,deletedAt);
@override @override
String toString() { String toString() {
return 'SnAccountStatus(id: $id, attitude: $attitude, isOnline: $isOnline, isInvisible: $isInvisible, isNotDisturb: $isNotDisturb, isCustomized: $isCustomized, label: $label, clearedAt: $clearedAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; return 'SnAccountStatus(id: $id, attitude: $attitude, isOnline: $isOnline, isInvisible: $isInvisible, isNotDisturb: $isNotDisturb, isCustomized: $isCustomized, label: $label, meta: $meta, clearedAt: $clearedAt, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
} }
@@ -1301,7 +1311,7 @@ abstract mixin class _$SnAccountStatusCopyWith<$Res> implements $SnAccountStatus
factory _$SnAccountStatusCopyWith(_SnAccountStatus value, $Res Function(_SnAccountStatus) _then) = __$SnAccountStatusCopyWithImpl; factory _$SnAccountStatusCopyWith(_SnAccountStatus value, $Res Function(_SnAccountStatus) _then) = __$SnAccountStatusCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $Res call({
String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt String id, int attitude, bool isOnline, bool isInvisible, bool isNotDisturb, bool isCustomized, String label, Map<String, dynamic>? meta, DateTime? clearedAt, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
}); });
@@ -1318,7 +1328,7 @@ class __$SnAccountStatusCopyWithImpl<$Res>
/// Create a copy of SnAccountStatus /// Create a copy of SnAccountStatus
/// 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? attitude = null,Object? isOnline = null,Object? isInvisible = null,Object? isNotDisturb = null,Object? isCustomized = null,Object? label = null,Object? clearedAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? attitude = null,Object? isOnline = null,Object? isInvisible = null,Object? isNotDisturb = null,Object? isCustomized = null,Object? label = null,Object? meta = freezed,Object? clearedAt = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
return _then(_SnAccountStatus( return _then(_SnAccountStatus(
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,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable as String,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
@@ -1327,7 +1337,8 @@ as bool,isInvisible: null == isInvisible ? _self.isInvisible : isInvisible // ig
as bool,isNotDisturb: null == isNotDisturb ? _self.isNotDisturb : isNotDisturb // ignore: cast_nullable_to_non_nullable as bool,isNotDisturb: null == isNotDisturb ? _self.isNotDisturb : isNotDisturb // ignore: cast_nullable_to_non_nullable
as bool,isCustomized: null == isCustomized ? _self.isCustomized : isCustomized // ignore: cast_nullable_to_non_nullable as bool,isCustomized: null == isCustomized ? _self.isCustomized : isCustomized // ignore: cast_nullable_to_non_nullable
as bool,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable as bool,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
as String,clearedAt: freezed == clearedAt ? _self.clearedAt : clearedAt // ignore: cast_nullable_to_non_nullable as String,meta: freezed == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,clearedAt: freezed == clearedAt ? _self.clearedAt : clearedAt // ignore: cast_nullable_to_non_nullable
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable as DateTime?,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

View File

@@ -158,6 +158,7 @@ _SnAccountStatus _$SnAccountStatusFromJson(Map<String, dynamic> json) =>
isNotDisturb: json['is_not_disturb'] as bool, isNotDisturb: json['is_not_disturb'] as bool,
isCustomized: json['is_customized'] as bool, isCustomized: json['is_customized'] as bool,
label: json['label'] as String? ?? "", label: json['label'] as String? ?? "",
meta: json['meta'] as Map<String, dynamic>?,
clearedAt: clearedAt:
json['cleared_at'] == null json['cleared_at'] == null
? null ? null
@@ -180,6 +181,7 @@ Map<String, dynamic> _$SnAccountStatusToJson(_SnAccountStatus instance) =>
'is_not_disturb': instance.isNotDisturb, 'is_not_disturb': instance.isNotDisturb,
'is_customized': instance.isCustomized, 'is_customized': instance.isCustomized,
'label': instance.label, 'label': instance.label,
'meta': instance.meta,
'cleared_at': instance.clearedAt?.toIso8601String(), 'cleared_at': instance.clearedAt?.toIso8601String(),
'account_id': instance.accountId, 'account_id': instance.accountId,
'created_at': instance.createdAt.toIso8601String(), 'created_at': instance.createdAt.toIso8601String(),

View File

@@ -1,4 +1,5 @@
import 'package:freezed_annotation/freezed_annotation.dart'; import 'package:freezed_annotation/freezed_annotation.dart';
import 'package:island/models/file_pool.dart';
part 'file.freezed.dart'; part 'file.freezed.dart';
part 'file.g.dart'; part 'file.g.dart';
@@ -42,6 +43,7 @@ sealed class SnCloudFile with _$SnCloudFile {
required String? description, required String? description,
required Map<String, dynamic>? fileMeta, required Map<String, dynamic>? fileMeta,
required Map<String, dynamic>? userMeta, required Map<String, dynamic>? userMeta,
required SnFilePool? pool,
@Default([]) List<int> sensitiveMarks, @Default([]) List<int> sensitiveMarks,
required String? mimeType, required String? mimeType,
required String? hash, required String? hash,

View File

@@ -278,7 +278,7 @@ as bool,
/// @nodoc /// @nodoc
mixin _$SnCloudFile { mixin _$SnCloudFile {
String get id; String get name; String? get description; Map<String, dynamic>? get fileMeta; Map<String, dynamic>? get userMeta; List<int> get sensitiveMarks; String? get mimeType; String? get hash; int get size; DateTime? get uploadedAt; String? get uploadedTo; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String get name; String? get description; Map<String, dynamic>? get fileMeta; Map<String, dynamic>? get userMeta; SnFilePool? get pool; List<int> get sensitiveMarks; String? get mimeType; String? get hash; int get size; DateTime? get uploadedAt; String? get uploadedTo; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
/// Create a copy of SnCloudFile /// Create a copy of SnCloudFile
/// 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)
@@ -291,16 +291,16 @@ $SnCloudFileCopyWith<SnCloudFile> get copyWith => _$SnCloudFileCopyWithImpl<SnCl
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.fileMeta, fileMeta)&&const DeepCollectionEquality().equals(other.userMeta, userMeta)&&const DeepCollectionEquality().equals(other.sensitiveMarks, sensitiveMarks)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(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 SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.fileMeta, fileMeta)&&const DeepCollectionEquality().equals(other.userMeta, userMeta)&&(identical(other.pool, pool) || other.pool == pool)&&const DeepCollectionEquality().equals(other.sensitiveMarks, sensitiveMarks)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(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,description,const DeepCollectionEquality().hash(fileMeta),const DeepCollectionEquality().hash(userMeta),const DeepCollectionEquality().hash(sensitiveMarks),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt); int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(fileMeta),const DeepCollectionEquality().hash(userMeta),pool,const DeepCollectionEquality().hash(sensitiveMarks),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
@override @override
String toString() { String toString() {
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, sensitiveMarks: $sensitiveMarks, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, pool: $pool, sensitiveMarks: $sensitiveMarks, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
} }
@@ -311,11 +311,11 @@ abstract mixin class $SnCloudFileCopyWith<$Res> {
factory $SnCloudFileCopyWith(SnCloudFile value, $Res Function(SnCloudFile) _then) = _$SnCloudFileCopyWithImpl; factory $SnCloudFileCopyWith(SnCloudFile value, $Res Function(SnCloudFile) _then) = _$SnCloudFileCopyWithImpl;
@useResult @useResult
$Res call({ $Res call({
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, SnFilePool? pool, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
}); });
$SnFilePoolCopyWith<$Res>? get pool;
} }
/// @nodoc /// @nodoc
@@ -328,14 +328,15 @@ class _$SnCloudFileCopyWithImpl<$Res>
/// Create a copy of SnCloudFile /// Create a copy of SnCloudFile
/// 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? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? sensitiveMarks = null,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { @pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? pool = freezed,Object? sensitiveMarks = null,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,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,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,fileMeta: freezed == fileMeta ? _self.fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable as String?,fileMeta: freezed == fileMeta ? _self.fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self.userMeta : userMeta // ignore: cast_nullable_to_non_nullable as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self.userMeta : userMeta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,sensitiveMarks: null == sensitiveMarks ? _self.sensitiveMarks : sensitiveMarks // ignore: cast_nullable_to_non_nullable as Map<String, dynamic>?,pool: freezed == pool ? _self.pool : pool // ignore: cast_nullable_to_non_nullable
as SnFilePool?,sensitiveMarks: null == sensitiveMarks ? _self.sensitiveMarks : sensitiveMarks // ignore: cast_nullable_to_non_nullable
as List<int>,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable as List<int>,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable
as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
@@ -347,7 +348,19 @@ as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ign
as DateTime?, as DateTime?,
)); ));
} }
/// Create a copy of SnCloudFile
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnFilePoolCopyWith<$Res>? get pool {
if (_self.pool == null) {
return null;
}
return $SnFilePoolCopyWith<$Res>(_self.pool!, (value) {
return _then(_self.copyWith(pool: value));
});
}
} }
@@ -426,10 +439,10 @@ return $default(_that);case _:
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, 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? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, SnFilePool? pool, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
switch (_that) { switch (_that) {
case _SnCloudFile() when $default != null: case _SnCloudFile() when $default != null:
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.pool,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return orElse(); return orElse();
} }
@@ -447,10 +460,10 @@ return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userM
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this; @optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, SnFilePool? pool, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
switch (_that) { switch (_that) {
case _SnCloudFile(): case _SnCloudFile():
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);} return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.pool,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);}
} }
/// A variant of `when` that fallback to returning `null` /// A variant of `when` that fallback to returning `null`
/// ///
@@ -464,10 +477,10 @@ return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userM
/// } /// }
/// ``` /// ```
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this; @optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, SnFilePool? pool, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
switch (_that) { switch (_that) {
case _SnCloudFile() when $default != null: case _SnCloudFile() when $default != null:
return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _: return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userMeta,_that.pool,_that.sensitiveMarks,_that.mimeType,_that.hash,_that.size,_that.uploadedAt,_that.uploadedTo,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
return null; return null;
} }
@@ -479,7 +492,7 @@ return $default(_that.id,_that.name,_that.description,_that.fileMeta,_that.userM
@JsonSerializable() @JsonSerializable()
class _SnCloudFile implements SnCloudFile { class _SnCloudFile implements SnCloudFile {
const _SnCloudFile({required this.id, required this.name, required this.description, required final Map<String, dynamic>? fileMeta, required final Map<String, dynamic>? userMeta, final List<int> sensitiveMarks = const [], required this.mimeType, required this.hash, required this.size, required this.uploadedAt, required this.uploadedTo, required this.createdAt, required this.updatedAt, required this.deletedAt}): _fileMeta = fileMeta,_userMeta = userMeta,_sensitiveMarks = sensitiveMarks; const _SnCloudFile({required this.id, required this.name, required this.description, required final Map<String, dynamic>? fileMeta, required final Map<String, dynamic>? userMeta, required this.pool, final List<int> sensitiveMarks = const [], required this.mimeType, required this.hash, required this.size, required this.uploadedAt, required this.uploadedTo, required this.createdAt, required this.updatedAt, required this.deletedAt}): _fileMeta = fileMeta,_userMeta = userMeta,_sensitiveMarks = sensitiveMarks;
factory _SnCloudFile.fromJson(Map<String, dynamic> json) => _$SnCloudFileFromJson(json); factory _SnCloudFile.fromJson(Map<String, dynamic> json) => _$SnCloudFileFromJson(json);
@override final String id; @override final String id;
@@ -503,6 +516,7 @@ class _SnCloudFile implements SnCloudFile {
return EqualUnmodifiableMapView(value); return EqualUnmodifiableMapView(value);
} }
@override final SnFilePool? pool;
final List<int> _sensitiveMarks; final List<int> _sensitiveMarks;
@override@JsonKey() List<int> get sensitiveMarks { @override@JsonKey() List<int> get sensitiveMarks {
if (_sensitiveMarks is EqualUnmodifiableListView) return _sensitiveMarks; if (_sensitiveMarks is EqualUnmodifiableListView) return _sensitiveMarks;
@@ -532,16 +546,16 @@ Map<String, dynamic> toJson() {
@override @override
bool operator ==(Object other) { bool operator ==(Object other) {
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._fileMeta, _fileMeta)&&const DeepCollectionEquality().equals(other._userMeta, _userMeta)&&const DeepCollectionEquality().equals(other._sensitiveMarks, _sensitiveMarks)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(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 _SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._fileMeta, _fileMeta)&&const DeepCollectionEquality().equals(other._userMeta, _userMeta)&&(identical(other.pool, pool) || other.pool == pool)&&const DeepCollectionEquality().equals(other._sensitiveMarks, _sensitiveMarks)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(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,description,const DeepCollectionEquality().hash(_fileMeta),const DeepCollectionEquality().hash(_userMeta),const DeepCollectionEquality().hash(_sensitiveMarks),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt); int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(_fileMeta),const DeepCollectionEquality().hash(_userMeta),pool,const DeepCollectionEquality().hash(_sensitiveMarks),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
@override @override
String toString() { String toString() {
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, sensitiveMarks: $sensitiveMarks, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)'; return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, pool: $pool, sensitiveMarks: $sensitiveMarks, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
} }
@@ -552,11 +566,11 @@ abstract mixin class _$SnCloudFileCopyWith<$Res> implements $SnCloudFileCopyWith
factory _$SnCloudFileCopyWith(_SnCloudFile value, $Res Function(_SnCloudFile) _then) = __$SnCloudFileCopyWithImpl; factory _$SnCloudFileCopyWith(_SnCloudFile value, $Res Function(_SnCloudFile) _then) = __$SnCloudFileCopyWithImpl;
@override @useResult @override @useResult
$Res call({ $Res call({
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, SnFilePool? pool, List<int> sensitiveMarks, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
}); });
@override $SnFilePoolCopyWith<$Res>? get pool;
} }
/// @nodoc /// @nodoc
@@ -569,14 +583,15 @@ class __$SnCloudFileCopyWithImpl<$Res>
/// Create a copy of SnCloudFile /// Create a copy of SnCloudFile
/// 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? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? sensitiveMarks = null,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) { @override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? pool = freezed,Object? sensitiveMarks = null,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
return _then(_SnCloudFile( return _then(_SnCloudFile(
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,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
as String?,fileMeta: freezed == fileMeta ? _self._fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable as String?,fileMeta: freezed == fileMeta ? _self._fileMeta : fileMeta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self._userMeta : userMeta // ignore: cast_nullable_to_non_nullable as Map<String, dynamic>?,userMeta: freezed == userMeta ? _self._userMeta : userMeta // ignore: cast_nullable_to_non_nullable
as Map<String, dynamic>?,sensitiveMarks: null == sensitiveMarks ? _self._sensitiveMarks : sensitiveMarks // ignore: cast_nullable_to_non_nullable as Map<String, dynamic>?,pool: freezed == pool ? _self.pool : pool // ignore: cast_nullable_to_non_nullable
as SnFilePool?,sensitiveMarks: null == sensitiveMarks ? _self._sensitiveMarks : sensitiveMarks // ignore: cast_nullable_to_non_nullable
as List<int>,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable as List<int>,mimeType: freezed == mimeType ? _self.mimeType : mimeType // ignore: cast_nullable_to_non_nullable
as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to_non_nullable
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
@@ -589,7 +604,19 @@ as DateTime?,
)); ));
} }
/// Create a copy of SnCloudFile
/// with the given fields replaced by the non-null parameter values.
@override
@pragma('vm:prefer-inline')
$SnFilePoolCopyWith<$Res>? get pool {
if (_self.pool == null) {
return null;
}
return $SnFilePoolCopyWith<$Res>(_self.pool!, (value) {
return _then(_self.copyWith(pool: value));
});
}
} }
// dart format on // dart format on

View File

@@ -33,6 +33,10 @@ _SnCloudFile _$SnCloudFileFromJson(Map<String, dynamic> json) => _SnCloudFile(
description: json['description'] as String?, description: json['description'] as String?,
fileMeta: json['file_meta'] as Map<String, dynamic>?, fileMeta: json['file_meta'] as Map<String, dynamic>?,
userMeta: json['user_meta'] as Map<String, dynamic>?, userMeta: json['user_meta'] as Map<String, dynamic>?,
pool:
json['pool'] == null
? null
: SnFilePool.fromJson(json['pool'] as Map<String, dynamic>),
sensitiveMarks: sensitiveMarks:
(json['sensitive_marks'] as List<dynamic>?) (json['sensitive_marks'] as List<dynamic>?)
?.map((e) => (e as num).toInt()) ?.map((e) => (e as num).toInt())
@@ -61,6 +65,7 @@ Map<String, dynamic> _$SnCloudFileToJson(_SnCloudFile instance) =>
'description': instance.description, 'description': instance.description,
'file_meta': instance.fileMeta, 'file_meta': instance.fileMeta,
'user_meta': instance.userMeta, 'user_meta': instance.userMeta,
'pool': instance.pool?.toJson(),
'sensitive_marks': instance.sensitiveMarks, 'sensitive_marks': instance.sensitiveMarks,
'mime_type': instance.mimeType, 'mime_type': instance.mimeType,
'hash': instance.hash, 'hash': instance.hash,

View File

@@ -23,31 +23,3 @@ sealed class SnFilePool with _$SnFilePool {
factory SnFilePool.fromJson(Map<String, dynamic> json) => factory SnFilePool.fromJson(Map<String, dynamic> json) =>
_$SnFilePoolFromJson(json); _$SnFilePoolFromJson(json);
} }
extension SnFilePoolList on List<SnFilePool> {
static List<SnFilePool> listFromResponse(dynamic data) {
if (data is List) {
return data
.whereType<Map<String, dynamic>>()
.map(SnFilePool.fromJson)
.toList();
}
throw ArgumentError('Unexpected response format: $data');
}
List<SnFilePool> filterValid() {
return where((p) {
final accept = p.policyConfig?['accept_types'];
if (accept is List) {
final acceptsOnlyMedia = accept.every((t) =>
t is String &&
(t.startsWith('image/') ||
t.startsWith('video/') ||
t.startsWith('audio/')));
if (acceptsOnlyMedia) return false;
}
return true;
}).toList();
}
}

View File

@@ -4,7 +4,9 @@ import 'dart:developer' as developer;
import 'dart:io'; import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/account.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/widgets/account/status.dart';
import 'package:shelf/shelf.dart'; import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf_io; import 'package:shelf/shelf_io.dart' as shelf_io;
import 'package:shelf_web_socket/shelf_web_socket.dart'; import 'package:shelf_web_socket/shelf_web_socket.dart';
@@ -390,17 +392,35 @@ final rpcServerStateProvider =
'message': (socket, dynamic data) async { 'message': (socket, dynamic data) async {
if (data['cmd'] == 'SET_ACTIVITY') { if (data['cmd'] == 'SET_ACTIVITY') {
notifier.addActivity( notifier.addActivity(
'Activity: ${data['args']['activity']['details'] ?? 'Unknown'}', 'Activity: ${data['args']['activity']['details'] ?? ''}',
); );
final label = data['args']['activity']['details'] ?? 'Unknown'; final label = data['args']['activity']['details'] ?? '';
final appId = socket.clientId; final appId = socket.clientId;
final meta = data['args']['activity'];
try { try {
await setRemoteActivityStatus( await setRemoteActivityStatus(
ref, ref,
label, label,
appId, appId,
data['args']['activity'], meta,
); );
final now = DateTime.now();
final status = SnAccountStatus(
id: 'local_$appId',
attitude: 0,
isOnline: true,
isInvisible: false,
isNotDisturb: false,
isCustomized: true,
label: label,
meta: meta,
clearedAt: null,
accountId: 'me',
createdAt: now,
updatedAt: now,
deletedAt: null,
);
ref.read(currentAccountStatusProvider.notifier).setStatus(status);
} catch (e) { } catch (e) {
developer.log( developer.log(
'Failed to set remote activity status: $e', 'Failed to set remote activity status: $e',
@@ -420,6 +440,7 @@ final rpcServerStateProvider =
final appId = socket.clientId; final appId = socket.clientId;
try { try {
await unsetRemoteActivityStatus(ref, appId); await unsetRemoteActivityStatus(ref, appId);
ref.read(currentAccountStatusProvider.notifier).clearStatus();
} catch (e) { } catch (e) {
developer.log( developer.log(
'Failed to unset remote activity status: $e', 'Failed to unset remote activity status: $e',

View File

@@ -6,23 +6,19 @@ import 'package:island/pods/network.dart';
final poolsProvider = FutureProvider<List<SnFilePool>>((ref) async { final poolsProvider = FutureProvider<List<SnFilePool>>((ref) async {
final dio = ref.watch(apiClientProvider); final dio = ref.watch(apiClientProvider);
final response = await dio.get('/drive/pools'); final response = await dio.get('/drive/pools');
final pools = SnFilePoolList.listFromResponse(response.data); return response.data
return pools.filterValid(); .map((e) => SnFilePool.fromJson(e))
.cast<SnFilePool>()
.toList();
}); });
String resolveDefaultPoolId(WidgetRef ref, List<SnFilePool> pools) { String? resolveDefaultPoolId(WidgetRef ref, List<SnFilePool> pools) {
final settings = ref.watch(appSettingsNotifierProvider); final settings = ref.watch(appSettingsNotifierProvider);
final validPools = pools.filterValid();
final configuredId = settings.defaultPoolId; final configuredId = settings.defaultPoolId;
if (configuredId != null && validPools.any((p) => p.id == configuredId)) { if (configuredId != null && pools.any((p) => p.id == configuredId)) {
return configuredId; return configuredId;
} }
if (validPools.isNotEmpty) { return pools.firstOrNull?.id;
return validPools.first.id;
} }
// DEFAULT: Solar Network Driver
return '500e5ed8-bd44-4359-bc0a-ec85e2adf447'; }

View File

@@ -10,17 +10,19 @@ Future<void> resetDatabase(WidgetRef ref) async {
if (kIsWeb) return; if (kIsWeb) return;
final db = ref.read(databaseProvider); final db = ref.read(databaseProvider);
final basepath = await getApplicationSupportDirectory();
final file = File(join(basepath.path, 'solar_network_data.sqlite'));
// Close current database connection // Close current database connection
db.close(); await db.close();
// Delete database file // Get the correct database file path
final dbFolder = await getApplicationDocumentsDirectory();
final file = File(join(dbFolder.path, 'solar_network_data.sqlite'));
// Delete database file if it exists
if (await file.exists()) { if (await file.exists()) {
await file.delete(); await file.delete();
} }
// Force refresh the database provider // Force refresh the database provider to create a new instance
ref.invalidate(databaseProvider); ref.invalidate(databaseProvider);
} }

View File

@@ -148,7 +148,6 @@ class LevelingScreen extends HookConsumerWidget {
return Center( return Center(
child: Container( child: Container(
padding: const EdgeInsets.symmetric(horizontal: 20), padding: const EdgeInsets.symmetric(horizontal: 20),
constraints: const BoxConstraints(maxWidth: 480),
child: CustomScrollView( child: CustomScrollView(
slivers: [ slivers: [
const SliverGap(20), const SliverGap(20),
@@ -180,6 +179,12 @@ class LevelingScreen extends HookConsumerWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
Text(
'${'levelingProgressLevel'.tr(args: [currentLevel.toString()])} / 120',
textAlign: TextAlign.start,
style: Theme.of(context).textTheme.bodySmall,
),
const Gap(8),
LinearProgressIndicator( LinearProgressIndicator(
value: currentLevel / 120, value: currentLevel / 120,
minHeight: 10, minHeight: 10,
@@ -190,12 +195,6 @@ class LevelingScreen extends HookConsumerWidget {
Theme.of(context).colorScheme.surfaceContainerHigh, Theme.of(context).colorScheme.surfaceContainerHigh,
borderRadius: BorderRadius.circular(32), borderRadius: BorderRadius.circular(32),
), ),
const Gap(8),
Text(
'${'levelingProgressLevel'.tr(args: [currentLevel.toString()])} / 120',
textAlign: TextAlign.right,
style: Theme.of(context).textTheme.bodySmall,
),
], ],
).padding(horizontal: 16, top: 16, bottom: 12), ).padding(horizontal: 16, top: 16, bottom: 12),
), ),
@@ -272,9 +271,6 @@ class LevelingScreen extends HookConsumerWidget {
return SingleChildScrollView( return SingleChildScrollView(
padding: getTabbedPadding(context, horizontal: 20, vertical: 20), padding: getTabbedPadding(context, horizontal: 20, vertical: 20),
child: Center(
child: ConstrainedBox(
constraints: const BoxConstraints(maxWidth: 480),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.stretch, crossAxisAlignment: CrossAxisAlignment.stretch,
children: [ children: [
@@ -282,8 +278,6 @@ class LevelingScreen extends HookConsumerWidget {
const Gap(16), const Gap(16),
], ],
), ),
),
),
); );
} }

View File

@@ -935,7 +935,7 @@ class _ChatAttachmentUploaderSheetState
if (snapshot.hasError) { if (snapshot.hasError) {
return Center(child: Text('errorLoadingPools'.tr())); return Center(child: Text('errorLoadingPools'.tr()));
} }
final pools = snapshot.data!.filterValid(); final pools = snapshot.data!;
selectedPoolId ??= resolveDefaultPoolId(widget.ref, pools); selectedPoolId ??= resolveDefaultPoolId(widget.ref, pools);
return Column( return Column(
@@ -1162,9 +1162,7 @@ class _ChatAttachmentUploaderSheetState
// Get the selected pool to check constraints // Get the selected pool to check constraints
final pools = await widget.ref.read(poolsProvider.future); final pools = await widget.ref.read(poolsProvider.future);
final selectedPool = pools.filterValid().firstWhere( final selectedPool = pools.firstWhere((p) => p.id == selectedPoolId);
(p) => p.id == selectedPoolId,
);
// Check constraints // Check constraints
final maxFileSize = selectedPool.policyConfig?['max_file_size'] as int?; final maxFileSize = selectedPool.policyConfig?['max_file_size'] as int?;

View File

@@ -6,7 +6,7 @@ part of 'file_list.dart';
// RiverpodGenerator // RiverpodGenerator
// ************************************************************************** // **************************************************************************
String _$billingUsageHash() => r'270ec8499378ee0c038aa44ad1c2e3ad9025740a'; String _$billingUsageHash() => r'58d8bc774868d60781574c85d6b25869a79c57aa';
/// See also [billingUsage]. /// See also [billingUsage].
@ProviderFor(billingUsage) @ProviderFor(billingUsage)
@@ -25,7 +25,7 @@ final billingUsageProvider =
@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 BillingUsageRef = AutoDisposeFutureProviderRef<Map<String, dynamic>?>; typedef BillingUsageRef = AutoDisposeFutureProviderRef<Map<String, dynamic>?>;
String _$billingQuotaHash() => r'0696b500fa8bb1270641bcacf262be58caff9b38'; String _$billingQuotaHash() => r'4ec5d728e439015800abb2d0d673b5a7329cc654';
/// See also [billingQuota]. /// See also [billingQuota].
@ProviderFor(billingQuota) @ProviderFor(billingQuota)
@@ -45,7 +45,7 @@ final billingQuotaProvider =
// ignore: unused_element // ignore: unused_element
typedef BillingQuotaRef = AutoDisposeFutureProviderRef<Map<String, dynamic>?>; typedef BillingQuotaRef = AutoDisposeFutureProviderRef<Map<String, dynamic>?>;
String _$cloudFileListNotifierHash() => String _$cloudFileListNotifierHash() =>
r'e2c8a076a9e635c7b43a87d00f78775427ba6334'; r'22c45a8ea23147a3835ba870ad2f0bb833f853ea';
/// See also [CloudFileListNotifier]. /// See also [CloudFileListNotifier].
@ProviderFor(CloudFileListNotifier) @ProviderFor(CloudFileListNotifier)

View File

@@ -22,7 +22,6 @@ import 'package:path_provider/path_provider.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
import 'package:island/pods/config.dart'; import 'package:island/pods/config.dart';
import 'package:island/pods/file_pool.dart'; import 'package:island/pods/file_pool.dart';
import 'package:island/models/file_pool.dart';
class SettingsScreen extends HookConsumerWidget { class SettingsScreen extends HookConsumerWidget {
const SettingsScreen({super.key}); const SettingsScreen({super.key});
@@ -417,7 +416,7 @@ class SettingsScreen extends HookConsumerWidget {
if (user.value != null) if (user.value != null)
pools.when( pools.when(
data: (data) { data: (data) {
final validPools = data.filterValid(); final validPools = data;
final currentPoolId = resolveDefaultPoolId(ref, data); final currentPoolId = resolveDefaultPoolId(ref, data);
return ListTile( return ListTile(
@@ -437,11 +436,14 @@ class SettingsScreen extends HookConsumerWidget {
validPools.map((p) { validPools.map((p) {
return DropdownMenuItem<String>( return DropdownMenuItem<String>(
value: p.id, value: p.id,
child: Tooltip(
message: p.name,
child: Text( child: Text(
p.name, p.name,
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
).fontSize(14), ).fontSize(14),
),
); );
}).toList(), }).toList(),
value: currentPoolId, value: currentPoolId,

View File

@@ -0,0 +1,122 @@
import 'package:flutter/material.dart';
import 'package:island/models/account.dart';
String? getActivityTitle(String? label, Map<String, dynamic>? meta) {
if (meta == null) return label;
if (meta['assets']?['large_text'] is String) {
return meta['assets']?['large_text'];
}
return label;
}
String? getActivitySubtitle(Map<String, dynamic>? meta) {
if (meta == null) return null;
if (meta['assets']?['small_text'] is String) {
return meta['assets']?['small_text'];
}
return null;
}
InlineSpan getActivityFullMessage(SnAccountStatus? status) {
if (status?.meta == null) return TextSpan(text: 'No activity details available');
final meta = status!.meta!;
final List<InlineSpan> spans = [];
if (meta.containsKey('assets') && meta['assets'] is Map) {
final assets = meta['assets'] as Map<String, dynamic>;
if (assets.containsKey('large_text')) {
spans.add(TextSpan(text: assets['large_text'], style: TextStyle(fontWeight: FontWeight.bold)));
}
if (assets.containsKey('small_text')) {
if (spans.isNotEmpty) spans.add(TextSpan(text: '\n'));
spans.add(TextSpan(text: assets['small_text']));
}
}
String normalText = '';
if (meta.containsKey('details')) {
normalText += 'Details: ${meta['details']}\n';
}
if (meta.containsKey('state')) {
normalText += 'State: ${meta['state']}\n';
}
if (meta.containsKey('timestamps') && meta['timestamps'] is Map) {
final ts = meta['timestamps'] as Map<String, dynamic>;
if (ts.containsKey('start') && ts['start'] is int) {
final start = DateTime.fromMillisecondsSinceEpoch(ts['start'] * 1000);
normalText += 'Started: ${start.toLocal()}\n';
}
if (ts.containsKey('end') && ts['end'] is int) {
final end = DateTime.fromMillisecondsSinceEpoch(ts['end'] * 1000);
normalText += 'Ends: ${end.toLocal()}\n';
}
}
if (meta.containsKey('party') && meta['party'] is Map) {
final party = meta['party'] as Map<String, dynamic>;
if (party.containsKey('size') && party['size'] is List && party['size'].length >= 2) {
final size = party['size'] as List;
normalText += 'Party: ${size[0]}/${size[1]}\n';
}
}
if (meta.containsKey('instance')) {
normalText += 'Instance: ${meta['instance']}\n';
}
// Add other keys if present
meta.forEach((key, value) {
if (!['details', 'state', 'timestamps', 'assets', 'party', 'secrets', 'instance'].contains(key)) {
normalText += '$key: $value\n';
}
});
if (normalText.isNotEmpty) {
if (spans.isNotEmpty) spans.add(TextSpan(text: '\n'));
spans.add(TextSpan(text: normalText.trimRight()));
}
return TextSpan(children: spans);
}
Widget buildActivityDetails(SnAccountStatus? status) {
if (status?.meta == null) return Text('No activity details available');
final meta = status!.meta!;
final List<Widget> children = [];
if (meta.containsKey('assets') && meta['assets'] is Map) {
final assets = meta['assets'] as Map<String, dynamic>;
if (assets.containsKey('large_text')) {
children.add(Text(assets['large_text']));
}
if (assets.containsKey('small_text')) {
children.add(Text(assets['small_text']));
}
}
if (meta.containsKey('details')) {
children.add(Text('Details: ${meta['details']}'));
}
if (meta.containsKey('state')) {
children.add(Text('State: ${meta['state']}'));
}
if (meta.containsKey('timestamps') && meta['timestamps'] is Map) {
final ts = meta['timestamps'] as Map<String, dynamic>;
if (ts.containsKey('start') && ts['start'] is int) {
final start = DateTime.fromMillisecondsSinceEpoch(ts['start'] * 1000);
children.add(Text('Started: ${start.toLocal()}'));
}
if (ts.containsKey('end') && ts['end'] is int) {
final end = DateTime.fromMillisecondsSinceEpoch(ts['end'] * 1000);
children.add(Text('Ends: ${end.toLocal()}'));
}
}
if (meta.containsKey('party') && meta['party'] is Map) {
final party = meta['party'] as Map<String, dynamic>;
if (party.containsKey('size') && party['size'] is List && party['size'].length >= 2) {
final size = party['size'] as List;
children.add(Text('Party: ${size[0]}/${size[1]}'));
}
}
if (meta.containsKey('instance')) {
children.add(Text('Instance: ${meta['instance']}'));
}
// Add other keys if present
children.addAll(meta.entries.where((e) => !['details', 'state', 'timestamps', 'assets', 'party', 'secrets', 'instance'].contains(e.key)).map((e) => Text('${e.key}: ${e.value}')));
return Column(
crossAxisAlignment: CrossAxisAlignment.start,
mainAxisSize: MainAxisSize.min,
children: children,
);
}

View File

@@ -147,6 +147,7 @@ class AccountProfileCard extends HookConsumerWidget {
if (data.badges.isNotEmpty) if (data.badges.isNotEmpty)
BadgeList(badges: data.badges).padding(top: 12), BadgeList(badges: data.badges).padding(top: 12),
LevelingProgressCard( LevelingProgressCard(
isCompact: true,
level: data.profile.level, level: data.profile.level,
experience: data.profile.experience, experience: data.profile.experience,
progress: data.profile.levelingProgress, progress: data.profile.levelingProgress,

View File

@@ -3,6 +3,7 @@ import 'package:flutter/material.dart';
import 'package:gap/gap.dart'; import 'package:gap/gap.dart';
import 'package:island/models/activity.dart'; import 'package:island/models/activity.dart';
import 'package:island/services/time.dart'; import 'package:island/services/time.dart';
import 'package:island/utils/activity_utils.dart';
import 'package:material_symbols_icons/symbols.dart'; import 'package:material_symbols_icons/symbols.dart';
import 'package:styled_widget/styled_widget.dart'; import 'package:styled_widget/styled_widget.dart';
@@ -75,7 +76,10 @@ class EventDetailsWidget extends StatelessWidget {
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
Text(status.label), if ((getActivityTitle(status.label, status.meta) ?? status.label).isNotEmpty)
Text(getActivityTitle(status.label, status.meta) ?? status.label),
if (getActivitySubtitle(status.meta) != null)
Text(getActivitySubtitle(status.meta)!).fontSize(11).opacity(0.8),
Text( Text(
'${status.createdAt.formatSystem()} - ${status.clearedAt?.formatSystem() ?? 'present'.tr()}', '${status.createdAt.formatSystem()} - ${status.clearedAt?.formatSystem() ?? 'present'.tr()}',
).fontSize(11).opacity(0.8), ).fontSize(11).opacity(0.8),

View File

@@ -4,8 +4,10 @@ import 'package:flutter/material.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart'; import 'package:hooks_riverpod/hooks_riverpod.dart';
import 'package:island/models/account.dart'; import 'package:island/models/account.dart';
import 'package:island/pods/network.dart'; import 'package:island/pods/network.dart';
import 'package:island/pods/userinfo.dart';
import 'package:island/screens/account/profile.dart'; import 'package:island/screens/account/profile.dart';
import 'package:island/services/time.dart'; import 'package:island/services/time.dart';
import 'package:island/utils/activity_utils.dart';
import 'package:island/widgets/account/status_creation.dart'; import 'package:island/widgets/account/status_creation.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';
@@ -13,8 +15,31 @@ import 'package:styled_widget/styled_widget.dart';
part 'status.g.dart'; part 'status.g.dart';
class CurrentAccountStatusNotifier extends StateNotifier<SnAccountStatus?> {
CurrentAccountStatusNotifier() : super(null);
void setStatus(SnAccountStatus status) {
state = status;
}
void clearStatus() {
state = null;
}
}
final currentAccountStatusProvider = StateNotifierProvider<CurrentAccountStatusNotifier, SnAccountStatus?>((ref) {
return CurrentAccountStatusNotifier();
});
@riverpod @riverpod
Future<SnAccountStatus?> accountStatus(Ref ref, String uname) async { Future<SnAccountStatus?> accountStatus(Ref ref, String uname) async {
final userInfo = ref.watch(userInfoProvider);
if (uname == 'me' || (userInfo.value != null && uname == userInfo.value!.name)) {
final local = ref.watch(currentAccountStatusProvider);
if (local != null) {
return local;
}
}
final apiClient = ref.watch(apiClientProvider); final apiClient = ref.watch(apiClientProvider);
try { try {
final resp = await apiClient.get('/id/accounts/$uname/statuses'); final resp = await apiClient.get('/id/accounts/$uname/statuses');
@@ -110,7 +135,11 @@ class AccountStatusWidget extends HookConsumerWidget {
@override @override
Widget build(BuildContext context, WidgetRef ref) { Widget build(BuildContext context, WidgetRef ref) {
final status = ref.watch(accountStatusProvider(uname)); final userInfo = ref.watch(userInfoProvider);
final localStatus = ref.watch(currentAccountStatusProvider);
final status = (uname == 'me' || (userInfo.value != null && uname == userInfo.value!.name && localStatus != null))
? AsyncValue.data(localStatus)
: ref.watch(accountStatusProvider(uname));
final account = ref.watch(accountProvider(uname)); final account = ref.watch(accountProvider(uname));
return Padding( return Padding(
@@ -133,11 +162,32 @@ class AccountStatusWidget extends HookConsumerWidget {
).padding(right: 4), ).padding(right: 4),
if (status.value?.isCustomized ?? false) if (status.value?.isCustomized ?? false)
Flexible( Flexible(
child: GestureDetector(
onLongPress: () {
showDialog(
context: context,
builder: (context) => AlertDialog(
title: Text('Activity Details'),
content: buildActivityDetails(status.value),
actions: [
TextButton(
onPressed: () => Navigator.of(context).pop(),
child: Text('Close'),
),
],
),
);
},
child: Tooltip(
richMessage: getActivityFullMessage(status.value),
child: Text( child: Text(
status.value?.label ?? 'unknown'.tr(), getActivityTitle(status.value?.label, status.value?.meta) ??
'unknown'.tr(),
maxLines: 1, maxLines: 1,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
), ),
),
),
) )
else else
Flexible( Flexible(
@@ -148,7 +198,13 @@ class AccountStatusWidget extends HookConsumerWidget {
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
).tr(), ).tr(),
), ),
if (!(status.value?.isOnline ?? false) && if (getActivitySubtitle(status.value?.meta) != null)
Flexible(
child: Text(
getActivitySubtitle(status.value?.meta)!,
).opacity(0.75),
)
else if (!(status.value?.isOnline ?? false) &&
account.value?.profile.lastSeenAt != null) account.value?.profile.lastSeenAt != null)
Flexible( Flexible(
child: Text( child: Text(

View File

@@ -59,7 +59,7 @@ class _AttachmentUploaderSheetState extends State<AttachmentUploaderSheet> {
if (snapshot.hasError) { if (snapshot.hasError) {
return Center(child: Text('errorLoadingPools'.tr())); return Center(child: Text('errorLoadingPools'.tr()));
} }
final pools = snapshot.data!.filterValid(); final pools = snapshot.data!;
selectedPoolId ??= resolveDefaultPoolId(widget.ref, pools); selectedPoolId ??= resolveDefaultPoolId(widget.ref, pools);
return Column( return Column(
@@ -286,9 +286,7 @@ class _AttachmentUploaderSheetState extends State<AttachmentUploaderSheet> {
// Get the selected pool to check constraints // Get the selected pool to check constraints
final pools = await widget.ref.read(poolsProvider.future); final pools = await widget.ref.read(poolsProvider.future);
final selectedPool = pools.filterValid().firstWhere( final selectedPool = pools.firstWhere((p) => p.id == selectedPoolId);
(p) => p.id == selectedPoolId,
);
// Check constraints // Check constraints
final maxFileSize = selectedPool.policyConfig?['max_file_size'] as int?; final maxFileSize = selectedPool.policyConfig?['max_file_size'] as int?;

View File

@@ -130,7 +130,7 @@ class MessageItem extends HookConsumerWidget {
useEffect(() { useEffect(() {
if (flashing) { if (flashing) {
if (flashTimer.value != null) return null; flashTimer.value?.cancel();
isFlashing.value = true; isFlashing.value = true;
flashTimer.value = Timer.periodic( flashTimer.value = Timer.periodic(
const Duration(milliseconds: kFlashDuration), const Duration(milliseconds: kFlashDuration),
@@ -343,6 +343,10 @@ class MessageItemDisplayBubble extends HookConsumerWidget {
isCurrentUser isCurrentUser
? Theme.of(context).colorScheme.onPrimaryContainer ? Theme.of(context).colorScheme.onPrimaryContainer
: Theme.of(context).colorScheme.onSurfaceVariant; : Theme.of(context).colorScheme.onSurfaceVariant;
final containerColor =
isCurrentUser
? Theme.of(context).colorScheme.primaryContainer.withOpacity(0.5)
: Theme.of(context).colorScheme.surfaceContainer;
final hasBackground = final hasBackground =
ref.watch(backgroundImageFileProvider).valueOrNull != null; ref.watch(backgroundImageFileProvider).valueOrNull != null;
@@ -377,6 +381,15 @@ class MessageItemDisplayBubble extends HookConsumerWidget {
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
children: [ children: [
Flexible( Flexible(
child: Container(
decoration: BoxDecoration(
color: containerColor,
borderRadius: BorderRadius.circular(16),
),
padding: const EdgeInsets.symmetric(
horizontal: 12,
vertical: 6,
),
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
children: [ children: [
@@ -471,6 +484,7 @@ class MessageItemDisplayBubble extends HookConsumerWidget {
], ],
), ),
), ),
),
MessageIndicators( MessageIndicators(
editedAt: remoteMessage.editedAt, editedAt: remoteMessage.editedAt,
status: message.status, status: message.status,

View File

@@ -229,6 +229,7 @@ class CheckInWidget extends HookConsumerWidget {
Column( Column(
mainAxisAlignment: MainAxisAlignment.spaceBetween, mainAxisAlignment: MainAxisAlignment.spaceBetween,
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
spacing: 4,
children: [ children: [
AnimatedSwitcher( AnimatedSwitcher(
duration: const Duration(milliseconds: 300), duration: const Duration(milliseconds: 300),

View File

@@ -21,7 +21,7 @@ class FileInfoSheet extends StatelessWidget {
final exifData = item.fileMeta?['exif'] as Map<String, dynamic>? ?? {}; final exifData = item.fileMeta?['exif'] as Map<String, dynamic>? ?? {};
return SheetScaffold( return SheetScaffold(
titleText: 'File Information', titleText: 'fileInfoTitle'.tr(),
child: SingleChildScrollView( child: SingleChildScrollView(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@@ -81,7 +81,7 @@ class FileInfoSheet extends StatelessWidget {
), ),
onLongPress: () { onLongPress: () {
Clipboard.setData(ClipboardData(text: item.hash!)); Clipboard.setData(ClipboardData(text: item.hash!));
showSnackBar('File hash copied to clipboard'); showSnackBar('fileHashCopied'.tr());
}, },
), ),
), ),
@@ -101,7 +101,7 @@ class FileInfoSheet extends StatelessWidget {
icon: const Icon(Icons.copy), icon: const Icon(Icons.copy),
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: item.id)); Clipboard.setData(ClipboardData(text: item.id));
showSnackBar('File ID copied to clipboard'); showSnackBar('fileIdCopied'.tr());
}, },
), ),
), ),
@@ -118,7 +118,25 @@ class FileInfoSheet extends StatelessWidget {
icon: const Icon(Icons.copy), icon: const Icon(Icons.copy),
onPressed: () { onPressed: () {
Clipboard.setData(ClipboardData(text: item.name)); Clipboard.setData(ClipboardData(text: item.name));
showSnackBar('File name copied to clipboard'); showSnackBar('fileNameCopied'.tr());
},
),
),
if (item.pool != null)
ListTile(
leading: const Icon(Symbols.calendar_today),
title: Text('File Pool').tr(),
subtitle: Text(
item.pool!.name,
maxLines: 1,
overflow: TextOverflow.ellipsis,
),
contentPadding: EdgeInsets.symmetric(horizontal: 24),
trailing: IconButton(
icon: const Icon(Icons.copy),
onPressed: () {
Clipboard.setData(ClipboardData(text: item.pool!.id));
showSnackBar('fileNameCopied'.tr());
}, },
), ),
), ),
@@ -163,7 +181,7 @@ class FileInfoSheet extends StatelessWidget {
Clipboard.setData( Clipboard.setData(
ClipboardData(text: '${entry.value}'), ClipboardData(text: '${entry.value}'),
); );
showSnackBar('Value copied to clipboard'); showSnackBar('valueCopied'.tr());
}, },
), ),
), ),
@@ -180,7 +198,7 @@ class FileInfoSheet extends StatelessWidget {
child: ExpansionTile( child: ExpansionTile(
tilePadding: const EdgeInsets.symmetric(horizontal: 24), tilePadding: const EdgeInsets.symmetric(horizontal: 24),
title: Text( title: Text(
'File Metadata', 'fileMetadata'.tr(),
style: theme.textTheme.titleMedium?.copyWith( style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -212,7 +230,7 @@ class FileInfoSheet extends StatelessWidget {
Clipboard.setData( Clipboard.setData(
ClipboardData(text: jsonEncode(entry.value)), ClipboardData(text: jsonEncode(entry.value)),
); );
showSnackBar('Value copied to clipboard'); showSnackBar('valueCopied'.tr());
}, },
), ),
), ),
@@ -229,7 +247,7 @@ class FileInfoSheet extends StatelessWidget {
child: ExpansionTile( child: ExpansionTile(
tilePadding: const EdgeInsets.symmetric(horizontal: 24), tilePadding: const EdgeInsets.symmetric(horizontal: 24),
title: Text( title: Text(
'User Metadata', 'userMetadata'.tr(),
style: theme.textTheme.titleMedium?.copyWith( style: theme.textTheme.titleMedium?.copyWith(
fontWeight: FontWeight.bold, fontWeight: FontWeight.bold,
), ),
@@ -261,7 +279,7 @@ class FileInfoSheet extends StatelessWidget {
Clipboard.setData( Clipboard.setData(
ClipboardData(text: jsonEncode(entry.value)), ClipboardData(text: jsonEncode(entry.value)),
); );
showSnackBar('Value copied to clipboard'); showSnackBar('valueCopied'.tr());
}, },
), ),
), ),

View File

@@ -21,19 +21,19 @@ PODS:
- Firebase/Messaging (12.2.0): - Firebase/Messaging (12.2.0):
- Firebase/CoreOnly - Firebase/CoreOnly
- FirebaseMessaging (~> 12.2.0) - FirebaseMessaging (~> 12.2.0)
- firebase_analytics (12.0.1): - firebase_analytics (12.0.2):
- firebase_core - firebase_core
- FirebaseAnalytics (= 12.2.0) - FirebaseAnalytics (= 12.2.0)
- FlutterMacOS - FlutterMacOS
- firebase_core (4.1.0): - firebase_core (4.1.1):
- Firebase/CoreOnly (~> 12.2.0) - Firebase/CoreOnly (~> 12.2.0)
- FlutterMacOS - FlutterMacOS
- firebase_crashlytics (5.0.1): - firebase_crashlytics (5.0.2):
- Firebase/CoreOnly (~> 12.2.0) - Firebase/CoreOnly (~> 12.2.0)
- Firebase/Crashlytics (~> 12.2.0) - Firebase/Crashlytics (~> 12.2.0)
- firebase_core - firebase_core
- FlutterMacOS - FlutterMacOS
- firebase_messaging (16.0.1): - firebase_messaging (16.0.2):
- Firebase/CoreOnly (~> 12.2.0) - Firebase/CoreOnly (~> 12.2.0)
- Firebase/Messaging (~> 12.2.0) - Firebase/Messaging (~> 12.2.0)
- firebase_core - firebase_core
@@ -402,10 +402,10 @@ SPEC CHECKSUMS:
file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31 file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1 Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
firebase_analytics: efe6e51156f4565f3791d99072e8e3b0fcca0e91 firebase_analytics: 26346c2ccb9ba410c2f33d5d34c62e6369cbbf29
firebase_core: a8d3b82b0a87bd1d0ebc21e686b37e939c56e6e1 firebase_core: 54fd706197e1779d510b297548eee74d3b39577c
firebase_crashlytics: fdbe67a1229a9e583ebf2b155541491aa83927bb firebase_crashlytics: 3694b4aca0849f6919244d7bbbb40615f989f46b
firebase_messaging: 6fb526705903e2e56e38a6ff56b43668b052b01b firebase_messaging: 658f1a6906d80faec2fb20e3aadb81af6b09e441
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8 FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5 FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5

View File

@@ -13,10 +13,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: _flutterfire_internals name: _flutterfire_internals
sha256: "948f7d74f41dd6f2d563ea9f4c21d7ea764f8e047d2b24138974c19c24d37eb6" sha256: "23d16f00a2da8ffa997c782453c73867b0609bd90435195671a54de38a3566df"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "1.3.61" version: "1.3.62"
analyzer: analyzer:
dependency: transitive dependency: transitive
description: description:
@@ -485,10 +485,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: drift name: drift
sha256: "6aaea757f53bb035e8a3baedf3d1d53a79d6549a6c13d84f7546509da9372c7c" sha256: "540cf382a3bfa99b76e51514db5b0ebcd81ce3679b7c1c9cb9478ff3735e47a1"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.28.1" version: "2.28.2"
drift_dev: drift_dev:
dependency: "direct dev" dependency: "direct dev"
description: description:
@@ -501,10 +501,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: drift_flutter name: drift_flutter
sha256: b52bd710f809db11e25259d429d799d034ba1c5224ce6a73fe8419feb980d44c sha256: b7534bf320aac5213259aac120670ba67b63a1fd010505babc436ff86083818f
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.2.6" version: "0.2.7"
dropdown_button2: dropdown_button2:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -629,90 +629,90 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_analytics name: firebase_analytics
sha256: dde9d6a7b69b07551a77cfb913c81c64804f7602b07541328322c321e73f2a0e sha256: fce78440ab7b95563054039aac5e342088efed9dc009ac6f81d5cac07155d509
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "12.0.1" version: "12.0.2"
firebase_analytics_platform_interface: firebase_analytics_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_analytics_platform_interface name: firebase_analytics_platform_interface
sha256: "4008d82a58edcbedec34a7b39f457eed24181cb9c89782c104828c42e4c859b2" sha256: "75bdcd2d2635c4cdcd7ec13727527751ddf2f9933e5bf1264a2387920246f3c5"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.1" version: "5.0.2"
firebase_analytics_web: firebase_analytics_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_analytics_web name: firebase_analytics_web
sha256: db2a2e8803f5471a5f89b4abacae95ae27e0644f77526879fb81a2c1abc12b5f sha256: ed5767695b131cdd425ee6d49934dca80689d9df40609c0d0aa8907ee6f0f785
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "0.6.0+1" version: "0.6.0+2"
firebase_core: firebase_core:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_core name: firebase_core
sha256: "967dae9a65f69377beb9f4ab292ea63ce5befa1ce24682cab1b69ca4b7a46927" sha256: "4dd96f05015c0dcceaa47711394c32971aee70169625d5e2477e7676c01ce0ee"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.1.0" version: "4.1.1"
firebase_core_platform_interface: firebase_core_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_core_platform_interface name: firebase_core_platform_interface
sha256: "5dbc900677dcbe5873d22ad7fbd64b047750124f1f9b7ebe2a33b9ddccc838eb" sha256: "5873a370f0d232918e23a5a6137dbe4c2c47cf017301f4ea02d9d636e52f60f0"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "6.0.0" version: "6.0.1"
firebase_core_web: firebase_core_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_core_web name: firebase_core_web
sha256: f7ee08febc1c4451588ce58ffcf28edaee857e9a196fee88b85deb889990094a sha256: "61a51037312dac781f713308903bb7a1762a7f92f7bc286a3a0947fb2a713b82"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.1.0" version: "3.1.1"
firebase_crashlytics: firebase_crashlytics:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_crashlytics name: firebase_crashlytics
sha256: f2e175a967712ee1f616ab8843390891a315428ba497ce3d256d4c46f32db6f8 sha256: a636096df0d2a4bc72397bfc669a4fffc8896016a58de1a6f45a49d9ba064f94
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "5.0.1" version: "5.0.2"
firebase_crashlytics_platform_interface: firebase_crashlytics_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_crashlytics_platform_interface name: firebase_crashlytics_platform_interface
sha256: b49b90af4a1fd8f30b58abd90af88371969bea51b62838a4f4e737c2098b725e sha256: "1ccad077a6fc7bace97d8eace263f42e66dc23a23a839de864a4f10ac4a7c264"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "3.8.12" version: "3.8.13"
firebase_messaging: firebase_messaging:
dependency: "direct main" dependency: "direct main"
description: description:
name: firebase_messaging name: firebase_messaging
sha256: aad5dcdea5698499b70d74d5a53b1f6a9972f85f97225e4b7ac006dd8d4f9bac sha256: ba12ad0b600e0c939fbb9391e1cd3320a5b5dad5284276b9182fc21eb1e72c2b
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "16.0.1" version: "16.0.2"
firebase_messaging_platform_interface: firebase_messaging_platform_interface:
dependency: transitive dependency: transitive
description: description:
name: firebase_messaging_platform_interface name: firebase_messaging_platform_interface
sha256: "825bc11767bf50a43dccf49b3026f847ec31d0f176139bfc48d662cc128b5014" sha256: b4bade67bfc09fcc56eb012b3fc72b59ca9e2259a34cdfb81b368169770ff536
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.7.1" version: "4.7.2"
firebase_messaging_web: firebase_messaging_web:
dependency: transitive dependency: transitive
description: description:
name: firebase_messaging_web name: firebase_messaging_web
sha256: db8dbdd79921245c4de02407e33cae2d1868683be18a5ba948d2af5311e3ef5d sha256: "8ae4a00d178993feb79603cad324b53696375cbb78805e8eb603fe331866629d"
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "4.0.1" version: "4.0.2"
fixnum: fixnum:
dependency: transitive dependency: transitive
description: description:
@@ -1193,10 +1193,10 @@ packages:
dependency: "direct main" dependency: "direct main"
description: description:
name: go_router name: go_router
sha256: b1488741c9ce37b72e026377c69a59c47378493156fc38efb5a54f6def3f92a3 sha256: c752e2d08d088bf83742cb05bf83003f3e9d276ff1519b5c92f9d5e60e5ddd23
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "16.2.2" version: "16.2.4"
google_fonts: google_fonts:
dependency: "direct main" dependency: "direct main"
description: description:
@@ -2177,10 +2177,10 @@ packages:
dependency: transitive dependency: transitive
description: description:
name: shared_preferences_android name: shared_preferences_android
sha256: a2608114b1ffdcbc9c120eb71a0e207c71da56202852d4aab8a5e30a82269e74 sha256: bd14436108211b0d4ee5038689a56d4ae3620fd72fd6036e113bf1345bc74d9e
url: "https://pub.dev" url: "https://pub.dev"
source: hosted source: hosted
version: "2.4.12" version: "2.4.13"
shared_preferences_foundation: shared_preferences_foundation:
dependency: transitive dependency: transitive
description: description:

View File

@@ -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+133 version: 3.2.0+134
environment: environment:
sdk: ^3.7.2 sdk: ^3.7.2
@@ -39,7 +39,7 @@ dependencies:
flutter_hooks: ^0.21.3+1 flutter_hooks: ^0.21.3+1
hooks_riverpod: ^2.6.1 hooks_riverpod: ^2.6.1
bitsdojo_window: ^0.1.6 bitsdojo_window: ^0.1.6
go_router: ^16.2.2 go_router: ^16.2.4
styled_widget: ^0.4.1 styled_widget: ^0.4.1
shared_preferences: ^2.5.3 shared_preferences: ^2.5.3
flutter_riverpod: ^2.6.1 flutter_riverpod: ^2.6.1
@@ -79,13 +79,13 @@ dependencies:
image_picker_android: ^0.8.13+3 image_picker_android: ^0.8.13+3
super_context_menu: ^0.9.1 super_context_menu: ^0.9.1
modal_bottom_sheet: ^3.0.0 modal_bottom_sheet: ^3.0.0
firebase_messaging: ^16.0.1 firebase_messaging: ^16.0.2
flutter_udid: ^4.0.0 flutter_udid: ^4.0.0
firebase_core: ^4.1.0 firebase_core: ^4.1.1
web_socket_channel: ^3.0.3 web_socket_channel: ^3.0.3
material_symbols_icons: ^4.2873.0 material_symbols_icons: ^4.2873.0
drift: ^2.28.1 drift: ^2.28.2
drift_flutter: ^0.2.6 drift_flutter: ^0.2.7
path: ^1.9.1 path: ^1.9.1
collection: ^1.19.1 collection: ^1.19.1
markdown_editor_plus: ^0.2.15 markdown_editor_plus: ^0.2.15
@@ -135,8 +135,8 @@ dependencies:
flutter_app_update: ^3.2.2 flutter_app_update: ^3.2.2
archive: ^4.0.7 archive: ^4.0.7
process_run: ^1.2.4 process_run: ^1.2.4
firebase_crashlytics: ^5.0.1 firebase_crashlytics: ^5.0.2
firebase_analytics: ^12.0.1 firebase_analytics: ^12.0.2
material_color_utilities: ^0.11.1 material_color_utilities: ^0.11.1
screenshot: ^3.0.0 screenshot: ^3.0.0
flutter_card_swiper: ^7.0.2 flutter_card_swiper: ^7.0.2

View File

@@ -1,6 +1,6 @@
; ================================================== ; ==================================================
#define AppVersion "3.2.0" #define AppVersion "3.2.0"
#define BuildNumber "132" #define BuildNumber "134"
; ================================================== ; ==================================================
#define FullVersion AppVersion + "." + BuildNumber #define FullVersion AppVersion + "." + BuildNumber