Compare commits
29 Commits
c7f5b63fe5
...
v3
Author | SHA1 | Date | |
---|---|---|---|
|
a61c889c6c | ||
|
0dd3221a56 | ||
|
66918521f8 | ||
|
bb1846e462 | ||
|
a976a6eaf4 | ||
|
4252f66fd3 | ||
|
f2d780b48f | ||
|
300541f9bb | ||
|
43787bb813 | ||
|
3417c51a3b | ||
|
f98e603e82 | ||
|
c9b71701c8 | ||
|
28e98488f1 | ||
|
b4d476613e | ||
|
b48a1aac44 | ||
|
596d212593 | ||
|
54f290327e | ||
|
16f248ceab | ||
|
856d811187 | ||
|
d07b194c04 | ||
|
2554b58be6 | ||
|
a627b5838e | ||
|
c479a9f381 | ||
|
02057e663b | ||
|
6501594100 | ||
|
c6599edc3d | ||
|
709a0620b6 | ||
|
f9b2a96c7c | ||
|
4dca6189cb |
@@ -386,6 +386,7 @@
|
|||||||
"postSettings": "Settings",
|
"postSettings": "Settings",
|
||||||
"postPublisherUnselected": "Publisher Unspecified",
|
"postPublisherUnselected": "Publisher Unspecified",
|
||||||
"postType": "Post Type",
|
"postType": "Post Type",
|
||||||
|
"postTypePost": "Post",
|
||||||
"articleAttachmentHint": "Attachments must be uploaded and inserted into the article body to be visible.",
|
"articleAttachmentHint": "Attachments must be uploaded and inserted into the article body to be visible.",
|
||||||
"postVisibility": "Post Visibility",
|
"postVisibility": "Post Visibility",
|
||||||
"postVisibilityPublic": "Public",
|
"postVisibilityPublic": "Public",
|
||||||
@@ -883,6 +884,7 @@
|
|||||||
"stellarProgram": "Stellar Program",
|
"stellarProgram": "Stellar Program",
|
||||||
"socialCredits": "Social Credits",
|
"socialCredits": "Social Credits",
|
||||||
"credits": "Credits",
|
"credits": "Credits",
|
||||||
|
"creditsStatus": "Credits Status",
|
||||||
"socialCreditsDescription": "Social Credit is a way for Solar Network to evaluate users. It is calculated based on their behavior and interactions. With a base score of 100, higher scores indicate a user's credibility within the community. Scores change over time to reflect a user's recent behavior. Users with higher credit ratings enjoy more benefits, while users with lower credit ratings may have some functionality restricted.",
|
"socialCreditsDescription": "Social Credit is a way for Solar Network to evaluate users. It is calculated based on their behavior and interactions. With a base score of 100, higher scores indicate a user's credibility within the community. Scores change over time to reflect a user's recent behavior. Users with higher credit ratings enjoy more benefits, while users with lower credit ratings may have some functionality restricted.",
|
||||||
"socialCreditsLevelPoor": "Poor",
|
"socialCreditsLevelPoor": "Poor",
|
||||||
"socialCreditsLevelNormal": "Normal",
|
"socialCreditsLevelNormal": "Normal",
|
||||||
@@ -926,5 +928,46 @@
|
|||||||
"newSecretGenerated": "New Secret Generated",
|
"newSecretGenerated": "New Secret Generated",
|
||||||
"copySecretHint": "Please copy this secret and store it somewhere safe. You will not be able to see it again.",
|
"copySecretHint": "Please copy this secret and store it somewhere safe. You will not be able to see it again.",
|
||||||
"expiresIn": "Expires In (seconds)",
|
"expiresIn": "Expires In (seconds)",
|
||||||
"isOidc": "OIDC Compliant"
|
"isOidc": "OIDC Compliant",
|
||||||
|
"pinPost": "Pin Post",
|
||||||
|
"unpinPost": "Unpin Post",
|
||||||
|
"pinnedPost": "Pinned",
|
||||||
|
"publisherPage": "Publisher Page",
|
||||||
|
"realmPage": "Realm Page",
|
||||||
|
"replyPage": "Reply Page",
|
||||||
|
"pinPostPublisherHint": "Pin this post to your publisher page",
|
||||||
|
"pinPostRealmHint": "Pin this post to the realm page",
|
||||||
|
"pinPostRealmDisabledHint": "This post doesn't belong to any realm",
|
||||||
|
"pinPostReplyHint": "Pin this post to the reply page",
|
||||||
|
"pinPostReplyDisabledHint": "This post is not a reply",
|
||||||
|
"pin": "Pin",
|
||||||
|
"unpinPostHint": "Are you sure you want to unpin this post?",
|
||||||
|
"all": "All",
|
||||||
|
"statusPresent": "Present",
|
||||||
|
"accountAutomated": "Automated",
|
||||||
|
"chatBreakClearButton": "Clear",
|
||||||
|
"chatBreak5m": "5m",
|
||||||
|
"chatBreak10m": "10m",
|
||||||
|
"chatBreak15m": "15m",
|
||||||
|
"chatBreak30m": "30m",
|
||||||
|
"chatBreakCustomMinutes": "Custom (minutes)",
|
||||||
|
"errorGeneric": "Error: {}",
|
||||||
|
"searchMessages": "Search Messages",
|
||||||
|
"messagesCount": "{} messages",
|
||||||
|
"dotSeparator": "·",
|
||||||
|
"roleValidationHint": "Role must be between 0 and 100",
|
||||||
|
"searchMessagesHint": "Search messages...",
|
||||||
|
"searchLinks": "Links",
|
||||||
|
"searchAttachments": "Attachments",
|
||||||
|
"noMessagesFound": "No messages found",
|
||||||
|
"openInBrowser": "Open in Browser",
|
||||||
|
"highlightPost": "Highlight Post",
|
||||||
|
"filters": "Filters",
|
||||||
|
"apply": "Apply",
|
||||||
|
"pubName": "Pub Name",
|
||||||
|
"realm": "Realm",
|
||||||
|
"shuffle": "Shuffle",
|
||||||
|
"pinned": "Pinned",
|
||||||
|
"noResultsFound": "No results found",
|
||||||
|
"toggleFilters": "Toggle filters"
|
||||||
}
|
}
|
@@ -855,5 +855,9 @@
|
|||||||
"newSecretGenerated": "已生成新密钥",
|
"newSecretGenerated": "已生成新密钥",
|
||||||
"copySecretHint": "请复制此密钥并将其存放在安全的地方。您将无法再次看到它。",
|
"copySecretHint": "请复制此密钥并将其存放在安全的地方。您将无法再次看到它。",
|
||||||
"expiresIn": "过期时间(秒)",
|
"expiresIn": "过期时间(秒)",
|
||||||
"isOidc": "OIDC 兼容"
|
"isOidc": "OIDC 兼容",
|
||||||
|
"statusPresent": "至今",
|
||||||
|
"accountAutomated": "机器人",
|
||||||
|
"openInBrowser": "在浏览器中打开",
|
||||||
|
"highlightPost": "精选帖子"
|
||||||
}
|
}
|
||||||
|
@@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>12.0</string>
|
<string>13.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
162
ios/Podfile.lock
162
ios/Podfile.lock
@@ -40,83 +40,85 @@ PODS:
|
|||||||
- file_picker (0.0.1):
|
- file_picker (0.0.1):
|
||||||
- DKImagePickerController/PhotoGallery
|
- DKImagePickerController/PhotoGallery
|
||||||
- Flutter
|
- Flutter
|
||||||
- Firebase/CoreOnly (12.0.0):
|
- file_saver (0.0.1):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- Flutter
|
||||||
- Firebase/Crashlytics (12.0.0):
|
- Firebase/CoreOnly (12.2.0):
|
||||||
|
- FirebaseCore (~> 12.2.0)
|
||||||
|
- Firebase/Crashlytics (12.2.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseCrashlytics (~> 12.0.0)
|
- FirebaseCrashlytics (~> 12.2.0)
|
||||||
- Firebase/Messaging (12.0.0):
|
- Firebase/Messaging (12.2.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 12.0.0)
|
- FirebaseMessaging (~> 12.2.0)
|
||||||
- firebase_analytics (12.0.0):
|
- firebase_analytics (12.0.1):
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FirebaseAnalytics (= 12.0.0)
|
- FirebaseAnalytics (= 12.2.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_core (4.0.0):
|
- firebase_core (4.1.0):
|
||||||
- Firebase/CoreOnly (= 12.0.0)
|
- Firebase/CoreOnly (= 12.2.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_crashlytics (5.0.0):
|
- firebase_crashlytics (5.0.1):
|
||||||
- Firebase/Crashlytics (= 12.0.0)
|
- Firebase/Crashlytics (= 12.2.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_messaging (16.0.0):
|
- firebase_messaging (16.0.1):
|
||||||
- Firebase/Messaging (= 12.0.0)
|
- Firebase/Messaging (= 12.2.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- FirebaseAnalytics (12.0.0):
|
- FirebaseAnalytics (12.2.0):
|
||||||
- FirebaseAnalytics/Default (= 12.0.0)
|
- FirebaseAnalytics/Default (= 12.2.0)
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseAnalytics/Default (12.0.0):
|
- FirebaseAnalytics/Default (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleAppMeasurement/Default (= 12.0.0)
|
- GoogleAppMeasurement/Default (= 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseCore (12.0.0):
|
- FirebaseCore (12.2.0):
|
||||||
- FirebaseCoreInternal (~> 12.0.0)
|
- FirebaseCoreInternal (~> 12.2.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- FirebaseCoreExtension (12.0.0):
|
- FirebaseCoreExtension (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseCoreInternal (12.0.0):
|
- FirebaseCoreInternal (12.2.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- FirebaseCrashlytics (12.0.0):
|
- FirebaseCrashlytics (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- FirebaseRemoteConfigInterop (~> 12.0.0)
|
- FirebaseRemoteConfigInterop (~> 12.2.0)
|
||||||
- FirebaseSessions (~> 12.0.0)
|
- FirebaseSessions (~> 12.2.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseInstallations (12.0.0):
|
- FirebaseInstallations (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (12.0.0):
|
- FirebaseMessaging (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Reachability (~> 8.1)
|
- GoogleUtilities/Reachability (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseRemoteConfigInterop (12.0.0)
|
- FirebaseRemoteConfigInterop (12.2.0)
|
||||||
- FirebaseSessions (12.0.0):
|
- FirebaseSessions (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseCoreExtension (~> 12.0.0)
|
- FirebaseCoreExtension (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
@@ -145,33 +147,33 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- flutter_webrtc (1.0.0):
|
- flutter_webrtc (1.1.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (= 137.7151.02)
|
- WebRTC-SDK (= 137.7151.03)
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- GoogleAdsOnDeviceConversion (2.1.0):
|
- GoogleAdsOnDeviceConversion (2.3.0):
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/Core (12.0.0):
|
- GoogleAppMeasurement/Core (12.2.0):
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/Default (12.0.0):
|
- GoogleAppMeasurement/Default (12.2.0):
|
||||||
- GoogleAdsOnDeviceConversion (= 2.1.0)
|
- GoogleAdsOnDeviceConversion (= 2.3.0)
|
||||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||||
- GoogleAppMeasurement/IdentitySupport (= 12.0.0)
|
- GoogleAppMeasurement/IdentitySupport (= 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/IdentitySupport (12.0.0):
|
- GoogleAppMeasurement/IdentitySupport (12.2.0):
|
||||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
@@ -215,7 +217,7 @@ PODS:
|
|||||||
- livekit_client (2.5.0):
|
- livekit_client (2.5.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- WebRTC-SDK (= 137.7151.02)
|
- WebRTC-SDK (= 137.7151.03)
|
||||||
- local_auth_darwin (0.0.1):
|
- local_auth_darwin (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -248,9 +250,9 @@ PODS:
|
|||||||
- record_ios (1.1.0):
|
- record_ios (1.1.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain (1.5.3)
|
- SAMKeychain (1.5.3)
|
||||||
- SDWebImage (5.21.1):
|
- SDWebImage (5.21.2):
|
||||||
- SDWebImage/Core (= 5.21.1)
|
- SDWebImage/Core (= 5.21.2)
|
||||||
- SDWebImage/Core (5.21.1)
|
- SDWebImage/Core (5.21.2)
|
||||||
- share_plus (0.0.1):
|
- share_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
@@ -295,7 +297,7 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (137.7151.02)
|
- WebRTC-SDK (137.7151.03)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Alamofire
|
- Alamofire
|
||||||
@@ -303,6 +305,7 @@ DEPENDENCIES:
|
|||||||
- croppy (from `.symlinks/plugins/croppy/ios`)
|
- croppy (from `.symlinks/plugins/croppy/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
|
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
||||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
||||||
@@ -381,6 +384,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
file_picker:
|
file_picker:
|
||||||
:path: ".symlinks/plugins/file_picker/ios"
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
|
file_saver:
|
||||||
|
:path: ".symlinks/plugins/file_saver/ios"
|
||||||
firebase_analytics:
|
firebase_analytics:
|
||||||
:path: ".symlinks/plugins/firebase_analytics/ios"
|
:path: ".symlinks/plugins/firebase_analytics/ios"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
@@ -464,21 +469,22 @@ SPEC CHECKSUMS:
|
|||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||||
Firebase: 800d487043c0557d9faed71477a38d9aafb08a41
|
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||||
firebase_analytics: cd56fc56f75c1df30a6ff5290cd56e230996a76d
|
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
|
||||||
firebase_core: 633e1851ffe1b9ab875f6467a4f574c79cef02e4
|
firebase_analytics: 111ff65791a430356bd6c7e4d7339537fc6a15ae
|
||||||
firebase_crashlytics: 2c6c1a17900a38081d938330e9f48e60ec5b255d
|
firebase_core: 3ff52146406557dddd01d570e807e203ec7e1302
|
||||||
firebase_messaging: d17feef781edc84ebefe62624fb384358ad96361
|
firebase_crashlytics: 3637078b718a52dc9fb4d64e37c969e86b87ff6f
|
||||||
FirebaseAnalytics: 6d790cd1b159b4eb61a99948df0934ce505a34f7
|
firebase_messaging: 3dcc998dd98e1e54af75d0cccae8606eba43553c
|
||||||
FirebaseCore: 055f4ab117d5964158c833f3d5e7ec6d91648d4a
|
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
|
||||||
FirebaseCoreExtension: 639afb3de6abd611952be78a794c54a47fa0f361
|
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
|
||||||
FirebaseCoreInternal: dedc28e569a4be85f38f3d6af1070a2e12018d55
|
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5
|
||||||
FirebaseCrashlytics: db75aa0cab8d00f68406fa247c32fe17ade884d7
|
FirebaseCoreInternal: 56ea29f3dad2894f81b060f706f9d53509b6ed3b
|
||||||
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
FirebaseCrashlytics: f83cbf176d5c637ade108c0aacf1ccbd5ec499bf
|
||||||
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
FirebaseInstallations: 3e884b01feabdf67582a80f3250425a00979b4ed
|
||||||
FirebaseRemoteConfigInterop: bfa0ea72ba3dc5af739777296424e46bd6f42613
|
FirebaseMessaging: 43ec73bbfedd0c385a849bb91593ab4ad4b9e48e
|
||||||
FirebaseSessions: 4e784acda213108aafef536535cdfc03504acc42
|
FirebaseRemoteConfigInterop: 0896fd52ab72586a355c8f389ff85aaa9e5375e1
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
FirebaseSessions: f4692789e770bec66ce17d772c0e9561c4f11737
|
||||||
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
||||||
@@ -487,16 +493,16 @@ SPEC CHECKSUMS:
|
|||||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||||
flutter_webrtc: 6f7da106613d52ade777d5b4875a43f48c28b457
|
flutter_webrtc: b0b2e04411747142962164a1cfa43a1af9a0afac
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64
|
GoogleAdsOnDeviceConversion: 9090c435cde08903e8dd1ba2c77fbec9e46d9afe
|
||||||
GoogleAppMeasurement: 8f6ab04ad6ae493b53fcf56bd26323fb2f1384f3
|
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||||
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
||||||
livekit_client: e3b79b99405428aac439b6b76a254cd9a11dbbfb
|
livekit_client: f810c81bbbc229a84f60b09e66603ac4e93f7599
|
||||||
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
||||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||||
@@ -512,7 +518,7 @@ SPEC CHECKSUMS:
|
|||||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||||
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
|
||||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
||||||
@@ -524,7 +530,7 @@ SPEC CHECKSUMS:
|
|||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||||
WebRTC-SDK: d20de357dcbf7c9696b124b39f3ff62125107e4b
|
WebRTC-SDK: 69d4e56b0b4b27d788e87bab9b9a1326ed05b1e3
|
||||||
|
|
||||||
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
||||||
|
|
||||||
|
@@ -853,7 +853,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -897,6 +897,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -915,6 +916,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -931,6 +933,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -1078,7 +1081,7 @@
|
|||||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1121,7 +1124,7 @@
|
|||||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1161,7 +1164,7 @@
|
|||||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1348,7 +1351,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -1399,7 +1402,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
|
@@ -68,6 +68,34 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
return (delete(chatMessages)..where((m) => m.id.equals(id))).go();
|
return (delete(chatMessages)..where((m) => m.id.equals(id))).go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> getTotalMessagesForRoom(String roomId) {
|
||||||
|
return (select(chatMessages)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<LocalChatMessage>> searchMessages(
|
||||||
|
String roomId,
|
||||||
|
String query,
|
||||||
|
) async {
|
||||||
|
var selectStatement = select(chatMessages)
|
||||||
|
..where((m) => m.roomId.equals(roomId));
|
||||||
|
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
selectStatement =
|
||||||
|
selectStatement
|
||||||
|
..where((m) => m.content.like('%${query.toLowerCase()}%'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
final messages =
|
||||||
|
await (selectStatement
|
||||||
|
..orderBy([(m) => OrderingTerm.desc(m.createdAt)]))
|
||||||
|
.get();
|
||||||
|
return messages.map((msg) => companionToMessage(msg)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
// Convert between Drift and model objects
|
// Convert between Drift and model objects
|
||||||
ChatMessagesCompanion messageToCompanion(LocalChatMessage message) {
|
ChatMessagesCompanion messageToCompanion(LocalChatMessage message) {
|
||||||
return ChatMessagesCompanion(
|
return ChatMessagesCompanion(
|
||||||
|
@@ -8,7 +8,7 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
|||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@@ -30,7 +30,6 @@ import 'package:shared_preferences/shared_preferences.dart';
|
|||||||
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
@@ -52,7 +51,6 @@ void main() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await langdetect.initLangDetect();
|
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
|
|
||||||
if (kIsWeb || !Platform.isLinux) {
|
if (kIsWeb || !Platform.isLinux) {
|
||||||
@@ -169,12 +167,12 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
final theme = ref.watch(themeProvider);
|
final theme = ref.watch(themeProvider);
|
||||||
|
|
||||||
void handleMessage(RemoteMessage notification) {
|
void handleMessage(RemoteMessage notification) {
|
||||||
if (notification.data['action_uri'] != null) {
|
if (notification.data['meta']?['action_uri'] != null) {
|
||||||
var uri = notification.data['action_uri'] as String;
|
var uri = notification.data['meta']['action_uri'] as String;
|
||||||
if (uri.startsWith('/')) {
|
if (uri.startsWith('/')) {
|
||||||
// In-app routes
|
// In-app routes
|
||||||
final router = ref.read(routerProvider);
|
final router = ref.read(routerProvider);
|
||||||
router.go(notification.data['action_uri']);
|
router.push(notification.data['meta']['action_uri']);
|
||||||
} else {
|
} else {
|
||||||
// External links
|
// External links
|
||||||
launchUrlString(uri);
|
launchUrlString(uri);
|
||||||
@@ -186,27 +184,6 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
if (!kIsWeb && Platform.isLinux) {
|
if (!kIsWeb && Platform.isLinux) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const channel = MethodChannel('dev.solsynth.solian/notifications');
|
|
||||||
|
|
||||||
Future<void> handleInitialLink() async {
|
|
||||||
final String? link = await channel.invokeMethod('initialLink');
|
|
||||||
if (link != null) {
|
|
||||||
final router = ref.read(routerProvider);
|
|
||||||
router.go(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!kIsWeb && Platform.isAndroid) {
|
|
||||||
handleInitialLink();
|
|
||||||
}
|
|
||||||
|
|
||||||
channel.setMethodCallHandler((call) async {
|
|
||||||
if (call.method == 'newLink') {
|
|
||||||
final String link = call.arguments;
|
|
||||||
final router = ref.read(routerProvider);
|
|
||||||
router.go(link);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// When the app is opened from a terminated state.
|
// When the app is opened from a terminated state.
|
||||||
FirebaseMessaging.instance.getInitialMessage().then((message) {
|
FirebaseMessaging.instance.getInitialMessage().then((message) {
|
||||||
|
@@ -71,6 +71,8 @@ sealed class SnAccountProfile with _$SnAccountProfile {
|
|||||||
SnAccountBadge? activeBadge,
|
SnAccountBadge? activeBadge,
|
||||||
required int experience,
|
required int experience,
|
||||||
required int level,
|
required int level,
|
||||||
|
@Default(100) double socialCredits,
|
||||||
|
@Default(0) int socialCreditsLevel,
|
||||||
required double levelingProgress,
|
required double levelingProgress,
|
||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
|
@@ -613,7 +613,7 @@ as String,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAccountProfile {
|
mixin _$SnAccountProfile {
|
||||||
|
|
||||||
String get id; String get firstName; String get middleName; String get lastName; String get bio; String get gender; String get pronouns; String get location; String get timeZone; DateTime? get birthday;@ProfileLinkConverter() List<ProfileLink> get links; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String get firstName; String get middleName; String get lastName; String get bio; String get gender; String get pronouns; String get location; String get timeZone; DateTime? get birthday;@ProfileLinkConverter() List<ProfileLink> get links; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get socialCredits; int get socialCreditsLevel; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnAccountProfile
|
/// Create a copy of SnAccountProfile
|
||||||
/// 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)
|
||||||
@@ -626,16 +626,16 @@ $SnAccountProfileCopyWith<SnAccountProfile> get copyWith => _$SnAccountProfileCo
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other.links, links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(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 SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other.links, links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(identical(other.socialCreditsLevel, socialCreditsLevel) || other.socialCreditsLevel == socialCreditsLevel)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(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.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(links),lastSeenAt,activeBadge,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(links),lastSeenAt,activeBadge,experience,level,socialCredits,socialCreditsLevel,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, socialCredits: $socialCredits, socialCreditsLevel: $socialCreditsLevel, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -646,7 +646,7 @@ abstract mixin class $SnAccountProfileCopyWith<$Res> {
|
|||||||
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -663,7 +663,7 @@ class _$SnAccountProfileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccountProfile
|
/// Create a copy of SnAccountProfile
|
||||||
/// 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? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? socialCredits = null,Object? socialCreditsLevel = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = 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,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -680,6 +680,8 @@ as List<ProfileLink>,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : last
|
|||||||
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,socialCredits: null == socialCredits ? _self.socialCredits : socialCredits // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double,socialCreditsLevel: null == socialCreditsLevel ? _self.socialCreditsLevel : socialCreditsLevel // ignore: cast_nullable_to_non_nullable
|
||||||
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
||||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -817,10 +819,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccountProfile() when $default != null:
|
case _SnAccountProfile() when $default != null:
|
||||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -838,10 +840,10 @@ return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.b
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccountProfile():
|
case _SnAccountProfile():
|
||||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -855,10 +857,10 @@ return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.b
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccountProfile() when $default != null:
|
case _SnAccountProfile() when $default != null:
|
||||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -870,7 +872,7 @@ return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.b
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnAccountProfile implements SnAccountProfile {
|
class _SnAccountProfile implements SnAccountProfile {
|
||||||
const _SnAccountProfile({required this.id, this.firstName = '', this.middleName = '', this.lastName = '', this.bio = '', this.gender = '', this.pronouns = '', this.location = '', this.timeZone = '', this.birthday, @ProfileLinkConverter() final List<ProfileLink> links = const [], this.lastSeenAt, this.activeBadge, required this.experience, required this.level, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.createdAt, required this.updatedAt, required this.deletedAt}): _links = links;
|
const _SnAccountProfile({required this.id, this.firstName = '', this.middleName = '', this.lastName = '', this.bio = '', this.gender = '', this.pronouns = '', this.location = '', this.timeZone = '', this.birthday, @ProfileLinkConverter() final List<ProfileLink> links = const [], this.lastSeenAt, this.activeBadge, required this.experience, required this.level, this.socialCredits = 100, this.socialCreditsLevel = 0, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.createdAt, required this.updatedAt, required this.deletedAt}): _links = links;
|
||||||
factory _SnAccountProfile.fromJson(Map<String, dynamic> json) => _$SnAccountProfileFromJson(json);
|
factory _SnAccountProfile.fromJson(Map<String, dynamic> json) => _$SnAccountProfileFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -894,6 +896,8 @@ class _SnAccountProfile implements SnAccountProfile {
|
|||||||
@override final SnAccountBadge? activeBadge;
|
@override final SnAccountBadge? activeBadge;
|
||||||
@override final int experience;
|
@override final int experience;
|
||||||
@override final int level;
|
@override final int level;
|
||||||
|
@override@JsonKey() final double socialCredits;
|
||||||
|
@override@JsonKey() final int socialCreditsLevel;
|
||||||
@override final double levelingProgress;
|
@override final double levelingProgress;
|
||||||
@override final SnCloudFile? picture;
|
@override final SnCloudFile? picture;
|
||||||
@override final SnCloudFile? background;
|
@override final SnCloudFile? background;
|
||||||
@@ -915,16 +919,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other._links, _links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(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 _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other._links, _links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(identical(other.socialCreditsLevel, socialCreditsLevel) || other.socialCreditsLevel == socialCreditsLevel)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(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.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(_links),lastSeenAt,activeBadge,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(_links),lastSeenAt,activeBadge,experience,level,socialCredits,socialCreditsLevel,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, socialCredits: $socialCredits, socialCreditsLevel: $socialCreditsLevel, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -935,7 +939,7 @@ abstract mixin class _$SnAccountProfileCopyWith<$Res> implements $SnAccountProfi
|
|||||||
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -952,7 +956,7 @@ class __$SnAccountProfileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccountProfile
|
/// Create a copy of SnAccountProfile
|
||||||
/// 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? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? socialCredits = null,Object? socialCreditsLevel = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnAccountProfile(
|
return _then(_SnAccountProfile(
|
||||||
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,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
as String,firstName: null == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -969,6 +973,8 @@ as List<ProfileLink>,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : last
|
|||||||
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,socialCredits: null == socialCredits ? _self.socialCredits : socialCredits // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double,socialCreditsLevel: null == socialCreditsLevel ? _self.socialCreditsLevel : socialCreditsLevel // ignore: cast_nullable_to_non_nullable
|
||||||
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
||||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
|
@@ -86,6 +86,8 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
|||||||
),
|
),
|
||||||
experience: (json['experience'] as num).toInt(),
|
experience: (json['experience'] as num).toInt(),
|
||||||
level: (json['level'] as num).toInt(),
|
level: (json['level'] as num).toInt(),
|
||||||
|
socialCredits: (json['social_credits'] as num?)?.toDouble() ?? 100,
|
||||||
|
socialCreditsLevel: (json['social_credits_level'] as num?)?.toInt() ?? 0,
|
||||||
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
||||||
picture:
|
picture:
|
||||||
json['picture'] == null
|
json['picture'] == null
|
||||||
@@ -128,6 +130,8 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
|||||||
'active_badge': instance.activeBadge?.toJson(),
|
'active_badge': instance.activeBadge?.toJson(),
|
||||||
'experience': instance.experience,
|
'experience': instance.experience,
|
||||||
'level': instance.level,
|
'level': instance.level,
|
||||||
|
'social_credits': instance.socialCredits,
|
||||||
|
'social_credits_level': instance.socialCreditsLevel,
|
||||||
'leveling_progress': instance.levelingProgress,
|
'leveling_progress': instance.levelingProgress,
|
||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
|
@@ -54,7 +54,7 @@ sealed class SnEventCalendarEntry with _$SnEventCalendarEntry {
|
|||||||
const factory SnEventCalendarEntry({
|
const factory SnEventCalendarEntry({
|
||||||
required DateTime date,
|
required DateTime date,
|
||||||
required SnCheckInResult? checkInResult,
|
required SnCheckInResult? checkInResult,
|
||||||
required List<dynamic> statuses,
|
required List<SnAccountStatus> statuses,
|
||||||
}) = _SnEventCalendarEntry;
|
}) = _SnEventCalendarEntry;
|
||||||
|
|
||||||
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
|
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
|
||||||
|
@@ -861,7 +861,7 @@ as String,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnEventCalendarEntry {
|
mixin _$SnEventCalendarEntry {
|
||||||
|
|
||||||
DateTime get date; SnCheckInResult? get checkInResult; List<dynamic> get statuses;
|
DateTime get date; SnCheckInResult? get checkInResult; List<SnAccountStatus> get statuses;
|
||||||
/// Create a copy of SnEventCalendarEntry
|
/// Create a copy of SnEventCalendarEntry
|
||||||
/// 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)
|
||||||
@@ -894,7 +894,7 @@ abstract mixin class $SnEventCalendarEntryCopyWith<$Res> {
|
|||||||
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
|
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -916,7 +916,7 @@ class _$SnEventCalendarEntryCopyWithImpl<$Res>
|
|||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
|
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,
|
as List<SnAccountStatus>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnEventCalendarEntry
|
/// Create a copy of SnEventCalendarEntry
|
||||||
@@ -1010,7 +1010,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry() when $default != null:
|
case _SnEventCalendarEntry() when $default != null:
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||||
@@ -1031,7 +1031,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry():
|
case _SnEventCalendarEntry():
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
||||||
@@ -1048,7 +1048,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry() when $default != null:
|
case _SnEventCalendarEntry() when $default != null:
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||||
@@ -1063,13 +1063,13 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnEventCalendarEntry implements SnEventCalendarEntry {
|
class _SnEventCalendarEntry implements SnEventCalendarEntry {
|
||||||
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<dynamic> statuses}): _statuses = statuses;
|
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<SnAccountStatus> statuses}): _statuses = statuses;
|
||||||
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
|
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
|
||||||
|
|
||||||
@override final DateTime date;
|
@override final DateTime date;
|
||||||
@override final SnCheckInResult? checkInResult;
|
@override final SnCheckInResult? checkInResult;
|
||||||
final List<dynamic> _statuses;
|
final List<SnAccountStatus> _statuses;
|
||||||
@override List<dynamic> get statuses {
|
@override List<SnAccountStatus> get statuses {
|
||||||
if (_statuses is EqualUnmodifiableListView) return _statuses;
|
if (_statuses is EqualUnmodifiableListView) return _statuses;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_statuses);
|
return EqualUnmodifiableListView(_statuses);
|
||||||
@@ -1109,7 +1109,7 @@ abstract mixin class _$SnEventCalendarEntryCopyWith<$Res> implements $SnEventCal
|
|||||||
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
|
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -1131,7 +1131,7 @@ class __$SnEventCalendarEntryCopyWithImpl<$Res>
|
|||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
|
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,
|
as List<SnAccountStatus>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -87,7 +87,10 @@ _SnEventCalendarEntry _$SnEventCalendarEntryFromJson(
|
|||||||
: SnCheckInResult.fromJson(
|
: SnCheckInResult.fromJson(
|
||||||
json['check_in_result'] as Map<String, dynamic>,
|
json['check_in_result'] as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
statuses: json['statuses'] as List<dynamic>,
|
statuses:
|
||||||
|
(json['statuses'] as List<dynamic>)
|
||||||
|
.map((e) => SnAccountStatus.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
||||||
@@ -95,5 +98,5 @@ Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
|||||||
) => <String, dynamic>{
|
) => <String, dynamic>{
|
||||||
'date': instance.date.toIso8601String(),
|
'date': instance.date.toIso8601String(),
|
||||||
'check_in_result': instance.checkInResult?.toJson(),
|
'check_in_result': instance.checkInResult?.toJson(),
|
||||||
'statuses': instance.statuses,
|
'statuses': instance.statuses.map((e) => e.toJson()).toList(),
|
||||||
};
|
};
|
||||||
|
@@ -27,6 +27,7 @@ sealed class SnPost with _$SnPost {
|
|||||||
@Default(0) int upvotes,
|
@Default(0) int upvotes,
|
||||||
@Default(0) int downvotes,
|
@Default(0) int downvotes,
|
||||||
@Default(0) int repliesCount,
|
@Default(0) int repliesCount,
|
||||||
|
int? pinMode,
|
||||||
String? threadedPostId,
|
String? threadedPostId,
|
||||||
SnPost? threadedPost,
|
SnPost? threadedPost,
|
||||||
String? repliedPostId,
|
String? repliedPostId,
|
||||||
|
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnPost {
|
mixin _$SnPost {
|
||||||
|
|
||||||
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
|
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $SnPostCopyWith<SnPost> get copyWith => _$SnPostCopyWithImpl<SnPost>(this as SnP
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ abstract mixin class $SnPostCopyWith<$Res> {
|
|||||||
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
|
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -65,7 +65,7 @@ class _$SnPostCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// 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? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||||
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,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -83,7 +83,8 @@ as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore:
|
|||||||
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
||||||
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
|
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
|
||||||
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
|
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
|
||||||
as int,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
as int,pinMode: freezed == pinMode ? _self.pinMode : pinMode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
|
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repliedPostId // ignore: cast_nullable_to_non_nullable
|
as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repliedPostId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -242,10 +243,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPost() when $default != null:
|
case _SnPost() when $default != null:
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -263,10 +264,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPost():
|
case _SnPost():
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
|
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -280,10 +281,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPost() when $default != null:
|
case _SnPost() when $default != null:
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -295,7 +296,7 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnPost implements SnPost {
|
class _SnPost implements SnPost {
|
||||||
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
||||||
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -322,6 +323,7 @@ class _SnPost implements SnPost {
|
|||||||
@override@JsonKey() final int upvotes;
|
@override@JsonKey() final int upvotes;
|
||||||
@override@JsonKey() final int downvotes;
|
@override@JsonKey() final int downvotes;
|
||||||
@override@JsonKey() final int repliesCount;
|
@override@JsonKey() final int repliesCount;
|
||||||
|
@override final int? pinMode;
|
||||||
@override final String? threadedPostId;
|
@override final String? threadedPostId;
|
||||||
@override final SnPost? threadedPost;
|
@override final SnPost? threadedPost;
|
||||||
@override final String? repliedPostId;
|
@override final String? repliedPostId;
|
||||||
@@ -398,16 +400,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -418,7 +420,7 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
|||||||
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
|
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -435,7 +437,7 @@ class __$SnPostCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// 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? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||||
return _then(_SnPost(
|
return _then(_SnPost(
|
||||||
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,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -453,7 +455,8 @@ as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore:
|
|||||||
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
||||||
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
|
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
|
||||||
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
|
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
|
||||||
as int,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
as int,pinMode: freezed == pinMode ? _self.pinMode : pinMode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
|
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repliedPostId // ignore: cast_nullable_to_non_nullable
|
as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repliedPostId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
||||||
|
@@ -29,6 +29,7 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
|||||||
upvotes: (json['upvotes'] as num?)?.toInt() ?? 0,
|
upvotes: (json['upvotes'] as num?)?.toInt() ?? 0,
|
||||||
downvotes: (json['downvotes'] as num?)?.toInt() ?? 0,
|
downvotes: (json['downvotes'] as num?)?.toInt() ?? 0,
|
||||||
repliesCount: (json['replies_count'] as num?)?.toInt() ?? 0,
|
repliesCount: (json['replies_count'] as num?)?.toInt() ?? 0,
|
||||||
|
pinMode: (json['pin_mode'] as num?)?.toInt(),
|
||||||
threadedPostId: json['threaded_post_id'] as String?,
|
threadedPostId: json['threaded_post_id'] as String?,
|
||||||
threadedPost:
|
threadedPost:
|
||||||
json['threaded_post'] == null
|
json['threaded_post'] == null
|
||||||
@@ -109,6 +110,7 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
|||||||
'upvotes': instance.upvotes,
|
'upvotes': instance.upvotes,
|
||||||
'downvotes': instance.downvotes,
|
'downvotes': instance.downvotes,
|
||||||
'replies_count': instance.repliesCount,
|
'replies_count': instance.repliesCount,
|
||||||
|
'pin_mode': instance.pinMode,
|
||||||
'threaded_post_id': instance.threadedPostId,
|
'threaded_post_id': instance.threadedPostId,
|
||||||
'threaded_post': instance.threadedPost?.toJson(),
|
'threaded_post': instance.threadedPost?.toJson(),
|
||||||
'replied_post_id': instance.repliedPostId,
|
'replied_post_id': instance.repliedPostId,
|
||||||
|
@@ -1,11 +1,9 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
|
||||||
|
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
|
||||||
|
|
||||||
part 'translate.freezed.dart';
|
part 'translate.freezed.dart';
|
||||||
part 'translate.g.dart';
|
part 'translate.g.dart';
|
||||||
@@ -29,10 +27,17 @@ Future<String> translateString(Ref ref, TranslateQuery query) async {
|
|||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
String? detectStringLanguage(Ref ref, String text) {
|
String? detectStringLanguage(Ref ref, String text) {
|
||||||
try {
|
bool isChinese(String text) {
|
||||||
return langdetect.detectLangs(text).firstOrNull?.lang;
|
final chineseRegex = RegExp(r'[\u4e00-\u9fff]');
|
||||||
} catch (err) {
|
return chineseRegex.hasMatch(text);
|
||||||
log('[Language] Unable to detect text\'s language: $text');
|
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool isEnglish(String text) {
|
||||||
|
final englishRegex = RegExp(r'[a-zA-Z]');
|
||||||
|
return englishRegex.hasMatch(text) && !isChinese(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isChinese(text)) return "zh";
|
||||||
|
if (isEnglish(text)) return "en";
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
@@ -38,6 +38,7 @@ import 'package:island/screens/chat/chat.dart';
|
|||||||
import 'package:island/screens/chat/room.dart';
|
import 'package:island/screens/chat/room.dart';
|
||||||
import 'package:island/screens/chat/room_detail.dart';
|
import 'package:island/screens/chat/room_detail.dart';
|
||||||
import 'package:island/screens/chat/call.dart';
|
import 'package:island/screens/chat/call.dart';
|
||||||
|
import 'package:island/screens/chat/search_messages_screen.dart';
|
||||||
import 'package:island/screens/creators/hub.dart';
|
import 'package:island/screens/creators/hub.dart';
|
||||||
import 'package:island/screens/creators/posts/post_manage_list.dart';
|
import 'package:island/screens/creators/posts/post_manage_list.dart';
|
||||||
import 'package:island/screens/creators/stickers/stickers.dart';
|
import 'package:island/screens/creators/stickers/stickers.dart';
|
||||||
@@ -555,6 +556,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
return ChatDetailScreen(id: id);
|
return ChatDetailScreen(id: id);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
name: 'searchMessages',
|
||||||
|
path: '/chat/:id/search',
|
||||||
|
builder: (context, state) {
|
||||||
|
final id = state.pathParameters['id']!;
|
||||||
|
return SearchMessagesScreen(roomId: id);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@@ -68,6 +68,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: getTabbedPadding(context),
|
padding: getTabbedPadding(context),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
spacing: 4,
|
||||||
children: <Widget>[
|
children: <Widget>[
|
||||||
Card(
|
Card(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -112,20 +113,22 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||||
textBaseline: TextBaseline.alphabetic,
|
textBaseline: TextBaseline.alphabetic,
|
||||||
children: [
|
children: [
|
||||||
AccountName(
|
Flexible(
|
||||||
account: user.value!,
|
child: AccountName(
|
||||||
style: TextStyle(
|
account: user.value!,
|
||||||
fontSize: 16,
|
style: TextStyle(
|
||||||
fontWeight: FontWeight.bold,
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Text('@${user.value!.name}'),
|
Flexible(child: Text('@${user.value!.name}')),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
(user.value!.profile.bio.isNotEmpty)
|
(user.value!.profile.bio.isNotEmpty)
|
||||||
? user.value!.profile.bio
|
? user.value!.profile.bio
|
||||||
: 'No description yet.',
|
: 'descriptionNone'.tr(),
|
||||||
maxLines: 1,
|
maxLines: 1,
|
||||||
overflow: TextOverflow.ellipsis,
|
overflow: TextOverflow.ellipsis,
|
||||||
),
|
),
|
||||||
@@ -158,8 +161,16 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Icon(Symbols.draw, size: 28).padding(bottom: 8),
|
Icon(Symbols.draw, size: 28).padding(bottom: 8),
|
||||||
Text('creatorHub').tr().fontSize(16).bold(),
|
Text(
|
||||||
Text('creatorHubDescription').tr(),
|
'creatorHub',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).tr().fontSize(16).bold(),
|
||||||
|
Text(
|
||||||
|
'creatorHubDescription',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).tr(),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, vertical: 12),
|
).padding(horizontal: 16, vertical: 12),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -176,8 +187,16 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Icon(Symbols.code, size: 28).padding(bottom: 8),
|
Icon(Symbols.code, size: 28).padding(bottom: 8),
|
||||||
Text('developerPortal').tr().fontSize(16).bold(),
|
Text(
|
||||||
Text('developerPortalDescription').tr(),
|
'developerPortal',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).tr().fontSize(16).bold(),
|
||||||
|
Text(
|
||||||
|
'developerPortalDescription',
|
||||||
|
maxLines: 2,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
).tr(),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, vertical: 12),
|
).padding(horizontal: 16, vertical: 12),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
@@ -95,8 +95,24 @@ class LevelingScreen extends HookConsumerWidget {
|
|||||||
title: Text('levelingProgress'.tr()),
|
title: Text('levelingProgress'.tr()),
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
tabs: [
|
tabs: [
|
||||||
Tab(text: 'leveling'.tr()),
|
Tab(
|
||||||
Tab(text: 'stellarProgram'.tr()),
|
child: Text(
|
||||||
|
'leveling'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'stellarProgram'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -14,7 +14,6 @@ import 'package:island/screens/account/me/settings_connections.dart';
|
|||||||
import 'package:island/screens/account/me/settings_contacts.dart';
|
import 'package:island/screens/account/me/settings_contacts.dart';
|
||||||
import 'package:island/screens/auth/captcha.dart';
|
import 'package:island/screens/auth/captcha.dart';
|
||||||
import 'package:island/screens/auth/login.dart';
|
import 'package:island/screens/auth/login.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
|
||||||
import 'package:island/widgets/account/account_devices.dart';
|
import 'package:island/widgets/account/account_devices.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@@ -57,7 +56,6 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final isDesktop =
|
final isDesktop =
|
||||||
!kIsWeb && (Platform.isWindows || Platform.isMacOS || Platform.isLinux);
|
!kIsWeb && (Platform.isWindows || Platform.isMacOS || Platform.isLinux);
|
||||||
final isWide = isWideScreen(context);
|
|
||||||
|
|
||||||
Future<void> requestAccountDeletion() async {
|
Future<void> requestAccountDeletion() async {
|
||||||
final confirm = await showConfirmAlert(
|
final confirm = await showConfirmAlert(
|
||||||
@@ -440,51 +438,19 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Create a responsive layout based on screen width
|
// Create a responsive layout based on screen width
|
||||||
Widget buildSettingsList() {
|
Widget buildSettingsList() {
|
||||||
if (isWide) {
|
return Column(
|
||||||
// Two-column layout for wide screens
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
return Row(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
_SettingsSection(
|
||||||
children: [
|
title: 'accountSecurityTitle',
|
||||||
Expanded(
|
children: securitySettings,
|
||||||
child: Column(
|
),
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
_SettingsSection(
|
||||||
children: [
|
title: 'accountDangerZoneTitle',
|
||||||
_SettingsSection(
|
children: dangerZoneSettings,
|
||||||
title: 'accountSecurityTitle',
|
),
|
||||||
children: securitySettings,
|
],
|
||||||
),
|
);
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
_SettingsSection(
|
|
||||||
title: 'accountDangerZoneTitle',
|
|
||||||
children: dangerZoneSettings,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
} else {
|
|
||||||
// Single column layout for narrow screens
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
_SettingsSection(
|
|
||||||
title: 'accountSecurityTitle',
|
|
||||||
children: securitySettings,
|
|
||||||
),
|
|
||||||
_SettingsSection(
|
|
||||||
title: 'accountDangerZoneTitle',
|
|
||||||
children: dangerZoneSettings,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
@@ -1,10 +1,12 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_svg/flutter_svg.dart';
|
import 'package:flutter_svg/flutter_svg.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/auth.dart';
|
import 'package:island/models/auth.dart';
|
||||||
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/screens/account/me/account_settings.dart';
|
import 'package:island/screens/account/me/account_settings.dart';
|
||||||
import 'package:island/screens/auth/oidc.native.dart';
|
import 'package:island/screens/auth/oidc.native.dart';
|
||||||
@@ -16,6 +18,7 @@ import 'package:island/widgets/response.dart';
|
|||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
|
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
// Helper function to get provider icon and localized name
|
// Helper function to get provider icon and localized name
|
||||||
Widget getProviderIcon(String provider, {double size = 24, Color? color}) {
|
Widget getProviderIcon(String provider, {double size = 24, Color? color}) {
|
||||||
@@ -165,9 +168,7 @@ class AccountConnectionNewSheet extends HookConsumerWidget {
|
|||||||
scopes: [AppleIDAuthorizationScopes.email],
|
scopes: [AppleIDAuthorizationScopes.email],
|
||||||
webAuthenticationOptions: WebAuthenticationOptions(
|
webAuthenticationOptions: WebAuthenticationOptions(
|
||||||
clientId: 'dev.solsynth.solarpass',
|
clientId: 'dev.solsynth.solarpass',
|
||||||
redirectUri: Uri.parse(
|
redirectUri: Uri.parse('https://id.solian.app/auth/callback'),
|
||||||
'https://id.solian.app/auth/callback/apple',
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -195,17 +196,25 @@ class AccountConnectionNewSheet extends HookConsumerWidget {
|
|||||||
case 'github':
|
case 'github':
|
||||||
case 'discord':
|
case 'discord':
|
||||||
case 'afdian':
|
case 'afdian':
|
||||||
await Navigator.of(context, rootNavigator: true).push(
|
if (kIsWeb) {
|
||||||
MaterialPageRoute(
|
final serverUrl = ref.watch(serverUrlProvider);
|
||||||
builder:
|
final accessToken = ref.watch(tokenProvider);
|
||||||
(context) => OidcScreen(
|
launchUrlString(
|
||||||
provider: selectedProvider.value.toLowerCase(),
|
'$serverUrl/id/auth/login/${selectedProvider.value}?tk=${accessToken!.token}',
|
||||||
title:
|
);
|
||||||
'Connect with ${selectedProvider.value.capitalizeEachWord()}',
|
} else {
|
||||||
),
|
await Navigator.of(context, rootNavigator: true).push(
|
||||||
),
|
MaterialPageRoute(
|
||||||
);
|
builder:
|
||||||
if (context.mounted) Navigator.pop(context, true);
|
(context) => OidcScreen(
|
||||||
|
provider: selectedProvider.value.toLowerCase(),
|
||||||
|
title:
|
||||||
|
'Connect with ${selectedProvider.value.capitalizeEachWord()}',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
if (context.mounted) Navigator.pop(context, true);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
showSnackBar('accountConnectionAddError'.tr());
|
showSnackBar('accountConnectionAddError'.tr());
|
||||||
|
@@ -2,6 +2,7 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
@@ -279,6 +280,36 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
if (data.profile.lastName.isNotEmpty) Text(data.profile.lastName),
|
if (data.profile.lastName.isNotEmpty) Text(data.profile.lastName),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
Tooltip(
|
||||||
|
message: 'creditsStatus'.tr(),
|
||||||
|
child: Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Icon(Symbols.star, size: 17, fill: 1).padding(right: 2),
|
||||||
|
Text('${data.profile.socialCredits.toStringAsFixed(2)} pts'),
|
||||||
|
Text('·').bold(),
|
||||||
|
switch (data.profile.socialCreditsLevel) {
|
||||||
|
-1 => Text('socialCreditsLevelPoor').tr(),
|
||||||
|
0 => Text('socialCreditsLevelNormal').tr(),
|
||||||
|
1 => Text('socialCreditsLevelGood').tr(),
|
||||||
|
2 => Text('socialCreditsLevelExcellent').tr(),
|
||||||
|
_ => Text('unknown').tr(),
|
||||||
|
},
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
InkWell(
|
||||||
|
child: Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Icon(Symbols.fingerprint, size: 17, fill: 1).padding(right: 2),
|
||||||
|
Text(data.id),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: data.id));
|
||||||
|
},
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
|
import 'package:island/widgets/account/account_pfc.dart';
|
||||||
import 'package:island/widgets/account/account_picker.dart';
|
import 'package:island/widgets/account/account_picker.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@@ -99,7 +100,10 @@ class RelationshipListTile extends StatelessWidget {
|
|||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: const EdgeInsets.only(left: 16, right: 12),
|
contentPadding: const EdgeInsets.only(left: 16, right: 12),
|
||||||
leading: ProfilePictureWidget(fileId: account.profile.picture?.id),
|
leading: AccountPfcGestureDetector(
|
||||||
|
uname: account.name,
|
||||||
|
child: ProfilePictureWidget(fileId: account.profile.picture?.id),
|
||||||
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
|
@@ -700,45 +700,48 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
|||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
onSubmitted: isBusy.value ? null : (_) => performNewTicket(),
|
onSubmitted: isBusy.value ? null : (_) => performNewTicket(),
|
||||||
).padding(horizontal: 7),
|
).padding(horizontal: 7),
|
||||||
Row(
|
if (!kIsWeb)
|
||||||
spacing: 6,
|
Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
spacing: 6,
|
||||||
children: <Widget>[
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
Text("loginOr").tr().fontSize(11).opacity(0.85),
|
children: <Widget>[
|
||||||
const Gap(8),
|
Text("loginOr").tr().fontSize(11).opacity(0.85),
|
||||||
Spacer(),
|
const Gap(8),
|
||||||
IconButton.filledTonal(
|
Spacer(),
|
||||||
onPressed: () => withOidc('github'),
|
IconButton.filledTonal(
|
||||||
padding: EdgeInsets.zero,
|
onPressed: () => withOidc('github'),
|
||||||
icon: getProviderIcon(
|
padding: EdgeInsets.zero,
|
||||||
"github",
|
icon: getProviderIcon(
|
||||||
size: 16,
|
"github",
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
size: 16,
|
||||||
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
|
),
|
||||||
|
tooltip: 'GitHub',
|
||||||
),
|
),
|
||||||
tooltip: 'GitHub',
|
IconButton.filledTonal(
|
||||||
),
|
onPressed: () => withOidc('google'),
|
||||||
IconButton.filledTonal(
|
padding: EdgeInsets.zero,
|
||||||
onPressed: () => withOidc('google'),
|
icon: getProviderIcon(
|
||||||
padding: EdgeInsets.zero,
|
"google",
|
||||||
icon: getProviderIcon(
|
size: 16,
|
||||||
"google",
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
size: 16,
|
),
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
tooltip: 'Google',
|
||||||
),
|
),
|
||||||
tooltip: 'Google',
|
IconButton.filledTonal(
|
||||||
),
|
onPressed: withApple,
|
||||||
IconButton.filledTonal(
|
padding: EdgeInsets.zero,
|
||||||
onPressed: withApple,
|
icon: getProviderIcon(
|
||||||
padding: EdgeInsets.zero,
|
"apple",
|
||||||
icon: getProviderIcon(
|
size: 16,
|
||||||
"apple",
|
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||||
size: 16,
|
),
|
||||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
tooltip: 'Apple Account',
|
||||||
),
|
),
|
||||||
tooltip: 'Apple Account',
|
],
|
||||||
),
|
).padding(horizontal: 8, vertical: 8)
|
||||||
],
|
else
|
||||||
).padding(horizontal: 8, vertical: 8),
|
const Gap(12),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
children: [
|
children: [
|
||||||
|
@@ -4,6 +4,7 @@ import "dart:developer" as developer;
|
|||||||
import "dart:io";
|
import "dart:io";
|
||||||
import "package:dio/dio.dart";
|
import "package:dio/dio.dart";
|
||||||
import "package:easy_localization/easy_localization.dart";
|
import "package:easy_localization/easy_localization.dart";
|
||||||
|
import "package:file_picker/file_picker.dart";
|
||||||
import "package:flutter/foundation.dart";
|
import "package:flutter/foundation.dart";
|
||||||
import "package:flutter/material.dart";
|
import "package:flutter/material.dart";
|
||||||
import "package:go_router/go_router.dart";
|
import "package:go_router/go_router.dart";
|
||||||
@@ -72,6 +73,207 @@ class _AppLifecycleObserver extends WidgetsBindingObserver {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class _PublicRoomPreview extends HookConsumerWidget {
|
||||||
|
final String id;
|
||||||
|
final SnChatRoom room;
|
||||||
|
|
||||||
|
const _PublicRoomPreview({required this.id, required this.room});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final messages = ref.watch(messagesNotifierProvider(id));
|
||||||
|
final messagesNotifier = ref.read(messagesNotifierProvider(id).notifier);
|
||||||
|
final scrollController = useScrollController();
|
||||||
|
|
||||||
|
final listController = useMemoized(() => ListController(), []);
|
||||||
|
|
||||||
|
var isLoading = false;
|
||||||
|
|
||||||
|
// Add scroll listener for pagination
|
||||||
|
useEffect(() {
|
||||||
|
void onScroll() {
|
||||||
|
if (scrollController.position.pixels >=
|
||||||
|
scrollController.position.maxScrollExtent - 200) {
|
||||||
|
if (isLoading) return;
|
||||||
|
isLoading = true;
|
||||||
|
messagesNotifier.loadMore().then((_) => isLoading = false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
scrollController.addListener(onScroll);
|
||||||
|
return () => scrollController.removeListener(onScroll);
|
||||||
|
}, [scrollController]);
|
||||||
|
|
||||||
|
Widget chatMessageListWidget(List<LocalChatMessage> messageList) =>
|
||||||
|
SuperListView.builder(
|
||||||
|
listController: listController,
|
||||||
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
|
controller: scrollController,
|
||||||
|
reverse: true, // Show newest messages at the bottom
|
||||||
|
itemCount: messageList.length,
|
||||||
|
findChildIndexCallback: (key) {
|
||||||
|
final valueKey = key as ValueKey;
|
||||||
|
final messageId = valueKey.value as String;
|
||||||
|
return messageList.indexWhere((m) => m.id == messageId);
|
||||||
|
},
|
||||||
|
extentEstimation: (_, _) => 40,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final message = messageList[index];
|
||||||
|
final nextMessage =
|
||||||
|
index < messageList.length - 1 ? messageList[index + 1] : null;
|
||||||
|
final isLastInGroup =
|
||||||
|
nextMessage == null ||
|
||||||
|
nextMessage.senderId != message.senderId ||
|
||||||
|
nextMessage.createdAt
|
||||||
|
.difference(message.createdAt)
|
||||||
|
.inMinutes
|
||||||
|
.abs() >
|
||||||
|
3;
|
||||||
|
|
||||||
|
return MessageItem(
|
||||||
|
message: message,
|
||||||
|
isCurrentUser: false, // User is not a member, so not current user
|
||||||
|
onAction: null, // No actions allowed in preview mode
|
||||||
|
onJump: (_) {}, // No jump functionality in preview
|
||||||
|
progress: null,
|
||||||
|
showAvatar: isLastInGroup,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
final compactHeader = isWideScreen(context);
|
||||||
|
|
||||||
|
Widget comfortHeaderWidget() => Column(
|
||||||
|
spacing: 4,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 26,
|
||||||
|
width: 26,
|
||||||
|
child:
|
||||||
|
(room.type == 1 && room.picture?.id == null)
|
||||||
|
? SplitAvatarWidget(
|
||||||
|
filesId:
|
||||||
|
room.members!
|
||||||
|
.map((e) => e.account.profile.picture?.id)
|
||||||
|
.toList(),
|
||||||
|
)
|
||||||
|
: room.picture?.id != null
|
||||||
|
? ProfilePictureWidget(
|
||||||
|
fileId: room.picture?.id,
|
||||||
|
fallbackIcon: Symbols.chat,
|
||||||
|
)
|
||||||
|
: CircleAvatar(
|
||||||
|
child: Text(
|
||||||
|
room.name![0].toUpperCase(),
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
(room.type == 1 && room.name == null)
|
||||||
|
? room.members!.map((e) => e.account.nick).join(', ')
|
||||||
|
: room.name!,
|
||||||
|
).fontSize(15),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
Widget compactHeaderWidget() => Row(
|
||||||
|
spacing: 8,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
SizedBox(
|
||||||
|
height: 26,
|
||||||
|
width: 26,
|
||||||
|
child:
|
||||||
|
(room.type == 1 && room.picture?.id == null)
|
||||||
|
? SplitAvatarWidget(
|
||||||
|
filesId:
|
||||||
|
room.members!
|
||||||
|
.map((e) => e.account.profile.picture?.id)
|
||||||
|
.toList(),
|
||||||
|
)
|
||||||
|
: room.picture?.id != null
|
||||||
|
? ProfilePictureWidget(
|
||||||
|
fileId: room.picture?.id,
|
||||||
|
fallbackIcon: Symbols.chat,
|
||||||
|
)
|
||||||
|
: CircleAvatar(
|
||||||
|
child: Text(
|
||||||
|
room.name![0].toUpperCase(),
|
||||||
|
style: const TextStyle(fontSize: 12),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
(room.type == 1 && room.name == null)
|
||||||
|
? room.members!.map((e) => e.account.nick).join(', ')
|
||||||
|
: room.name!,
|
||||||
|
).fontSize(19),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
|
return AppScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: !compactHeader ? const Center(child: PageBackButton()) : null,
|
||||||
|
automaticallyImplyLeading: false,
|
||||||
|
toolbarHeight: compactHeader ? null : 64,
|
||||||
|
title: compactHeader ? compactHeaderWidget() : comfortHeaderWidget(),
|
||||||
|
actions: [
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Icons.more_vert),
|
||||||
|
onPressed: () {
|
||||||
|
context.pushNamed('chatDetail', pathParameters: {'id': id});
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: messages.when(
|
||||||
|
data:
|
||||||
|
(messageList) =>
|
||||||
|
messageList.isEmpty
|
||||||
|
? Center(child: Text('No messages yet'.tr()))
|
||||||
|
: chatMessageListWidget(messageList),
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error:
|
||||||
|
(error, _) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => messagesNotifier.loadInitial(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
// Join button at the bottom for public rooms
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: FilledButton.tonalIcon(
|
||||||
|
onPressed: () async {
|
||||||
|
try {
|
||||||
|
showLoadingModal(context);
|
||||||
|
final apiClient = ref.read(apiClientProvider);
|
||||||
|
await apiClient.post('/sphere/chat/${room.id}/members/me');
|
||||||
|
ref.invalidate(chatroomIdentityProvider(id));
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) hideLoadingModal(context);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
label: Text('chatJoin').tr(),
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
class MessagesNotifier extends _$MessagesNotifier {
|
class MessagesNotifier extends _$MessagesNotifier {
|
||||||
late final Dio _apiClient;
|
late final Dio _apiClient;
|
||||||
@@ -82,6 +284,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
final Map<String, LocalChatMessage> _pendingMessages = {};
|
final Map<String, LocalChatMessage> _pendingMessages = {};
|
||||||
final Map<String, Map<int, double>> _fileUploadProgress = {};
|
final Map<String, Map<int, double>> _fileUploadProgress = {};
|
||||||
int? _totalCount;
|
int? _totalCount;
|
||||||
|
String? _searchQuery;
|
||||||
|
bool? _withLinks;
|
||||||
|
bool? _withAttachments;
|
||||||
|
|
||||||
late final String _roomId;
|
late final String _roomId;
|
||||||
int _currentPage = 0;
|
int _currentPage = 0;
|
||||||
@@ -96,28 +301,42 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
_database = ref.watch(databaseProvider);
|
_database = ref.watch(databaseProvider);
|
||||||
final room = await ref.watch(chatroomProvider(roomId).future);
|
final room = await ref.watch(chatroomProvider(roomId).future);
|
||||||
final identity = await ref.watch(chatroomIdentityProvider(roomId).future);
|
final identity = await ref.watch(chatroomIdentityProvider(roomId).future);
|
||||||
if (room == null || identity == null) {
|
|
||||||
throw Exception('Room or identity not found');
|
if (room == null) {
|
||||||
|
throw Exception('Room not found');
|
||||||
}
|
}
|
||||||
_room = room;
|
_room = room;
|
||||||
_identity = identity;
|
|
||||||
|
// Allow building even if identity is null for public rooms
|
||||||
|
if (identity != null) {
|
||||||
|
_identity = identity;
|
||||||
|
}
|
||||||
|
|
||||||
developer.log(
|
developer.log(
|
||||||
'MessagesNotifier built for room $roomId',
|
'MessagesNotifier built for room $roomId',
|
||||||
name: 'MessagesNotifier',
|
name: 'MessagesNotifier',
|
||||||
);
|
);
|
||||||
|
|
||||||
ref.listen(appLifecycleStateProvider, (_, next) {
|
// Only setup sync and lifecycle listeners if user is a member
|
||||||
if (next.hasValue && next.value == AppLifecycleState.resumed) {
|
if (identity != null) {
|
||||||
developer.log(
|
ref.listen(appLifecycleStateProvider, (_, next) {
|
||||||
'App resumed, syncing messages',
|
if (next.hasValue && next.value == AppLifecycleState.resumed) {
|
||||||
name: 'MessagesNotifier',
|
developer.log(
|
||||||
);
|
'App resumed, syncing messages',
|
||||||
syncMessages();
|
name: 'MessagesNotifier',
|
||||||
}
|
);
|
||||||
});
|
syncMessages();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
return await loadInitial();
|
loadInitial();
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LocalChatMessage> _sortMessages(List<LocalChatMessage> messages) {
|
||||||
|
messages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||||
|
return messages;
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> _getCachedMessages({
|
Future<List<LocalChatMessage>> _getCachedMessages({
|
||||||
@@ -128,13 +347,32 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
'Getting cached messages from offset $offset, take $take',
|
'Getting cached messages from offset $offset, take $take',
|
||||||
name: 'MessagesNotifier',
|
name: 'MessagesNotifier',
|
||||||
);
|
);
|
||||||
final dbMessages = await _database.getMessagesForRoom(
|
final List<LocalChatMessage> dbMessages;
|
||||||
_roomId,
|
if (_searchQuery != null && _searchQuery!.isNotEmpty) {
|
||||||
offset: offset,
|
dbMessages = await _database.searchMessages(_roomId, _searchQuery ?? '');
|
||||||
limit: take,
|
} else {
|
||||||
);
|
final chatMessagesFromDb = await _database.getMessagesForRoom(
|
||||||
final dbLocalMessages =
|
_roomId,
|
||||||
dbMessages.map(_database.companionToMessage).toList();
|
offset: offset,
|
||||||
|
limit: take,
|
||||||
|
);
|
||||||
|
dbMessages =
|
||||||
|
chatMessagesFromDb.map(_database.companionToMessage).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
List<LocalChatMessage> filteredMessages = dbMessages;
|
||||||
|
|
||||||
|
if (_withLinks == true) {
|
||||||
|
filteredMessages =
|
||||||
|
filteredMessages.where((msg) => _hasLink(msg)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (_withAttachments == true) {
|
||||||
|
filteredMessages =
|
||||||
|
filteredMessages.where((msg) => _hasAttachment(msg)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
|
final dbLocalMessages = filteredMessages;
|
||||||
|
|
||||||
if (offset == 0) {
|
if (offset == 0) {
|
||||||
final pendingForRoom =
|
final pendingForRoom =
|
||||||
@@ -143,7 +381,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
final allMessages = [...pendingForRoom, ...dbLocalMessages];
|
final allMessages = [...pendingForRoom, ...dbLocalMessages];
|
||||||
allMessages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
_sortMessages(allMessages); // Use the helper function
|
||||||
|
|
||||||
final uniqueMessages = <LocalChatMessage>[];
|
final uniqueMessages = <LocalChatMessage>[];
|
||||||
final seenIds = <String>{};
|
final seenIds = <String>{};
|
||||||
@@ -218,7 +456,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
_isSyncing = true;
|
_isSyncing = true;
|
||||||
|
|
||||||
developer.log('Starting message sync', name: 'MessagesNotifier');
|
developer.log('Starting message sync', name: 'MessagesNotifier');
|
||||||
ref.read(isSyncingProvider.notifier).state = true;
|
Future.microtask(() => ref.read(isSyncingProvider.notifier).state = true);
|
||||||
try {
|
try {
|
||||||
final dbMessages = await _database.getMessagesForRoom(
|
final dbMessages = await _database.getMessagesForRoom(
|
||||||
_room.id,
|
_room.id,
|
||||||
@@ -279,7 +517,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
} finally {
|
} finally {
|
||||||
developer.log('Finished message sync', name: 'MessagesNotifier');
|
developer.log('Finished message sync', name: 'MessagesNotifier');
|
||||||
ref.read(isSyncingProvider.notifier).state = false;
|
Future.microtask(
|
||||||
|
() => ref.read(isSyncingProvider.notifier).state = false,
|
||||||
|
);
|
||||||
_isSyncing = false;
|
_isSyncing = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -290,7 +530,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
bool synced = false,
|
bool synced = false,
|
||||||
}) async {
|
}) async {
|
||||||
try {
|
try {
|
||||||
if (offset == 0 && !synced) {
|
if (offset == 0 &&
|
||||||
|
!synced &&
|
||||||
|
(_searchQuery == null || _searchQuery!.isEmpty)) {
|
||||||
_fetchAndCacheMessages(offset: 0, take: take).catchError((_) {
|
_fetchAndCacheMessages(offset: 0, take: take).catchError((_) {
|
||||||
return <LocalChatMessage>[];
|
return <LocalChatMessage>[];
|
||||||
});
|
});
|
||||||
@@ -305,7 +547,11 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
return localMessages;
|
return localMessages;
|
||||||
}
|
}
|
||||||
|
|
||||||
return await _fetchAndCacheMessages(offset: offset, take: take);
|
if (_searchQuery == null || _searchQuery!.isEmpty) {
|
||||||
|
return await _fetchAndCacheMessages(offset: offset, take: take);
|
||||||
|
} else {
|
||||||
|
return []; // If searching, and no local messages, don't fetch from network
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
final localMessages = await _getCachedMessages(
|
final localMessages = await _getCachedMessages(
|
||||||
offset: offset,
|
offset: offset,
|
||||||
@@ -319,13 +565,15 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> loadInitial() async {
|
Future<void> loadInitial() async {
|
||||||
developer.log('Loading initial messages', name: 'MessagesNotifier');
|
developer.log('Loading initial messages', name: 'MessagesNotifier');
|
||||||
syncMessages();
|
if (_searchQuery == null || _searchQuery!.isEmpty) {
|
||||||
|
syncMessages();
|
||||||
|
}
|
||||||
final messages = await _getCachedMessages(offset: 0, take: 100);
|
final messages = await _getCachedMessages(offset: 0, take: 100);
|
||||||
_currentPage = 0;
|
_currentPage = 0;
|
||||||
_hasMore = messages.length == _pageSize;
|
_hasMore = messages.length == _pageSize;
|
||||||
return messages;
|
state = AsyncValue.data(messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> loadMore() async {
|
Future<void> loadMore() async {
|
||||||
@@ -344,7 +592,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
_hasMore = false;
|
_hasMore = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
state = AsyncValue.data([...currentMessages, ...newMessages]);
|
state = AsyncValue.data(
|
||||||
|
_sortMessages([...currentMessages, ...newMessages]),
|
||||||
|
);
|
||||||
} catch (err, stackTrace) {
|
} catch (err, stackTrace) {
|
||||||
developer.log(
|
developer.log(
|
||||||
'Error loading more messages',
|
'Error loading more messages',
|
||||||
@@ -455,10 +705,13 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
|
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = state.value ?? [];
|
||||||
if (editingTo != null) {
|
if (editingTo != null) {
|
||||||
final newMessages = currentMessages
|
final newMessages =
|
||||||
.where((m) => m.id != localMessage.id) // remove pending message
|
currentMessages
|
||||||
.map((m) => m.id == editingTo.id ? updatedMessage : m) // update original message
|
.where((m) => m.id != localMessage.id) // remove pending message
|
||||||
.toList();
|
.map(
|
||||||
|
(m) => m.id == editingTo.id ? updatedMessage : m,
|
||||||
|
) // update original message
|
||||||
|
.toList();
|
||||||
state = AsyncValue.data(newMessages);
|
state = AsyncValue.data(newMessages);
|
||||||
} else {
|
} else {
|
||||||
final newMessages =
|
final newMessages =
|
||||||
@@ -566,7 +819,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
}
|
}
|
||||||
return m;
|
return m;
|
||||||
}).toList();
|
}).toList();
|
||||||
state = AsyncValue.data(newMessages);
|
state = AsyncValue.data(_sortMessages(newMessages));
|
||||||
showErrorAlert(e);
|
showErrorAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -626,7 +879,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
if (index >= 0) {
|
if (index >= 0) {
|
||||||
final newList = [...currentMessages];
|
final newList = [...currentMessages];
|
||||||
newList[index] = updatedMessage;
|
newList[index] = updatedMessage;
|
||||||
state = AsyncValue.data(newList);
|
state = AsyncValue.data(_sortMessages(newList));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -686,6 +939,20 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void searchMessages(String query, {bool? withLinks, bool? withAttachments}) {
|
||||||
|
_searchQuery = query.trim();
|
||||||
|
_withLinks = withLinks;
|
||||||
|
_withAttachments = withAttachments;
|
||||||
|
loadInitial();
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearSearch() {
|
||||||
|
_searchQuery = null;
|
||||||
|
_withLinks = null;
|
||||||
|
_withAttachments = null;
|
||||||
|
loadInitial();
|
||||||
|
}
|
||||||
|
|
||||||
Future<LocalChatMessage?> fetchMessageById(String messageId) async {
|
Future<LocalChatMessage?> fetchMessageById(String messageId) async {
|
||||||
developer.log(
|
developer.log(
|
||||||
'Fetching message by id $messageId',
|
'Fetching message by id $messageId',
|
||||||
@@ -715,6 +982,18 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
rethrow;
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool _hasLink(LocalChatMessage message) {
|
||||||
|
final content = message.toRemoteMessage().content;
|
||||||
|
if (content == null) return false;
|
||||||
|
final urlRegex = RegExp(r'https?://[^\s/$.?#].[^\s]*');
|
||||||
|
return urlRegex.hasMatch(content);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool _hasAttachment(LocalChatMessage message) {
|
||||||
|
final remoteMessage = message.toRemoteMessage();
|
||||||
|
return remoteMessage.attachments.isNotEmpty;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class ChatRoomScreen extends HookConsumerWidget {
|
class ChatRoomScreen extends HookConsumerWidget {
|
||||||
@@ -734,57 +1013,77 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
} else if (chatIdentity.value == null) {
|
} else if (chatIdentity.value == null) {
|
||||||
// Identity was not found, user was not joined
|
// Identity was not found, user was not joined
|
||||||
return AppScaffold(
|
return chatRoom.when(
|
||||||
appBar: AppBar(leading: const PageBackButton()),
|
data: (room) {
|
||||||
body: Center(
|
if (room!.isPublic) {
|
||||||
child:
|
// Show public room preview with messages but no input
|
||||||
ConstrainedBox(
|
return _PublicRoomPreview(id: id, room: room);
|
||||||
constraints: const BoxConstraints(maxWidth: 280),
|
} else {
|
||||||
child: Column(
|
// Show regular "not joined" screen for private rooms
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
return AppScaffold(
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
appBar: AppBar(leading: const PageBackButton()),
|
||||||
children: [
|
body: Center(
|
||||||
Icon(
|
child:
|
||||||
chatRoom.value?.isCommunity == true
|
ConstrainedBox(
|
||||||
? Symbols.person_add
|
constraints: const BoxConstraints(maxWidth: 280),
|
||||||
: Symbols.person_remove,
|
child: Column(
|
||||||
size: 36,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
fill: 1,
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
).padding(bottom: 4),
|
children: [
|
||||||
Text('chatNotJoined').tr(),
|
Icon(
|
||||||
if (chatRoom.value?.isCommunity != true)
|
room.isCommunity == true
|
||||||
Text(
|
? Symbols.person_add
|
||||||
'chatUnableJoin',
|
: Symbols.person_remove,
|
||||||
textAlign: TextAlign.center,
|
size: 36,
|
||||||
).tr().bold()
|
fill: 1,
|
||||||
else
|
).padding(bottom: 4),
|
||||||
FilledButton.tonalIcon(
|
Text('chatNotJoined').tr(),
|
||||||
onPressed: () async {
|
if (room.isCommunity != true)
|
||||||
try {
|
Text(
|
||||||
showLoadingModal(context);
|
'chatUnableJoin',
|
||||||
final apiClient = ref.read(apiClientProvider);
|
textAlign: TextAlign.center,
|
||||||
if (chatRoom.value == null) {
|
).tr().bold()
|
||||||
hideLoadingModal(context);
|
else
|
||||||
return;
|
FilledButton.tonalIcon(
|
||||||
}
|
onPressed: () async {
|
||||||
|
try {
|
||||||
await apiClient.post(
|
showLoadingModal(context);
|
||||||
'/sphere/chat/${chatRoom.value!.id}/members/me',
|
final apiClient = ref.read(apiClientProvider);
|
||||||
);
|
await apiClient.post(
|
||||||
ref.invalidate(chatroomIdentityProvider(id));
|
'/sphere/chat/${room.id}/members/me',
|
||||||
} catch (err) {
|
);
|
||||||
showErrorAlert(err);
|
ref.invalidate(chatroomIdentityProvider(id));
|
||||||
} finally {
|
} catch (err) {
|
||||||
if (context.mounted) hideLoadingModal(context);
|
showErrorAlert(err);
|
||||||
}
|
} finally {
|
||||||
},
|
if (context.mounted) {
|
||||||
label: Text('chatJoin').tr(),
|
hideLoadingModal(context);
|
||||||
icon: const Icon(Icons.add),
|
}
|
||||||
).padding(top: 8),
|
}
|
||||||
],
|
},
|
||||||
),
|
label: Text('chatJoin').tr(),
|
||||||
).center(),
|
icon: const Icon(Icons.add),
|
||||||
),
|
).padding(top: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).center(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
loading:
|
||||||
|
() => AppScaffold(
|
||||||
|
appBar: AppBar(leading: const PageBackButton()),
|
||||||
|
body: CircularProgressIndicator().center(),
|
||||||
|
),
|
||||||
|
error:
|
||||||
|
(error, _) => AppScaffold(
|
||||||
|
appBar: AppBar(leading: const PageBackButton()),
|
||||||
|
body: ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => ref.refresh(chatroomProvider(id)),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -953,26 +1252,32 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
}, [id]);
|
}, [id]);
|
||||||
|
|
||||||
Future<void> pickPhotoMedia() async {
|
Future<void> pickPhotoMedia() async {
|
||||||
final result = await ref
|
final result = await FilePicker.platform.pickFiles(
|
||||||
.watch(imagePickerProvider)
|
type: FileType.image,
|
||||||
.pickMultiImage(requestFullMetadata: true);
|
allowMultiple: true,
|
||||||
if (result.isEmpty) return;
|
allowCompression: false,
|
||||||
|
);
|
||||||
|
if (result == null || result.count == 0) return;
|
||||||
attachments.value = [
|
attachments.value = [
|
||||||
...attachments.value,
|
...attachments.value,
|
||||||
...result.map(
|
...result.files.map(
|
||||||
(e) => UniversalFile(data: e, type: UniversalFileType.image),
|
(e) => UniversalFile(data: e, type: UniversalFileType.image),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> pickVideoMedia() async {
|
Future<void> pickVideoMedia() async {
|
||||||
final result = await ref
|
final result = await FilePicker.platform.pickFiles(
|
||||||
.watch(imagePickerProvider)
|
type: FileType.video,
|
||||||
.pickVideo(source: ImageSource.gallery);
|
allowMultiple: true,
|
||||||
if (result == null) return;
|
allowCompression: false,
|
||||||
|
);
|
||||||
|
if (result == null || result.count == 0) return;
|
||||||
attachments.value = [
|
attachments.value = [
|
||||||
...attachments.value,
|
...attachments.value,
|
||||||
UniversalFile(data: result, type: UniversalFileType.video),
|
...result.files.map(
|
||||||
|
(e) => UniversalFile(data: e, type: UniversalFileType.video),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1089,6 +1394,8 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
const messageKeyPrefix = 'message-';
|
||||||
|
|
||||||
Widget chatMessageListWidget(List<LocalChatMessage> messageList) =>
|
Widget chatMessageListWidget(List<LocalChatMessage> messageList) =>
|
||||||
SuperListView.builder(
|
SuperListView.builder(
|
||||||
listController: listController,
|
listController: listController,
|
||||||
@@ -1098,7 +1405,9 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
itemCount: messageList.length,
|
itemCount: messageList.length,
|
||||||
findChildIndexCallback: (key) {
|
findChildIndexCallback: (key) {
|
||||||
final valueKey = key as ValueKey;
|
final valueKey = key as ValueKey;
|
||||||
final messageId = valueKey.value as String;
|
final messageId = (valueKey.value as String).substring(
|
||||||
|
messageKeyPrefix.length,
|
||||||
|
);
|
||||||
return messageList.indexWhere((m) => m.id == messageId);
|
return messageList.indexWhere((m) => m.id == messageId);
|
||||||
},
|
},
|
||||||
extentEstimation: (_, _) => 40,
|
extentEstimation: (_, _) => 40,
|
||||||
@@ -1115,10 +1424,13 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
.abs() >
|
.abs() >
|
||||||
3;
|
3;
|
||||||
|
|
||||||
|
final key = ValueKey('$messageKeyPrefix${message.id}');
|
||||||
|
|
||||||
return chatIdentity.when(
|
return chatIdentity.when(
|
||||||
skipError: true,
|
skipError: true,
|
||||||
data:
|
data:
|
||||||
(identity) => MessageItem(
|
(identity) => MessageItem(
|
||||||
|
key: key,
|
||||||
message: message,
|
message: message,
|
||||||
isCurrentUser: identity?.id == message.senderId,
|
isCurrentUser: identity?.id == message.senderId,
|
||||||
onAction: (action) {
|
onAction: (action) {
|
||||||
@@ -1161,6 +1473,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
loading:
|
loading:
|
||||||
() => MessageItem(
|
() => MessageItem(
|
||||||
|
key: key,
|
||||||
message: message,
|
message: message,
|
||||||
isCurrentUser: false,
|
isCurrentUser: false,
|
||||||
onAction: null,
|
onAction: null,
|
||||||
@@ -1168,7 +1481,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
showAvatar: false,
|
showAvatar: false,
|
||||||
onJump: (_) {},
|
onJump: (_) {},
|
||||||
),
|
),
|
||||||
error: (_, _) => const SizedBox.shrink(),
|
error: (_, _) => SizedBox.shrink(key: key),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -1549,7 +1862,7 @@ class _ChatInput extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
IconButton(
|
IconButton(
|
||||||
tooltip: 'stickers'.tr(),
|
tooltip: 'stickers'.tr(),
|
||||||
icon: const Icon(Symbols.emoji_symbols),
|
icon: const Icon(Symbols.add_reaction),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
final size = MediaQuery.of(context).size;
|
final size = MediaQuery.of(context).size;
|
||||||
showStickerPickerPopover(
|
showStickerPickerPopover(
|
||||||
@@ -1659,8 +1972,13 @@ class _ChatInput extends HookConsumerWidget {
|
|||||||
horizontal: 12,
|
horizontal: 12,
|
||||||
vertical: 4,
|
vertical: 4,
|
||||||
),
|
),
|
||||||
|
counterText:
|
||||||
|
messageController.text.length > 1024
|
||||||
|
? '${messageController.text.length}/4096'
|
||||||
|
: null,
|
||||||
),
|
),
|
||||||
maxLines: null,
|
maxLines: 3,
|
||||||
|
minLines: 1,
|
||||||
onTapOutside:
|
onTapOutside:
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
|
@@ -6,7 +6,7 @@ part of 'room.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$messagesNotifierHash() => r'32afe6ea24086d869cc47bd3389c8fd734409ca0';
|
String _$messagesNotifierHash() => r'fc3b66dfb8dd3fc55d142dae5c5e7bdc67eca5d4';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
@@ -9,6 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/screens/chat/chat.dart';
|
import 'package:island/screens/chat/chat.dart';
|
||||||
|
import 'package:island/widgets/account/account_pfc.dart';
|
||||||
import 'package:island/widgets/account/account_picker.dart';
|
import 'package:island/widgets/account/account_picker.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
@@ -19,10 +20,17 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:island/pods/database.dart';
|
||||||
|
|
||||||
part 'room_detail.freezed.dart';
|
part 'room_detail.freezed.dart';
|
||||||
part 'room_detail.g.dart';
|
part 'room_detail.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<int> totalMessagesCount(Ref ref, String roomId) async {
|
||||||
|
final database = ref.watch(databaseProvider);
|
||||||
|
return database.getTotalMessagesForRoom(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
class ChatDetailScreen extends HookConsumerWidget {
|
class ChatDetailScreen extends HookConsumerWidget {
|
||||||
final String id;
|
final String id;
|
||||||
const ChatDetailScreen({super.key, required this.id});
|
const ChatDetailScreen({super.key, required this.id});
|
||||||
@@ -31,6 +39,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final roomState = ref.watch(chatroomProvider(id));
|
final roomState = ref.watch(chatroomProvider(id));
|
||||||
final roomIdentity = ref.watch(chatroomIdentityProvider(id));
|
final roomIdentity = ref.watch(chatroomIdentityProvider(id));
|
||||||
|
final totalMessages = ref.watch(totalMessagesCountProvider(id));
|
||||||
|
|
||||||
const kNotifyLevelText = [
|
const kNotifyLevelText = [
|
||||||
'chatNotifyLevelAll',
|
'chatNotifyLevelAll',
|
||||||
@@ -131,7 +140,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
const Text('chatBreakDescription').tr(),
|
const Text('chatBreakDescription').tr(),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('Clear').tr(),
|
title: const Text('chatBreakClearButton').tr(),
|
||||||
subtitle: const Text('chatBreakClear').tr(),
|
subtitle: const Text('chatBreakClear').tr(),
|
||||||
leading: const Icon(Icons.notifications_active),
|
leading: const Icon(Icons.notifications_active),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -143,8 +152,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('5m'),
|
title: const Text('chatBreak5m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['5m']),
|
subtitle: const Text(
|
||||||
|
'chatBreakHour',
|
||||||
|
).tr(args: ['chatBreak5m'.tr()]),
|
||||||
leading: const Icon(Symbols.circle),
|
leading: const Icon(Symbols.circle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 5)));
|
setChatBreak(now.add(const Duration(minutes: 5)));
|
||||||
@@ -155,8 +166,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('10m'),
|
title: const Text('chatBreak10m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['10m']),
|
subtitle: const Text(
|
||||||
|
'chatBreakHour',
|
||||||
|
).tr(args: ['chatBreak10m'.tr()]),
|
||||||
leading: const Icon(Symbols.circle),
|
leading: const Icon(Symbols.circle),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 10)));
|
setChatBreak(now.add(const Duration(minutes: 10)));
|
||||||
@@ -167,8 +180,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('15m'),
|
title: const Text('chatBreak15m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['15m']),
|
subtitle: const Text(
|
||||||
|
'chatBreakHour',
|
||||||
|
).tr(args: ['chatBreak15m'.tr()]),
|
||||||
leading: const Icon(Symbols.timer_3),
|
leading: const Icon(Symbols.timer_3),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 15)));
|
setChatBreak(now.add(const Duration(minutes: 15)));
|
||||||
@@ -179,8 +194,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
title: const Text('30m'),
|
title: const Text('chatBreak30m').tr(),
|
||||||
subtitle: const Text('chatBreakHour').tr(args: ['30m']),
|
subtitle: const Text(
|
||||||
|
'chatBreakHour',
|
||||||
|
).tr(args: ['chatBreak30m'.tr()]),
|
||||||
leading: const Icon(Symbols.timer),
|
leading: const Icon(Symbols.timer),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
setChatBreak(now.add(const Duration(minutes: 30)));
|
setChatBreak(now.add(const Duration(minutes: 30)));
|
||||||
@@ -194,8 +211,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
TextField(
|
TextField(
|
||||||
controller: durationController,
|
controller: durationController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
labelText: 'Custom (minutes)'.tr(),
|
labelText: 'chatBreakCustomMinutes'.tr(),
|
||||||
hintText: 'Enter minutes'.tr(),
|
hintText: 'chatBreakEnterMinutes'.tr(),
|
||||||
border: const OutlineInputBorder(),
|
border: const OutlineInputBorder(),
|
||||||
suffixIcon: IconButton(
|
suffixIcon: IconButton(
|
||||||
icon: const Icon(Icons.check),
|
icon: const Icon(Icons.check),
|
||||||
@@ -238,7 +255,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
body: roomState.when(
|
body: roomState.when(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, _) => Center(child: Text('Error: $error')),
|
error:
|
||||||
|
(error, _) => Center(
|
||||||
|
child: Text('errorGeneric'.tr(args: [error.toString()])),
|
||||||
|
),
|
||||||
data:
|
data:
|
||||||
(currentRoom) => CustomScrollView(
|
(currentRoom) => CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
@@ -358,6 +378,36 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
: const Text('chatBreakNone').tr(),
|
: const Text('chatBreakNone').tr(),
|
||||||
onTap: () => showChatBreakDialog(),
|
onTap: () => showChatBreakDialog(),
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
leading: const Icon(Icons.search),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
title: const Text('searchMessages').tr(),
|
||||||
|
subtitle: totalMessages.when(
|
||||||
|
data:
|
||||||
|
(count) => Text(
|
||||||
|
'messagesCount'.tr(
|
||||||
|
args: [count.toString()],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
loading:
|
||||||
|
() => const CircularProgressIndicator(),
|
||||||
|
error:
|
||||||
|
(err, stack) => Text(
|
||||||
|
'errorGeneric'.tr(
|
||||||
|
args: [err.toString()],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
context.pushNamed(
|
||||||
|
'searchMessages',
|
||||||
|
pathParameters: {'id': id},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
error: (_, _) => const SizedBox.shrink(),
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
@@ -666,8 +716,11 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
final member = data.items[index];
|
final member = data.items[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
||||||
leading: ProfilePictureWidget(
|
leading: AccountPfcGestureDetector(
|
||||||
fileId: member.account.profile.picture?.id,
|
uname: member.account.name,
|
||||||
|
child: ProfilePictureWidget(
|
||||||
|
fileId: member.account.profile.picture?.id,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
@@ -848,7 +901,7 @@ class _ChatMemberRoleSheet extends HookConsumerWidget {
|
|||||||
try {
|
try {
|
||||||
final newRole = int.parse(roleController.text);
|
final newRole = int.parse(roleController.text);
|
||||||
if (newRole < 0 || newRole > 100) {
|
if (newRole < 0 || newRole > 100) {
|
||||||
throw 'Role must be between 0 and 100';
|
throw 'roleValidationHint'.tr();
|
||||||
}
|
}
|
||||||
|
|
||||||
final apiClient = ref.read(apiClientProvider);
|
final apiClient = ref.read(apiClientProvider);
|
||||||
|
@@ -6,8 +6,8 @@ part of 'room_detail.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$chatMemberListNotifierHash() =>
|
String _$totalMessagesCountHash() =>
|
||||||
r'3ea30150278523e9f6b23f9200ea9a9fbae9c973';
|
r'a15c03461f25c2d4d39c0926509bf626ae2550a6';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -30,6 +30,128 @@ class _SystemHash {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
@ProviderFor(totalMessagesCount)
|
||||||
|
const totalMessagesCountProvider = TotalMessagesCountFamily();
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
class TotalMessagesCountFamily extends Family<AsyncValue<int>> {
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
const TotalMessagesCountFamily();
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
TotalMessagesCountProvider call(String roomId) {
|
||||||
|
return TotalMessagesCountProvider(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TotalMessagesCountProvider getProviderOverride(
|
||||||
|
covariant TotalMessagesCountProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'totalMessagesCountProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
class TotalMessagesCountProvider extends AutoDisposeFutureProvider<int> {
|
||||||
|
/// See also [totalMessagesCount].
|
||||||
|
TotalMessagesCountProvider(String roomId)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => totalMessagesCount(ref as TotalMessagesCountRef, roomId),
|
||||||
|
from: totalMessagesCountProvider,
|
||||||
|
name: r'totalMessagesCountProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$totalMessagesCountHash,
|
||||||
|
dependencies: TotalMessagesCountFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
TotalMessagesCountFamily._allTransitiveDependencies,
|
||||||
|
roomId: roomId,
|
||||||
|
);
|
||||||
|
|
||||||
|
TotalMessagesCountProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.roomId,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String roomId;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<int> Function(TotalMessagesCountRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: TotalMessagesCountProvider._internal(
|
||||||
|
(ref) => create(ref as TotalMessagesCountRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
roomId: roomId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<int> createElement() {
|
||||||
|
return _TotalMessagesCountProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is TotalMessagesCountProvider && other.roomId == roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, roomId.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin TotalMessagesCountRef on AutoDisposeFutureProviderRef<int> {
|
||||||
|
/// The parameter `roomId` of this provider.
|
||||||
|
String get roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TotalMessagesCountProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<int>
|
||||||
|
with TotalMessagesCountRef {
|
||||||
|
_TotalMessagesCountProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get roomId => (origin as TotalMessagesCountProvider).roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$chatMemberListNotifierHash() =>
|
||||||
|
r'3ea30150278523e9f6b23f9200ea9a9fbae9c973';
|
||||||
|
|
||||||
abstract class _$ChatMemberListNotifier
|
abstract class _$ChatMemberListNotifier
|
||||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> {
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> {
|
||||||
late final String roomId;
|
late final String roomId;
|
||||||
|
139
lib/screens/chat/search_messages_screen.dart
Normal file
139
lib/screens/chat/search_messages_screen.dart
Normal file
@@ -0,0 +1,139 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/screens/chat/room.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/chat/message_item.dart';
|
||||||
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
|
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||||
|
|
||||||
|
class SearchMessagesScreen extends HookConsumerWidget {
|
||||||
|
final String roomId;
|
||||||
|
|
||||||
|
const SearchMessagesScreen({super.key, required this.roomId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final searchController = useTextEditingController();
|
||||||
|
final withLinks = useState(false);
|
||||||
|
final withAttachments = useState(false);
|
||||||
|
|
||||||
|
final messagesNotifier = ref.read(
|
||||||
|
messagesNotifierProvider(roomId).notifier,
|
||||||
|
);
|
||||||
|
final messages = ref.watch(messagesNotifierProvider(roomId));
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
// Clear search when screen is disposed
|
||||||
|
return () {
|
||||||
|
messagesNotifier.clearSearch();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
return AppScaffold(
|
||||||
|
appBar: AppBar(title: const Text('searchMessages').tr()),
|
||||||
|
body: Column(
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: searchController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
hintText: 'searchMessagesHint'.tr(),
|
||||||
|
border: InputBorder.none,
|
||||||
|
isDense: true,
|
||||||
|
contentPadding: EdgeInsets.only(
|
||||||
|
left: 16,
|
||||||
|
right: 16,
|
||||||
|
top: 12,
|
||||||
|
bottom: 16,
|
||||||
|
),
|
||||||
|
suffix: IconButton(
|
||||||
|
iconSize: 18,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
icon: const Icon(Icons.clear),
|
||||||
|
onPressed: () {
|
||||||
|
searchController.clear();
|
||||||
|
messagesNotifier.clearSearch();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
onChanged: (query) {
|
||||||
|
messagesNotifier.searchMessages(
|
||||||
|
query,
|
||||||
|
withLinks: withLinks.value,
|
||||||
|
withAttachments: withAttachments.value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: CheckboxListTile(
|
||||||
|
secondary: const Icon(Symbols.link),
|
||||||
|
title: const Text('searchLinks').tr(),
|
||||||
|
value: withLinks.value,
|
||||||
|
onChanged: (bool? value) {
|
||||||
|
withLinks.value = value!;
|
||||||
|
messagesNotifier.searchMessages(
|
||||||
|
searchController.text,
|
||||||
|
withLinks: withLinks.value,
|
||||||
|
withAttachments: withAttachments.value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: CheckboxListTile(
|
||||||
|
secondary: const Icon(Symbols.file_copy),
|
||||||
|
title: const Text('searchAttachments').tr(),
|
||||||
|
value: withAttachments.value,
|
||||||
|
onChanged: (bool? value) {
|
||||||
|
withAttachments.value = value!;
|
||||||
|
messagesNotifier.searchMessages(
|
||||||
|
searchController.text,
|
||||||
|
withLinks: withLinks.value,
|
||||||
|
withAttachments: withAttachments.value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
Expanded(
|
||||||
|
child: messages.when(
|
||||||
|
data:
|
||||||
|
(messageList) =>
|
||||||
|
messageList.isEmpty
|
||||||
|
? Center(child: Text('noMessagesFound'.tr()))
|
||||||
|
: SuperListView.builder(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||||
|
reverse: true, // Show newest messages at the bottom
|
||||||
|
itemCount: messageList.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final message = messageList[index];
|
||||||
|
// Simplified MessageItem for search results, no grouping logic
|
||||||
|
return MessageItem(
|
||||||
|
message: message,
|
||||||
|
isCurrentUser:
|
||||||
|
false, // Or determine based on actual user
|
||||||
|
onAction: null,
|
||||||
|
onJump: (_) {},
|
||||||
|
progress: null,
|
||||||
|
showAvatar: true,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error: (error, _) => Center(child: Text('errorGeneric'.tr(args: [error.toString()]))),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -27,7 +27,9 @@ class AppDetailScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final tabController = useTabController(initialLength: 2);
|
final tabController = useTabController(initialLength: 2);
|
||||||
final appData = ref.watch(customAppProvider(publisherName, projectId, appId));
|
final appData = ref.watch(
|
||||||
|
customAppProvider(publisherName, projectId, appId),
|
||||||
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
@@ -35,23 +37,43 @@ class AppDetailScreen extends HookConsumerWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.edit),
|
icon: const Icon(Symbols.edit),
|
||||||
onPressed: appData.value == null
|
onPressed:
|
||||||
? null
|
appData.value == null
|
||||||
: () {
|
? null
|
||||||
context.pushNamed(
|
: () {
|
||||||
'developerAppEdit',
|
context.pushNamed(
|
||||||
pathParameters: {
|
'developerAppEdit',
|
||||||
'name': publisherName,
|
pathParameters: {
|
||||||
'projectId': projectId,
|
'name': publisherName,
|
||||||
'id': appId,
|
'projectId': projectId,
|
||||||
},
|
'id': appId,
|
||||||
);
|
},
|
||||||
},
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [Tab(text: 'overview'.tr()), Tab(text: 'secrets'.tr())],
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'overview'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'secrets'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: appData.when(
|
body: appData.when(
|
||||||
@@ -70,12 +92,14 @@ class AppDetailScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (err, stack) => ResponseErrorWidget(
|
error:
|
||||||
error: err,
|
(err, stack) => ResponseErrorWidget(
|
||||||
onRetry: () => ref.invalidate(
|
error: err,
|
||||||
customAppProvider(publisherName, projectId, appId),
|
onRetry:
|
||||||
),
|
() => ref.invalidate(
|
||||||
),
|
customAppProvider(publisherName, projectId, appId),
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -98,12 +122,13 @@ class _AppOverview extends StatelessWidget {
|
|||||||
children: [
|
children: [
|
||||||
Container(
|
Container(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
child: app.background != null
|
child:
|
||||||
? CloudFileWidget(
|
app.background != null
|
||||||
item: app.background!,
|
? CloudFileWidget(
|
||||||
fit: BoxFit.cover,
|
item: app.background!,
|
||||||
)
|
fit: BoxFit.cover,
|
||||||
: const SizedBox.shrink(),
|
)
|
||||||
|
: const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 20,
|
left: 20,
|
||||||
|
@@ -52,7 +52,26 @@ class BotDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [Tab(text: 'overview'.tr()), Tab(text: 'keys'.tr())],
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'overview'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'keys'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: botData.when(
|
body: botData.when(
|
||||||
|
@@ -58,7 +58,26 @@ class ProjectDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [Tab(text: 'customApps'.tr()), Tab(text: 'bots'.tr())],
|
tabs: [
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'customApps'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'bots'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: TabBarView(
|
body: TabBarView(
|
||||||
|
@@ -143,8 +143,26 @@ class ArticlesScreen extends ConsumerWidget {
|
|||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
isScrollable: true,
|
isScrollable: true,
|
||||||
tabs: [
|
tabs: [
|
||||||
const Tab(text: 'All'),
|
Tab(
|
||||||
...feeds.map((feed) => Tab(text: feed.title)),
|
child: Text(
|
||||||
|
'All',
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
...feeds.map(
|
||||||
|
(feed) => Tab(
|
||||||
|
child: Text(
|
||||||
|
feed.title,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -151,7 +151,9 @@ class PostCategoryDetailScreen extends HookConsumerWidget {
|
|||||||
(error, _) => Text(
|
(error, _) => Text(
|
||||||
'Error loading subscription status',
|
'Error loading subscription status',
|
||||||
),
|
),
|
||||||
loading: () => CircularProgressIndicator(),
|
loading:
|
||||||
|
() =>
|
||||||
|
CircularProgressIndicator().center(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, vertical: 16),
|
).padding(horizontal: 24, vertical: 16),
|
||||||
@@ -220,7 +222,9 @@ class PostCategoryDetailScreen extends HookConsumerWidget {
|
|||||||
(error, _) => Text(
|
(error, _) => Text(
|
||||||
'Error loading subscription status',
|
'Error loading subscription status',
|
||||||
),
|
),
|
||||||
loading: () => CircularProgressIndicator(),
|
loading:
|
||||||
|
() =>
|
||||||
|
CircularProgressIndicator().center(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, vertical: 16),
|
).padding(horizontal: 24, vertical: 16),
|
||||||
|
@@ -1,5 +1,7 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
@@ -7,6 +9,7 @@ import 'package:island/widgets/app_scaffold.dart';
|
|||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
import 'package:island/widgets/response.dart';
|
import 'package:island/widgets/response.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
final postSearchNotifierProvider = StateNotifierProvider.autoDispose<
|
final postSearchNotifierProvider = StateNotifierProvider.autoDispose<
|
||||||
PostSearchNotifier,
|
PostSearchNotifier,
|
||||||
@@ -18,6 +21,13 @@ class PostSearchNotifier
|
|||||||
final AutoDisposeRef ref;
|
final AutoDisposeRef ref;
|
||||||
static const int _pageSize = 20;
|
static const int _pageSize = 20;
|
||||||
String _currentQuery = '';
|
String _currentQuery = '';
|
||||||
|
String? _pubName;
|
||||||
|
String? _realm;
|
||||||
|
int? _type;
|
||||||
|
List<String>? _categories;
|
||||||
|
List<String>? _tags;
|
||||||
|
bool _shuffle = false;
|
||||||
|
bool? _pinned;
|
||||||
bool _isLoading = false;
|
bool _isLoading = false;
|
||||||
|
|
||||||
PostSearchNotifier(this.ref) : super(const AsyncValue.loading()) {
|
PostSearchNotifier(this.ref) : super(const AsyncValue.loading()) {
|
||||||
@@ -26,11 +36,38 @@ class PostSearchNotifier
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> search(String query) async {
|
Future<void> search(
|
||||||
|
String query, {
|
||||||
|
String? pubName,
|
||||||
|
String? realm,
|
||||||
|
int? type,
|
||||||
|
List<String>? categories,
|
||||||
|
List<String>? tags,
|
||||||
|
bool shuffle = false,
|
||||||
|
bool? pinned,
|
||||||
|
}) async {
|
||||||
if (_isLoading) return;
|
if (_isLoading) return;
|
||||||
|
|
||||||
_currentQuery = query.trim();
|
_currentQuery = query.trim();
|
||||||
if (_currentQuery.isEmpty) {
|
_pubName = pubName;
|
||||||
|
_realm = realm;
|
||||||
|
_type = type;
|
||||||
|
_categories = categories;
|
||||||
|
_tags = tags;
|
||||||
|
_shuffle = shuffle;
|
||||||
|
_pinned = pinned;
|
||||||
|
|
||||||
|
// Allow search even with empty query if any filters are applied
|
||||||
|
final hasFilters =
|
||||||
|
pubName != null ||
|
||||||
|
realm != null ||
|
||||||
|
type != null ||
|
||||||
|
categories != null ||
|
||||||
|
tags != null ||
|
||||||
|
shuffle ||
|
||||||
|
pinned != null;
|
||||||
|
|
||||||
|
if (_currentQuery.isEmpty && !hasFilters) {
|
||||||
state = AsyncValue.data(
|
state = AsyncValue.data(
|
||||||
CursorPagingData(items: [], hasMore: false, nextCursor: null),
|
CursorPagingData(items: [], hasMore: false, nextCursor: null),
|
||||||
);
|
);
|
||||||
@@ -57,6 +94,13 @@ class PostSearchNotifier
|
|||||||
'offset': offset,
|
'offset': offset,
|
||||||
'take': _pageSize,
|
'take': _pageSize,
|
||||||
'vector': false,
|
'vector': false,
|
||||||
|
if (_pubName != null) 'pub': _pubName,
|
||||||
|
if (_realm != null) 'realm': _realm,
|
||||||
|
if (_type != null) 'type': _type,
|
||||||
|
if (_tags != null) 'tags': _tags,
|
||||||
|
if (_categories != null) 'categories': _categories,
|
||||||
|
if (_shuffle) 'shuffle': true,
|
||||||
|
if (_pinned != null) 'pinned': _pinned,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -80,100 +124,269 @@ class PostSearchNotifier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class PostSearchScreen extends ConsumerStatefulWidget {
|
class PostSearchScreen extends HookConsumerWidget {
|
||||||
const PostSearchScreen({super.key});
|
const PostSearchScreen({super.key});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
ConsumerState<PostSearchScreen> createState() => _PostSearchScreenState();
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
}
|
final searchController = useTextEditingController();
|
||||||
|
final debounce = useMemoized(() => Duration(milliseconds: 500));
|
||||||
|
final debounceTimer = useRef<Timer?>(null);
|
||||||
|
final showFilters = useState(false);
|
||||||
|
final pubNameController = useTextEditingController();
|
||||||
|
final realmController = useTextEditingController();
|
||||||
|
final typeValue = useState<int?>(null);
|
||||||
|
final selectedCategories = useState<List<String>>([]);
|
||||||
|
final selectedTags = useState<List<String>>([]);
|
||||||
|
final shuffleValue = useState(false);
|
||||||
|
final pinnedValue = useState<bool?>(null);
|
||||||
|
|
||||||
class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
|
useEffect(() {
|
||||||
final _searchController = TextEditingController();
|
return () {
|
||||||
final _debounce = Duration(milliseconds: 500);
|
searchController.dispose();
|
||||||
Timer? _debounceTimer;
|
pubNameController.dispose();
|
||||||
|
realmController.dispose();
|
||||||
|
debounceTimer.value?.cancel();
|
||||||
|
};
|
||||||
|
}, []);
|
||||||
|
|
||||||
@override
|
void onSearchChanged(String query) {
|
||||||
void dispose() {
|
if (debounceTimer.value?.isActive ?? false) debounceTimer.value!.cancel();
|
||||||
_searchController.dispose();
|
|
||||||
_debounceTimer?.cancel();
|
|
||||||
super.dispose();
|
|
||||||
}
|
|
||||||
|
|
||||||
void _onSearchChanged(String query) {
|
debounceTimer.value = Timer(debounce, () {
|
||||||
if (_debounceTimer?.isActive ?? false) _debounceTimer!.cancel();
|
ref.read(postSearchNotifierProvider.notifier).search(query);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
_debounceTimer = Timer(_debounce, () {
|
void onSearchWithFilters(String query) {
|
||||||
ref.read(postSearchNotifierProvider.notifier).search(query);
|
if (debounceTimer.value?.isActive ?? false) debounceTimer.value!.cancel();
|
||||||
});
|
|
||||||
}
|
debounceTimer.value = Timer(debounce, () {
|
||||||
|
ref
|
||||||
|
.read(postSearchNotifierProvider.notifier)
|
||||||
|
.search(
|
||||||
|
query,
|
||||||
|
pubName:
|
||||||
|
pubNameController.text.isNotEmpty
|
||||||
|
? pubNameController.text
|
||||||
|
: null,
|
||||||
|
realm:
|
||||||
|
realmController.text.isNotEmpty ? realmController.text : null,
|
||||||
|
type: typeValue.value,
|
||||||
|
categories:
|
||||||
|
selectedCategories.value.isNotEmpty
|
||||||
|
? selectedCategories.value
|
||||||
|
: null,
|
||||||
|
tags: selectedTags.value.isNotEmpty ? selectedTags.value : null,
|
||||||
|
shuffle: shuffleValue.value,
|
||||||
|
pinned: pinnedValue.value,
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void toggleFilters() {
|
||||||
|
showFilters.value = !showFilters.value;
|
||||||
|
}
|
||||||
|
|
||||||
|
void applyFilters() {
|
||||||
|
onSearchWithFilters(searchController.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
void clearFilters() {
|
||||||
|
pubNameController.clear();
|
||||||
|
realmController.clear();
|
||||||
|
typeValue.value = null;
|
||||||
|
selectedCategories.value = [];
|
||||||
|
selectedTags.value = [];
|
||||||
|
shuffleValue.value = false;
|
||||||
|
pinnedValue.value = null;
|
||||||
|
onSearchChanged(searchController.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
Widget buildFilterPanel() {
|
||||||
|
return Card(
|
||||||
|
margin: EdgeInsets.symmetric(vertical: 8, horizontal: 8),
|
||||||
|
child: Padding(
|
||||||
|
padding: EdgeInsets.all(16),
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'filters'.tr(),
|
||||||
|
style: Theme.of(context).textTheme.titleMedium,
|
||||||
|
).padding(left: 4),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: applyFilters,
|
||||||
|
child: Text('apply'.tr()),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: clearFilters,
|
||||||
|
child: Text('clear'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
SizedBox(height: 16),
|
||||||
|
TextField(
|
||||||
|
controller: pubNameController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'pubName'.tr(),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
onChanged:
|
||||||
|
(value) => onSearchWithFilters(searchController.text),
|
||||||
|
),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
TextField(
|
||||||
|
controller: realmController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'realm'.tr(),
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
onChanged:
|
||||||
|
(value) => onSearchWithFilters(searchController.text),
|
||||||
|
),
|
||||||
|
SizedBox(height: 8),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: shuffleValue.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
shuffleValue.value = value ?? false;
|
||||||
|
onSearchWithFilters(searchController.text);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text('shuffle'.tr()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Checkbox(
|
||||||
|
value: pinnedValue.value ?? false,
|
||||||
|
onChanged: (value) {
|
||||||
|
pinnedValue.value = value;
|
||||||
|
onSearchWithFilters(searchController.text);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Text('pinned'.tr()),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
// TODO: Add dropdown for type selection
|
||||||
|
// TODO: Add multi-select for categories and tags
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
isNoBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: TextField(
|
title: Row(
|
||||||
controller: _searchController,
|
children: [
|
||||||
decoration: InputDecoration(
|
Expanded(
|
||||||
hintText: 'Search posts...',
|
child: TextField(
|
||||||
border: InputBorder.none,
|
controller: searchController,
|
||||||
hintStyle: TextStyle(
|
decoration: InputDecoration(
|
||||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
hintText: 'search'.tr(),
|
||||||
|
border: InputBorder.none,
|
||||||
|
hintStyle: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor,
|
||||||
|
),
|
||||||
|
onChanged: onSearchChanged,
|
||||||
|
onSubmitted: (value) {
|
||||||
|
onSearchWithFilters(value);
|
||||||
|
},
|
||||||
|
autofocus: true,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
IconButton(
|
||||||
style: TextStyle(
|
icon: Icon(
|
||||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
showFilters.value
|
||||||
),
|
? Icons.filter_alt
|
||||||
onChanged: _onSearchChanged,
|
: Icons.filter_alt_outlined,
|
||||||
onSubmitted: (value) {
|
),
|
||||||
ref.read(postSearchNotifierProvider.notifier).search(value);
|
onPressed: toggleFilters,
|
||||||
},
|
tooltip: 'toggleFilters'.tr(),
|
||||||
autofocus: true,
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
body: Consumer(
|
body: Consumer(
|
||||||
builder: (context, ref, child) {
|
builder: (context, ref, child) {
|
||||||
final searchState = ref.watch(postSearchNotifierProvider);
|
final searchState = ref.watch(postSearchNotifierProvider);
|
||||||
|
|
||||||
return searchState.when(
|
return CustomScrollView(
|
||||||
data: (data) {
|
slivers: [
|
||||||
if (data.items.isEmpty && _searchController.text.isNotEmpty) {
|
if (showFilters.value)
|
||||||
return const Center(child: Text('No results found'));
|
SliverToBoxAdapter(
|
||||||
}
|
child: Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
return ListView.builder(
|
constraints: const BoxConstraints(maxWidth: 600),
|
||||||
padding: EdgeInsets.zero,
|
child: buildFilterPanel(),
|
||||||
itemCount: data.items.length + (data.hasMore ? 1 : 0),
|
),
|
||||||
itemBuilder: (context, index) {
|
),
|
||||||
if (index >= data.items.length) {
|
),
|
||||||
ref
|
searchState.when(
|
||||||
.read(postSearchNotifierProvider.notifier)
|
data: (data) {
|
||||||
.fetch(cursor: data.nextCursor);
|
if (data.items.isEmpty && searchController.text.isNotEmpty) {
|
||||||
return const Center(child: CircularProgressIndicator());
|
return SliverFillRemaining(
|
||||||
|
child: Center(child: Text('noResultsFound'.tr())),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final post = data.items[index];
|
return SliverList(
|
||||||
return Center(
|
delegate: SliverChildBuilderDelegate((context, index) {
|
||||||
child: ConstrainedBox(
|
if (index >= data.items.length) {
|
||||||
constraints: BoxConstraints(maxWidth: 600),
|
ref
|
||||||
child: Card(
|
.read(postSearchNotifierProvider.notifier)
|
||||||
margin: EdgeInsets.symmetric(
|
.fetch(cursor: data.nextCursor);
|
||||||
horizontal: 8,
|
return Center(child: CircularProgressIndicator());
|
||||||
vertical: 4,
|
}
|
||||||
|
|
||||||
|
final post = data.items[index];
|
||||||
|
return Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: 600),
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
|
child: PostActionableItem(
|
||||||
|
item: post,
|
||||||
|
borderRadius: 8,
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
child: PostActionableItem(item: post, borderRadius: 8),
|
);
|
||||||
),
|
}, childCount: data.items.length + (data.hasMore ? 1 : 0)),
|
||||||
),
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
loading:
|
||||||
},
|
() => SliverFillRemaining(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
child: Center(child: CircularProgressIndicator()),
|
||||||
error:
|
),
|
||||||
(error, stack) => ResponseErrorWidget(
|
error:
|
||||||
error: error,
|
(error, stack) => SliverFillRemaining(
|
||||||
onRetry: () => ref.invalidate(postSearchNotifierProvider),
|
child: ResponseErrorWidget(
|
||||||
),
|
error: error,
|
||||||
|
onRetry:
|
||||||
|
() => ref.invalidate(postSearchNotifierProvider),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
@@ -288,7 +288,11 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
controller: categoryTabController,
|
controller: categoryTabController,
|
||||||
dividerColor: Colors.transparent,
|
dividerColor: Colors.transparent,
|
||||||
splashBorderRadius: const BorderRadius.all(Radius.circular(8)),
|
splashBorderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
tabs: [Tab(text: 'All'), Tab(text: 'Posts'), Tab(text: 'Articles')],
|
tabs: [
|
||||||
|
Tab(text: 'all'.tr()),
|
||||||
|
Tab(text: 'postTypePost'.tr()),
|
||||||
|
Tab(text: 'postArticle'.tr()),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -345,12 +349,14 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverGap(16),
|
SliverGap(16),
|
||||||
|
SliverPostList(pubName: name, pinned: true),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: publisherCategoryTabWidget(),
|
child: publisherCategoryTabWidget(),
|
||||||
),
|
),
|
||||||
SliverPostList(
|
SliverPostList(
|
||||||
key: ValueKey(categoryTab.value),
|
key: ValueKey(categoryTab.value),
|
||||||
pubName: name,
|
pubName: name,
|
||||||
|
pinned: false,
|
||||||
type: switch (categoryTab.value) {
|
type: switch (categoryTab.value) {
|
||||||
1 => 0,
|
1 => 0,
|
||||||
2 => 1,
|
2 => 1,
|
||||||
@@ -433,10 +439,12 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
child: publisherVerificationWidget(data),
|
child: publisherVerificationWidget(data),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(child: publisherBioWidget(data)),
|
SliverToBoxAdapter(child: publisherBioWidget(data)),
|
||||||
|
SliverPostList(pubName: name, pinned: true),
|
||||||
SliverToBoxAdapter(child: publisherCategoryTabWidget()),
|
SliverToBoxAdapter(child: publisherCategoryTabWidget()),
|
||||||
SliverPostList(
|
SliverPostList(
|
||||||
key: ValueKey(categoryTab.value),
|
key: ValueKey(categoryTab.value),
|
||||||
pubName: name,
|
pubName: name,
|
||||||
|
pinned: false,
|
||||||
type: switch (categoryTab.value) {
|
type: switch (categoryTab.value) {
|
||||||
1 => 0,
|
1 => 0,
|
||||||
2 => 1,
|
2 => 1,
|
||||||
|
@@ -5,6 +5,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:island/services/color.dart';
|
import 'package:island/services/color.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
|
import 'package:island/widgets/account/account_pfc.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/post/post_list.dart';
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
import 'package:palette_generator/palette_generator.dart';
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
@@ -244,7 +245,10 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
Flexible(
|
Flexible(
|
||||||
flex: 3,
|
flex: 3,
|
||||||
child: CustomScrollView(
|
child: CustomScrollView(
|
||||||
slivers: [SliverPostList(realm: slug)],
|
slivers: [
|
||||||
|
SliverPostList(realm: slug, pinned: true),
|
||||||
|
SliverPostList(realm: slug, pinned: false),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Flexible(
|
Flexible(
|
||||||
@@ -359,7 +363,8 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: realmChatRoomListWidget(realm),
|
child: realmChatRoomListWidget(realm),
|
||||||
),
|
),
|
||||||
SliverPostList(realm: slug),
|
SliverPostList(realm: slug, pinned: true),
|
||||||
|
SliverPostList(realm: slug, pinned: false),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -654,8 +659,11 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
final member = data.items[index];
|
final member = data.items[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
||||||
leading: ProfilePictureWidget(
|
leading: AccountPfcGestureDetector(
|
||||||
fileId: member.account!.profile.picture?.id,
|
uname: member.account!.name,
|
||||||
|
child: ProfilePictureWidget(
|
||||||
|
fileId: member.account!.profile.picture?.id,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
|
9
lib/utils/format.dart
Normal file
9
lib/utils/format.dart
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
String formatFileSize(int bytes) {
|
||||||
|
if (bytes <= 0) return '0 B';
|
||||||
|
if (bytes < 1024) return '$bytes B';
|
||||||
|
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB';
|
||||||
|
if (bytes < 1024 * 1024 * 1024) {
|
||||||
|
return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB';
|
||||||
|
}
|
||||||
|
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB';
|
||||||
|
}
|
@@ -37,11 +37,28 @@ class AccountName extends StatelessWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
spacing: 4,
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: Text(account.nick, style: nameStyle)),
|
Flexible(
|
||||||
|
child: Text(
|
||||||
|
account.nick,
|
||||||
|
style: nameStyle,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
if (account.perkSubscription != null)
|
if (account.perkSubscription != null)
|
||||||
StellarMembershipMark(membership: account.perkSubscription!),
|
StellarMembershipMark(membership: account.perkSubscription!),
|
||||||
if (account.profile.verification != null)
|
if (account.profile.verification != null)
|
||||||
VerificationMark(mark: account.profile.verification!),
|
VerificationMark(mark: account.profile.verification!),
|
||||||
|
if (account.automatedId != null)
|
||||||
|
Tooltip(
|
||||||
|
message: 'accountAutomated'.tr(),
|
||||||
|
child: Icon(
|
||||||
|
Symbols.smart_toy,
|
||||||
|
size: 16,
|
||||||
|
color: nameStyle.color,
|
||||||
|
fill: 1,
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -141,7 +158,7 @@ class VerificationStatusCard extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
mark.type == 4
|
mark.type == 4
|
||||||
@@ -152,7 +169,7 @@ class VerificationStatusCard extends StatelessWidget {
|
|||||||
size: 32,
|
size: 32,
|
||||||
color: kVerificationMarkColors[mark.type],
|
color: kVerificationMarkColors[mark.type],
|
||||||
fill: 1,
|
fill: 1,
|
||||||
),
|
).alignment(Alignment.centerLeft),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
Text(mark.title ?? 'No title').bold(),
|
Text(mark.title ?? 'No title').bold(),
|
||||||
Text(mark.description ?? 'descriptionNone'.tr()),
|
Text(mark.description ?? 'descriptionNone'.tr()),
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:flutter_popup_card/flutter_popup_card.dart';
|
import 'package:flutter_popup_card/flutter_popup_card.dart';
|
||||||
@@ -74,27 +75,75 @@ class AccountProfileCard extends HookConsumerWidget {
|
|||||||
uname: data.name,
|
uname: data.name,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
if (data.profile.timeZone.isNotEmpty)
|
Tooltip(
|
||||||
Row(
|
message: 'creditsStatus'.tr(),
|
||||||
|
child: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
Symbols.alarm,
|
Symbols.star,
|
||||||
size: 17,
|
size: 17,
|
||||||
fill: 1,
|
fill: 1,
|
||||||
).padding(right: 2),
|
).padding(right: 2),
|
||||||
Text(
|
Text(
|
||||||
getTzInfo(
|
'${data.profile.socialCredits.toStringAsFixed(2)} pts',
|
||||||
data.profile.timeZone,
|
|
||||||
).$2.formatCustomGlobal('HH:mm'),
|
|
||||||
).fontSize(12),
|
|
||||||
Text(
|
|
||||||
getTzInfo(
|
|
||||||
data.profile.timeZone,
|
|
||||||
).$1.formatOffsetLocal(),
|
|
||||||
).fontSize(12),
|
).fontSize(12),
|
||||||
|
switch (data.profile.socialCreditsLevel) {
|
||||||
|
-1 => Text('socialCreditsLevelPoor').tr(),
|
||||||
|
0 => Text('socialCreditsLevelNormal').tr(),
|
||||||
|
1 => Text('socialCreditsLevelGood').tr(),
|
||||||
|
2 => Text('socialCreditsLevelExcellent').tr(),
|
||||||
|
_ => Text('unknown').tr(),
|
||||||
|
}.fontSize(12),
|
||||||
],
|
],
|
||||||
).padding(top: 2),
|
),
|
||||||
|
),
|
||||||
|
if (data.automatedId != null)
|
||||||
|
Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Symbols.smart_toy,
|
||||||
|
size: 17,
|
||||||
|
fill: 1,
|
||||||
|
).padding(right: 2),
|
||||||
|
Text('accountAutomated').tr().fontSize(12),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (data.profile.timeZone.isNotEmpty && !kIsWeb)
|
||||||
|
() {
|
||||||
|
try {
|
||||||
|
final tzInfo = getTzInfo(data.profile.timeZone);
|
||||||
|
return Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Symbols.alarm,
|
||||||
|
size: 17,
|
||||||
|
fill: 1,
|
||||||
|
).padding(right: 2),
|
||||||
|
Text(
|
||||||
|
tzInfo.$2.formatCustomGlobal('HH:mm'),
|
||||||
|
).fontSize(12),
|
||||||
|
Text(
|
||||||
|
tzInfo.$1.formatOffsetLocal(),
|
||||||
|
).fontSize(12),
|
||||||
|
],
|
||||||
|
).padding(top: 2);
|
||||||
|
} catch (e) {
|
||||||
|
return Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Symbols.alarm,
|
||||||
|
size: 17,
|
||||||
|
fill: 1,
|
||||||
|
).padding(right: 2),
|
||||||
|
Text('timezoneNotFound'.tr()).fontSize(12),
|
||||||
|
],
|
||||||
|
).padding(top: 2);
|
||||||
|
}
|
||||||
|
}(),
|
||||||
if (data.badges.isNotEmpty)
|
if (data.badges.isNotEmpty)
|
||||||
BadgeList(badges: data.badges).padding(top: 12),
|
BadgeList(badges: data.badges).padding(top: 12),
|
||||||
LevelingProgressCard(
|
LevelingProgressCard(
|
||||||
|
@@ -2,7 +2,9 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.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/activity.dart';
|
import 'package:island/models/activity.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:island/widgets/account/event_details_widget.dart';
|
import 'package:island/widgets/account/event_details_widget.dart';
|
||||||
import 'package:table_calendar/table_calendar.dart';
|
import 'package:table_calendar/table_calendar.dart';
|
||||||
@@ -87,24 +89,56 @@ class EventCalendarWidget extends HookConsumerWidget {
|
|||||||
return Center(child: Text(text));
|
return Center(child: Text(text));
|
||||||
},
|
},
|
||||||
markerBuilder: (context, day, events) {
|
markerBuilder: (context, day, events) {
|
||||||
var checkInResult =
|
final checkInResult =
|
||||||
events.whereType<SnCheckInResult>().firstOrNull;
|
events.whereType<SnCheckInResult>().firstOrNull;
|
||||||
|
final statuses = events.whereType<SnAccountStatus>().toList();
|
||||||
|
|
||||||
|
final textColor =
|
||||||
|
isSameDay(selectedDay.value, day)
|
||||||
|
? Colors.white
|
||||||
|
: isSameDay(DateTime.now(), day)
|
||||||
|
? Colors.white
|
||||||
|
: Theme.of(context).colorScheme.onSurface;
|
||||||
|
|
||||||
|
final shadow =
|
||||||
|
isSameDay(selectedDay.value, day) ||
|
||||||
|
isSameDay(DateTime.now(), day)
|
||||||
|
? [
|
||||||
|
Shadow(
|
||||||
|
color: Colors.black.withOpacity(0.5),
|
||||||
|
offset: const Offset(0, 1),
|
||||||
|
blurRadius: 4,
|
||||||
|
),
|
||||||
|
]
|
||||||
|
: null;
|
||||||
|
|
||||||
if (checkInResult != null) {
|
if (checkInResult != null) {
|
||||||
return Positioned(
|
return Positioned(
|
||||||
top: 32,
|
top: 32,
|
||||||
child: Text(
|
child: Row(
|
||||||
'checkInResultT${checkInResult.level}'.tr(),
|
spacing: 2,
|
||||||
style: TextStyle(
|
children: [
|
||||||
fontSize: 9,
|
Text(
|
||||||
color:
|
'checkInResultT${checkInResult.level}'.tr(),
|
||||||
isSameDay(selectedDay.value, day)
|
style: TextStyle(
|
||||||
? Theme.of(context).colorScheme.onPrimaryContainer
|
fontSize: 9,
|
||||||
: isSameDay(DateTime.now(), day)
|
color: textColor,
|
||||||
? Theme.of(
|
shadows: shadow,
|
||||||
context,
|
),
|
||||||
).colorScheme.onSecondaryContainer
|
),
|
||||||
: Theme.of(context).colorScheme.onSurface,
|
if (statuses.isNotEmpty) ...[
|
||||||
),
|
Icon(
|
||||||
|
switch (statuses.first.attitude) {
|
||||||
|
0 => Symbols.sentiment_satisfied,
|
||||||
|
2 => Symbols.sentiment_dissatisfied,
|
||||||
|
_ => Symbols.sentiment_neutral,
|
||||||
|
},
|
||||||
|
size: 12,
|
||||||
|
color: textColor,
|
||||||
|
shadows: shadow,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@@ -2,6 +2,7 @@ import 'package:easy_localization/easy_localization.dart';
|
|||||||
import 'package:flutter/material.dart';
|
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: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';
|
||||||
|
|
||||||
@@ -53,6 +54,33 @@ class EventDetailsWidget extends StatelessWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(top: 8),
|
).padding(top: 8),
|
||||||
|
if (event!.statuses.isNotEmpty) ...[
|
||||||
|
const Gap(16),
|
||||||
|
Text('statusLabel').tr().fontSize(16).bold(),
|
||||||
|
],
|
||||||
|
for (final status in event!.statuses) ...[
|
||||||
|
Row(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
Icon(switch (status.attitude) {
|
||||||
|
0 => Symbols.sentiment_satisfied,
|
||||||
|
2 => Symbols.sentiment_dissatisfied,
|
||||||
|
_ => Symbols.sentiment_neutral,
|
||||||
|
}),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(status.label),
|
||||||
|
Text(
|
||||||
|
'${status.createdAt.formatSystem()} - ${status.clearedAt?.formatSystem() ?? 'present'.tr()}',
|
||||||
|
).fontSize(11).opacity(0.8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(vertical: 8),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (event?.checkInResult == null && (event?.statuses.isEmpty ?? true))
|
if (event?.checkInResult == null && (event?.statuses.isEmpty ?? true))
|
||||||
|
@@ -60,7 +60,9 @@ class AccountStatusCreationWidget extends HookConsumerWidget {
|
|||||||
spacing: 4,
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
Icon(Symbols.keyboard_arrow_up),
|
Icon(Symbols.keyboard_arrow_up),
|
||||||
Text('statusCreateHint').tr(),
|
Expanded(
|
||||||
|
child: Text('statusCreateHint', maxLines: 1).tr(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
).opacity(0.85),
|
).opacity(0.85),
|
||||||
|
@@ -10,6 +10,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/services/file.dart';
|
import 'package:island/services/file.dart';
|
||||||
|
import 'package:island/utils/format.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/content/sheet.dart';
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
@@ -284,6 +285,13 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
Builder(
|
Builder(
|
||||||
key: ValueKey(item.hashCode),
|
key: ValueKey(item.hashCode),
|
||||||
builder: (context) {
|
builder: (context) {
|
||||||
|
final fallbackIcon = switch (item.type) {
|
||||||
|
UniversalFileType.video => Symbols.video_file,
|
||||||
|
UniversalFileType.audio => Symbols.audio_file,
|
||||||
|
UniversalFileType.image => Symbols.image,
|
||||||
|
_ => Symbols.insert_drive_file,
|
||||||
|
};
|
||||||
|
|
||||||
if (item.isOnCloud) {
|
if (item.isOnCloud) {
|
||||||
return CloudFileWidget(item: item.data);
|
return CloudFileWidget(item: item.data);
|
||||||
} else if (item.data is XFile) {
|
} else if (item.data is XFile) {
|
||||||
@@ -309,9 +317,23 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
: Image.file(File(file.path));
|
: Image.file(File(file.path));
|
||||||
default:
|
default:
|
||||||
return Column(
|
return Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Symbols.document_scanner),
|
Icon(fallbackIcon),
|
||||||
|
const Gap(6),
|
||||||
Text(file.name),
|
Text(file.name),
|
||||||
|
FutureBuilder(
|
||||||
|
future: file.length(),
|
||||||
|
builder: (context, snapshot) {
|
||||||
|
if (snapshot.hasData) {
|
||||||
|
final size = snapshot.data as int;
|
||||||
|
return Text(
|
||||||
|
formatFileSize(size),
|
||||||
|
).fontSize(11);
|
||||||
|
}
|
||||||
|
return const SizedBox.shrink();
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -321,7 +343,14 @@ class AttachmentPreview extends HookConsumerWidget {
|
|||||||
return Image.memory(item.data);
|
return Image.memory(item.data);
|
||||||
default:
|
default:
|
||||||
return Column(
|
return Column(
|
||||||
children: [const Icon(Symbols.document_scanner)],
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(fallbackIcon),
|
||||||
|
const Gap(6),
|
||||||
|
Text(
|
||||||
|
formatFileSize(item.data.length),
|
||||||
|
).fontSize(11),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -1,9 +1,12 @@
|
|||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
import 'dart:ui';
|
import 'dart:ui';
|
||||||
|
|
||||||
import 'package:dismissible_page/dismissible_page.dart';
|
import 'package:dismissible_page/dismissible_page.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:file_saver/file_saver.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_blurhash/flutter_blurhash.dart';
|
import 'package:flutter_blurhash/flutter_blurhash.dart';
|
||||||
@@ -14,6 +17,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/utils/format.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/content/sensitive.dart';
|
import 'package:island/widgets/content/sensitive.dart';
|
||||||
@@ -321,7 +325,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
Future<void> saveToGallery() async {
|
Future<void> saveToGallery() async {
|
||||||
try {
|
try {
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
showSnackBar('Saving image to gallery...');
|
showSnackBar('Saving image...');
|
||||||
|
|
||||||
// Get the image URL
|
// Get the image URL
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
@@ -339,25 +343,23 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
filePath,
|
filePath,
|
||||||
queryParameters: {'original': true},
|
queryParameters: {'original': true},
|
||||||
);
|
);
|
||||||
await Gal.putImage(filePath, album: 'Solar Network');
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
|
// Save to gallery
|
||||||
// Show success message
|
await Gal.putImage(filePath, album: 'Solar Network');
|
||||||
showSnackBar('Image saved to gallery');
|
// Show success message
|
||||||
|
showSnackBar('Image saved to gallery');
|
||||||
|
} else {
|
||||||
|
await FileSaver.instance.saveFile(
|
||||||
|
name: item.name.isEmpty ? '${item.id}.$extName' : item.name,
|
||||||
|
file: File(filePath),
|
||||||
|
);
|
||||||
|
showSnackBar('Image saved to $filePath');
|
||||||
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
showErrorAlert(e);
|
showErrorAlert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String formatFileSize(int bytes) {
|
|
||||||
if (bytes <= 0) return '0 B';
|
|
||||||
if (bytes < 1024) return '$bytes B';
|
|
||||||
if (bytes < 1024 * 1024) return '${(bytes / 1024).toStringAsFixed(2)} KB';
|
|
||||||
if (bytes < 1024 * 1024 * 1024) {
|
|
||||||
return '${(bytes / (1024 * 1024)).toStringAsFixed(2)} MB';
|
|
||||||
}
|
|
||||||
return '${(bytes / (1024 * 1024 * 1024)).toStringAsFixed(2)} GB';
|
|
||||||
}
|
|
||||||
|
|
||||||
void showInfoSheet() {
|
void showInfoSheet() {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final exifData = item.fileMeta?['exif'] as Map<String, dynamic>? ?? {};
|
final exifData = item.fileMeta?['exif'] as Map<String, dynamic>? ?? {};
|
||||||
@@ -437,7 +439,24 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
).padding(horizontal: 24, vertical: 16),
|
).padding(horizontal: 24, vertical: 16),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
ListTile(
|
ListTile(
|
||||||
leading: const Icon(Icons.file_present),
|
leading: const Icon(Symbols.tag),
|
||||||
|
title: Text('ID').tr(),
|
||||||
|
subtitle: Text(
|
||||||
|
item.id,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
trailing: IconButton(
|
||||||
|
icon: const Icon(Icons.copy),
|
||||||
|
onPressed: () {
|
||||||
|
Clipboard.setData(ClipboardData(text: item.id));
|
||||||
|
showSnackBar('File ID copied to clipboard');
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Symbols.file_present),
|
||||||
title: Text('Name').tr(),
|
title: Text('Name').tr(),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
item.name,
|
item.name,
|
||||||
@@ -623,6 +642,10 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final shadow = [
|
||||||
|
Shadow(color: Colors.black54, blurRadius: 5.0, offset: Offset(1.0, 1.0)),
|
||||||
|
];
|
||||||
|
|
||||||
return DismissiblePage(
|
return DismissiblePage(
|
||||||
isFullScreen: true,
|
isFullScreen: true,
|
||||||
backgroundColor: Colors.transparent,
|
backgroundColor: Colors.transparent,
|
||||||
@@ -660,22 +683,17 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
if (!kIsWeb)
|
||||||
icon: Icon(
|
IconButton(
|
||||||
Icons.save_alt,
|
icon: Icon(
|
||||||
color: Colors.white,
|
Icons.save_alt,
|
||||||
shadows: [
|
color: Colors.white,
|
||||||
Shadow(
|
shadows: shadow,
|
||||||
color: Colors.black54,
|
),
|
||||||
blurRadius: 5.0,
|
onPressed: () async {
|
||||||
offset: Offset(1.0, 1.0),
|
saveToGallery();
|
||||||
),
|
},
|
||||||
],
|
|
||||||
),
|
),
|
||||||
onPressed: () async {
|
|
||||||
saveToGallery();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showOriginal.value = !showOriginal.value;
|
showOriginal.value = !showOriginal.value;
|
||||||
@@ -683,29 +701,13 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
icon: Icon(
|
icon: Icon(
|
||||||
showOriginal.value ? Symbols.hd : Symbols.sd,
|
showOriginal.value ? Symbols.hd : Symbols.sd,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
shadows: [
|
shadows: shadow,
|
||||||
Shadow(
|
|
||||||
color: Colors.black54,
|
|
||||||
blurRadius: 5.0,
|
|
||||||
offset: Offset(1.0, 1.0),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(
|
icon: Icon(Icons.close, color: Colors.white, shadows: shadow),
|
||||||
Icons.close,
|
|
||||||
color: Colors.white,
|
|
||||||
shadows: [
|
|
||||||
Shadow(
|
|
||||||
color: Colors.black54,
|
|
||||||
blurRadius: 5.0,
|
|
||||||
offset: Offset(1.0, 1.0),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
onPressed: () => Navigator.of(context).pop(),
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -722,26 +724,24 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.info_outline,
|
Icons.info_outline,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
shadows: [
|
shadows: shadow,
|
||||||
Shadow(
|
|
||||||
color: Colors.black54,
|
|
||||||
blurRadius: 5.0,
|
|
||||||
offset: Offset(1.0, 1.0),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
onPressed: showInfoSheet,
|
onPressed: showInfoSheet,
|
||||||
),
|
),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.remove, color: Colors.white),
|
icon: Icon(
|
||||||
|
Icons.remove,
|
||||||
|
color: Colors.white,
|
||||||
|
shadows: shadow,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
photoViewController.scale =
|
photoViewController.scale =
|
||||||
(photoViewController.scale ?? 1) - 0.05;
|
(photoViewController.scale ?? 1) - 0.05;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: Icon(Icons.add, color: Colors.white),
|
icon: Icon(Icons.add, color: Colors.white, shadows: shadow),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
photoViewController.scale =
|
photoViewController.scale =
|
||||||
(photoViewController.scale ?? 1) + 0.05;
|
(photoViewController.scale ?? 1) + 0.05;
|
||||||
@@ -752,13 +752,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
icon: Icon(
|
icon: Icon(
|
||||||
Icons.rotate_left,
|
Icons.rotate_left,
|
||||||
color: Colors.white,
|
color: Colors.white,
|
||||||
shadows: [
|
shadows: shadow,
|
||||||
Shadow(
|
|
||||||
color: Colors.black54,
|
|
||||||
blurRadius: 5.0,
|
|
||||||
offset: Offset(1.0, 1.0),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
rotation.value = (rotation.value - 1) % 4;
|
rotation.value = (rotation.value - 1) % 4;
|
||||||
|
@@ -1,15 +1,19 @@
|
|||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/services/time.dart';
|
import 'package:island/services/time.dart';
|
||||||
|
import 'package:island/utils/format.dart';
|
||||||
import 'package:island/widgets/content/audio.dart';
|
import 'package:island/widgets/content/audio.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
import 'image.dart';
|
import 'image.dart';
|
||||||
import 'video.dart';
|
import 'video.dart';
|
||||||
@@ -60,7 +64,45 @@ class CloudFileWidget extends HookConsumerWidget {
|
|||||||
child: UniversalAudio(uri: uri, filename: item.name),
|
child: UniversalAudio(uri: uri, filename: item.name),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
_ => Text('Unable render for ${item.mimeType}'),
|
_ => Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Symbols.insert_drive_file,
|
||||||
|
size: 48,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Text(
|
||||||
|
item.name,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
formatFileSize(item.size),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 12,
|
||||||
|
color: Theme.of(context).colorScheme.onSurfaceVariant,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
TextButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
launchUrlString(
|
||||||
|
'https://fs.solian.app/files/${item.id}',
|
||||||
|
mode: LaunchMode.externalApplication,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.launch),
|
||||||
|
label: Text('openInBrowser').tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(all: 8),
|
||||||
};
|
};
|
||||||
|
|
||||||
if (heroTag != null) {
|
if (heroTag != null) {
|
||||||
|
@@ -1,6 +1,7 @@
|
|||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@@ -388,26 +389,32 @@ class ComposeLogic {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> pickPhotoMedia(WidgetRef ref, ComposeState state) async {
|
static Future<void> pickPhotoMedia(WidgetRef ref, ComposeState state) async {
|
||||||
final result = await ref
|
final result = await FilePicker.platform.pickFiles(
|
||||||
.watch(imagePickerProvider)
|
type: FileType.image,
|
||||||
.pickMultiImage(requestFullMetadata: true);
|
allowMultiple: true,
|
||||||
if (result.isEmpty) return;
|
allowCompression: false,
|
||||||
|
);
|
||||||
|
if (result == null || result.count == 0) return;
|
||||||
state.attachments.value = [
|
state.attachments.value = [
|
||||||
...state.attachments.value,
|
...state.attachments.value,
|
||||||
...result.map(
|
...result.files.map(
|
||||||
(e) => UniversalFile(data: e, type: UniversalFileType.image),
|
(e) => UniversalFile(data: e, type: UniversalFileType.image),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
static Future<void> pickVideoMedia(WidgetRef ref, ComposeState state) async {
|
static Future<void> pickVideoMedia(WidgetRef ref, ComposeState state) async {
|
||||||
final result = await ref
|
final result = await FilePicker.platform.pickFiles(
|
||||||
.watch(imagePickerProvider)
|
type: FileType.video,
|
||||||
.pickVideo(source: ImageSource.gallery);
|
allowMultiple: true,
|
||||||
if (result == null) return;
|
allowCompression: false,
|
||||||
|
);
|
||||||
|
if (result == null || result.count == 0) return;
|
||||||
state.attachments.value = [
|
state.attachments.value = [
|
||||||
...state.attachments.value,
|
...state.attachments.value,
|
||||||
UniversalFile(data: result, type: UniversalFileType.video),
|
...result.files.map(
|
||||||
|
(e) => UniversalFile(data: e, type: UniversalFileType.video),
|
||||||
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -1,3 +1,4 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
@@ -105,7 +106,7 @@ class PostFeaturedList extends HookConsumerWidget {
|
|||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
const Icon(Symbols.highlight),
|
const Icon(Symbols.highlight),
|
||||||
Text('Highlight Posts'),
|
const Text('highlightPost').tr(),
|
||||||
Spacer(),
|
Spacer(),
|
||||||
IconButton(
|
IconButton(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
|
@@ -18,6 +18,7 @@ import 'package:island/screens/posts/compose.dart';
|
|||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
import 'package:island/widgets/post/post_item_screenshot.dart';
|
import 'package:island/widgets/post/post_item_screenshot.dart';
|
||||||
|
import 'package:island/widgets/post/post_pin_sheet.dart';
|
||||||
import 'package:island/widgets/post/post_shared.dart';
|
import 'package:island/widgets/post/post_shared.dart';
|
||||||
import 'package:island/widgets/safety/abuse_report_helper.dart';
|
import 'package:island/widgets/safety/abuse_report_helper.dart';
|
||||||
import 'package:island/widgets/share/share_sheet.dart';
|
import 'package:island/widgets/share/share_sheet.dart';
|
||||||
@@ -202,6 +203,45 @@ class PostActionableItem extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (isAuthor && item.pinMode == null)
|
||||||
|
MenuAction(
|
||||||
|
title: 'pinPost'.tr(),
|
||||||
|
image: MenuImage.icon(Symbols.keep),
|
||||||
|
callback: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder: (context) => PostPinSheet(post: item),
|
||||||
|
).then((value) {
|
||||||
|
if (value is int) {
|
||||||
|
onUpdate?.call(item.copyWith(pinMode: value));
|
||||||
|
}
|
||||||
|
});
|
||||||
|
},
|
||||||
|
)
|
||||||
|
else if (isAuthor && item.pinMode != null)
|
||||||
|
MenuAction(
|
||||||
|
title: 'unpinPost'.tr(),
|
||||||
|
image: MenuImage.icon(Symbols.keep_off),
|
||||||
|
callback: () {
|
||||||
|
showConfirmAlert('unpinPostHint'.tr(), 'unpinPost'.tr()).then(
|
||||||
|
(confirm) async {
|
||||||
|
if (confirm) {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
try {
|
||||||
|
if (context.mounted) showLoadingModal(context);
|
||||||
|
await client.delete('/sphere/posts/${item.id}/pin');
|
||||||
|
onUpdate?.call(item.copyWith(pinMode: null));
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) hideLoadingModal(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
MenuSeparator(),
|
MenuSeparator(),
|
||||||
MenuAction(
|
MenuAction(
|
||||||
title: 'share'.tr(),
|
title: 'share'.tr(),
|
||||||
@@ -300,7 +340,14 @@ class PostItem extends HookConsumerWidget {
|
|||||||
final delta = isRemoving ? -1 : 1;
|
final delta = isRemoving ? -1 : 1;
|
||||||
final reactionsCount = Map<String, int>.from(item.reactionsCount);
|
final reactionsCount = Map<String, int>.from(item.reactionsCount);
|
||||||
reactionsCount[symbol] = (reactionsCount[symbol] ?? 0) + delta;
|
reactionsCount[symbol] = (reactionsCount[symbol] ?? 0) + delta;
|
||||||
onUpdate?.call(item.copyWith(reactionsCount: reactionsCount));
|
final reactionsMade = Map<String, bool>.from(item.reactionsMade);
|
||||||
|
reactionsMade[symbol] = delta == 1 ? true : false;
|
||||||
|
onUpdate?.call(
|
||||||
|
item.copyWith(
|
||||||
|
reactionsCount: reactionsCount,
|
||||||
|
reactionsMade: reactionsMade,
|
||||||
|
),
|
||||||
|
);
|
||||||
HapticFeedback.heavyImpact();
|
HapticFeedback.heavyImpact();
|
||||||
});
|
});
|
||||||
reacting.value = false;
|
reacting.value = false;
|
||||||
|
@@ -10,6 +10,7 @@ import 'package:island/widgets/alert.dart';
|
|||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.dart';
|
||||||
import 'package:island/widgets/post/post_shared.dart';
|
import 'package:island/widgets/post/post_shared.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:super_context_menu/super_context_menu.dart';
|
import 'package:super_context_menu/super_context_menu.dart';
|
||||||
|
|
||||||
class PostItemCreator extends HookConsumerWidget {
|
class PostItemCreator extends HookConsumerWidget {
|
||||||
@@ -33,7 +34,7 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final renderingPadding =
|
final renderingPadding =
|
||||||
padding ?? const EdgeInsets.symmetric(horizontal: 16, vertical: 16);
|
padding ?? const EdgeInsets.symmetric(horizontal: 8, vertical: 8);
|
||||||
|
|
||||||
return ContextMenuWidget(
|
return ContextMenuWidget(
|
||||||
menuProvider: (_) {
|
menuProvider: (_) {
|
||||||
@@ -97,18 +98,22 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
context.goNamed('postDetail', pathParameters: {'id': item.id});
|
context.goNamed('postDetail', pathParameters: {'id': item.id});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: Padding(
|
child: Column(
|
||||||
padding: renderingPadding,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
Gap(renderingPadding.vertical),
|
||||||
children: [
|
PostHeader(item: item, renderingPadding: renderingPadding),
|
||||||
PostHeader(item: item),
|
PostBody(item: item, renderingPadding: renderingPadding),
|
||||||
PostBody(item: item),
|
ReferencedPostWidget(
|
||||||
ReferencedPostWidget(item: item),
|
item: item,
|
||||||
const Gap(16),
|
renderingPadding: renderingPadding,
|
||||||
_buildAnalyticsSection(context),
|
),
|
||||||
],
|
const Gap(16),
|
||||||
),
|
_buildAnalyticsSection(
|
||||||
|
context,
|
||||||
|
).padding(horizontal: renderingPadding.horizontal),
|
||||||
|
Gap(renderingPadding.vertical),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -21,6 +21,7 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
}) {
|
}) {
|
||||||
return fetch(cursor: null);
|
return fetch(cursor: null);
|
||||||
@@ -40,6 +41,7 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
if (tags != null) 'tags': tags,
|
if (tags != null) 'tags': tags,
|
||||||
if (categories != null) 'categories': categories,
|
if (categories != null) 'categories': categories,
|
||||||
if (shuffle) 'shuffle': true,
|
if (shuffle) 'shuffle': true,
|
||||||
|
if (pinned != null) 'pinned': pinned,
|
||||||
};
|
};
|
||||||
|
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
@@ -77,6 +79,7 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
final List<String>? categories;
|
final List<String>? categories;
|
||||||
final List<String>? tags;
|
final List<String>? tags;
|
||||||
final bool shuffle;
|
final bool shuffle;
|
||||||
|
final bool? pinned;
|
||||||
final PostItemType itemType;
|
final PostItemType itemType;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
final EdgeInsets? padding;
|
final EdgeInsets? padding;
|
||||||
@@ -93,6 +96,7 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
this.categories,
|
this.categories,
|
||||||
this.tags,
|
this.tags,
|
||||||
this.shuffle = false,
|
this.shuffle = false,
|
||||||
|
this.pinned,
|
||||||
this.itemType = PostItemType.regular,
|
this.itemType = PostItemType.regular,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.padding,
|
this.padding,
|
||||||
@@ -104,33 +108,19 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final provider = postListNotifierProvider(
|
||||||
|
pubName: pubName,
|
||||||
|
realm: realm,
|
||||||
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
|
shuffle: shuffle,
|
||||||
|
pinned: pinned,
|
||||||
|
);
|
||||||
return PagingHelperSliverView(
|
return PagingHelperSliverView(
|
||||||
provider: postListNotifierProvider(
|
provider: provider,
|
||||||
pubName: pubName,
|
futureRefreshable: provider.future,
|
||||||
realm: realm,
|
notifierRefreshable: provider.notifier,
|
||||||
type: type,
|
|
||||||
categories: categories,
|
|
||||||
tags: tags,
|
|
||||||
shuffle: shuffle,
|
|
||||||
),
|
|
||||||
futureRefreshable:
|
|
||||||
postListNotifierProvider(
|
|
||||||
pubName: pubName,
|
|
||||||
realm: realm,
|
|
||||||
type: type,
|
|
||||||
categories: categories,
|
|
||||||
tags: tags,
|
|
||||||
shuffle: shuffle,
|
|
||||||
).future,
|
|
||||||
notifierRefreshable:
|
|
||||||
postListNotifierProvider(
|
|
||||||
pubName: pubName,
|
|
||||||
realm: realm,
|
|
||||||
type: type,
|
|
||||||
categories: categories,
|
|
||||||
tags: tags,
|
|
||||||
shuffle: shuffle,
|
|
||||||
).notifier,
|
|
||||||
contentBuilder:
|
contentBuilder:
|
||||||
(data, widgetCount, endItemView) => SliverList.builder(
|
(data, widgetCount, endItemView) => SliverList.builder(
|
||||||
itemCount: widgetCount,
|
itemCount: widgetCount,
|
||||||
|
@@ -6,7 +6,7 @@ part of 'post_list.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$postListNotifierHash() => r'faa0b939fae56367ff120ce63d9deb17b1995c9c';
|
String _$postListNotifierHash() => r'3c0a8154ded4bcd8f5456f7a4ea2e542f57efa85';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -36,6 +36,7 @@ abstract class _$PostListNotifier
|
|||||||
late final int? type;
|
late final int? type;
|
||||||
late final List<String>? categories;
|
late final List<String>? categories;
|
||||||
late final List<String>? tags;
|
late final List<String>? tags;
|
||||||
|
late final bool? pinned;
|
||||||
late final bool shuffle;
|
late final bool shuffle;
|
||||||
|
|
||||||
FutureOr<CursorPagingData<SnPost>> build({
|
FutureOr<CursorPagingData<SnPost>> build({
|
||||||
@@ -44,6 +45,7 @@ abstract class _$PostListNotifier
|
|||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -65,6 +67,7 @@ class PostListNotifierFamily
|
|||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
}) {
|
}) {
|
||||||
return PostListNotifierProvider(
|
return PostListNotifierProvider(
|
||||||
@@ -73,6 +76,7 @@ class PostListNotifierFamily
|
|||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -87,6 +91,7 @@ class PostListNotifierFamily
|
|||||||
type: provider.type,
|
type: provider.type,
|
||||||
categories: provider.categories,
|
categories: provider.categories,
|
||||||
tags: provider.tags,
|
tags: provider.tags,
|
||||||
|
pinned: provider.pinned,
|
||||||
shuffle: provider.shuffle,
|
shuffle: provider.shuffle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -120,6 +125,7 @@ class PostListNotifierProvider
|
|||||||
int? type,
|
int? type,
|
||||||
List<String>? categories,
|
List<String>? categories,
|
||||||
List<String>? tags,
|
List<String>? tags,
|
||||||
|
bool? pinned,
|
||||||
bool shuffle = false,
|
bool shuffle = false,
|
||||||
}) : this._internal(
|
}) : this._internal(
|
||||||
() =>
|
() =>
|
||||||
@@ -129,6 +135,7 @@ class PostListNotifierProvider
|
|||||||
..type = type
|
..type = type
|
||||||
..categories = categories
|
..categories = categories
|
||||||
..tags = tags
|
..tags = tags
|
||||||
|
..pinned = pinned
|
||||||
..shuffle = shuffle,
|
..shuffle = shuffle,
|
||||||
from: postListNotifierProvider,
|
from: postListNotifierProvider,
|
||||||
name: r'postListNotifierProvider',
|
name: r'postListNotifierProvider',
|
||||||
@@ -144,6 +151,7 @@ class PostListNotifierProvider
|
|||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -159,6 +167,7 @@ class PostListNotifierProvider
|
|||||||
required this.type,
|
required this.type,
|
||||||
required this.categories,
|
required this.categories,
|
||||||
required this.tags,
|
required this.tags,
|
||||||
|
required this.pinned,
|
||||||
required this.shuffle,
|
required this.shuffle,
|
||||||
}) : super.internal();
|
}) : super.internal();
|
||||||
|
|
||||||
@@ -167,6 +176,7 @@ class PostListNotifierProvider
|
|||||||
final int? type;
|
final int? type;
|
||||||
final List<String>? categories;
|
final List<String>? categories;
|
||||||
final List<String>? tags;
|
final List<String>? tags;
|
||||||
|
final bool? pinned;
|
||||||
final bool shuffle;
|
final bool shuffle;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -179,6 +189,7 @@ class PostListNotifierProvider
|
|||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -195,6 +206,7 @@ class PostListNotifierProvider
|
|||||||
..type = type
|
..type = type
|
||||||
..categories = categories
|
..categories = categories
|
||||||
..tags = tags
|
..tags = tags
|
||||||
|
..pinned = pinned
|
||||||
..shuffle = shuffle,
|
..shuffle = shuffle,
|
||||||
from: from,
|
from: from,
|
||||||
name: null,
|
name: null,
|
||||||
@@ -206,6 +218,7 @@ class PostListNotifierProvider
|
|||||||
type: type,
|
type: type,
|
||||||
categories: categories,
|
categories: categories,
|
||||||
tags: tags,
|
tags: tags,
|
||||||
|
pinned: pinned,
|
||||||
shuffle: shuffle,
|
shuffle: shuffle,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -228,6 +241,7 @@ class PostListNotifierProvider
|
|||||||
other.type == type &&
|
other.type == type &&
|
||||||
other.categories == categories &&
|
other.categories == categories &&
|
||||||
other.tags == tags &&
|
other.tags == tags &&
|
||||||
|
other.pinned == pinned &&
|
||||||
other.shuffle == shuffle;
|
other.shuffle == shuffle;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -239,6 +253,7 @@ class PostListNotifierProvider
|
|||||||
hash = _SystemHash.combine(hash, type.hashCode);
|
hash = _SystemHash.combine(hash, type.hashCode);
|
||||||
hash = _SystemHash.combine(hash, categories.hashCode);
|
hash = _SystemHash.combine(hash, categories.hashCode);
|
||||||
hash = _SystemHash.combine(hash, tags.hashCode);
|
hash = _SystemHash.combine(hash, tags.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, pinned.hashCode);
|
||||||
hash = _SystemHash.combine(hash, shuffle.hashCode);
|
hash = _SystemHash.combine(hash, shuffle.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
@@ -264,6 +279,9 @@ mixin PostListNotifierRef
|
|||||||
/// The parameter `tags` of this provider.
|
/// The parameter `tags` of this provider.
|
||||||
List<String>? get tags;
|
List<String>? get tags;
|
||||||
|
|
||||||
|
/// The parameter `pinned` of this provider.
|
||||||
|
bool? get pinned;
|
||||||
|
|
||||||
/// The parameter `shuffle` of this provider.
|
/// The parameter `shuffle` of this provider.
|
||||||
bool get shuffle;
|
bool get shuffle;
|
||||||
}
|
}
|
||||||
@@ -289,6 +307,8 @@ class _PostListNotifierProviderElement
|
|||||||
@override
|
@override
|
||||||
List<String>? get tags => (origin as PostListNotifierProvider).tags;
|
List<String>? get tags => (origin as PostListNotifierProvider).tags;
|
||||||
@override
|
@override
|
||||||
|
bool? get pinned => (origin as PostListNotifierProvider).pinned;
|
||||||
|
@override
|
||||||
bool get shuffle => (origin as PostListNotifierProvider).shuffle;
|
bool get shuffle => (origin as PostListNotifierProvider).shuffle;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
124
lib/widgets/post/post_pin_sheet.dart
Normal file
124
lib/widgets/post/post_pin_sheet.dart
Normal file
@@ -0,0 +1,124 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/post.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/widgets/alert.dart';
|
||||||
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
class PostPinSheet extends HookConsumerWidget {
|
||||||
|
final SnPost post;
|
||||||
|
const PostPinSheet({super.key, required this.post});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final mode = useState(0);
|
||||||
|
|
||||||
|
Future<void> pinPost() async {
|
||||||
|
try {
|
||||||
|
showLoadingModal(context);
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
await client.post(
|
||||||
|
'/sphere/posts/${post.id}/pin',
|
||||||
|
data: {'mode': mode.value},
|
||||||
|
);
|
||||||
|
|
||||||
|
if (context.mounted) Navigator.of(context).pop(mode.value);
|
||||||
|
} catch (e) {
|
||||||
|
showErrorAlert(e);
|
||||||
|
} finally {
|
||||||
|
if (context.mounted) hideLoadingModal(context);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return SheetScaffold(
|
||||||
|
titleText: 'pinPost'.tr(),
|
||||||
|
heightFactor: 0.6,
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
// Publisher page pin option (always available)
|
||||||
|
ListTile(
|
||||||
|
leading: Radio<int>(
|
||||||
|
value: 0,
|
||||||
|
groupValue: mode.value,
|
||||||
|
onChanged: (value) {
|
||||||
|
mode.value = value!;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: Text('publisherPage'.tr()),
|
||||||
|
subtitle: Text('pinPostPublisherHint'.tr()),
|
||||||
|
onTap: () {
|
||||||
|
mode.value = 0;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
|
||||||
|
// Realm page pin option (show always, but disabled when not available)
|
||||||
|
ListTile(
|
||||||
|
leading: Radio<int>(
|
||||||
|
value: 1,
|
||||||
|
groupValue: mode.value,
|
||||||
|
onChanged:
|
||||||
|
post.realmId != null && post.realmId!.isNotEmpty
|
||||||
|
? (value) {
|
||||||
|
mode.value = value!;
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
title: Text('realmPage'.tr()),
|
||||||
|
subtitle:
|
||||||
|
post.realmId != null && post.realmId!.isNotEmpty
|
||||||
|
? Text('pinPostRealmHint'.tr())
|
||||||
|
: Text('pinPostRealmDisabledHint'.tr()),
|
||||||
|
onTap:
|
||||||
|
post.realmId != null && post.realmId!.isNotEmpty
|
||||||
|
? () {
|
||||||
|
mode.value = 1;
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
enabled: post.realmId != null && post.realmId!.isNotEmpty,
|
||||||
|
),
|
||||||
|
|
||||||
|
// Reply page pin option (show always, but disabled when not available)
|
||||||
|
// Disabled for now because im being lazy
|
||||||
|
// ListTile(
|
||||||
|
// leading: Radio<int>(
|
||||||
|
// value: 2,
|
||||||
|
// groupValue: mode.value,
|
||||||
|
// onChanged:
|
||||||
|
// post.repliedPostId != null && post.repliedPostId!.isNotEmpty
|
||||||
|
// ? (value) {
|
||||||
|
// mode.value = value!;
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
// ),
|
||||||
|
// title: Text('replyPage'.tr()),
|
||||||
|
// subtitle:
|
||||||
|
// post.repliedPostId != null && post.repliedPostId!.isNotEmpty
|
||||||
|
// ? Text('pinPostReplyHint'.tr())
|
||||||
|
// : Text('pinPostReplyDisabledHint'.tr()),
|
||||||
|
// onTap:
|
||||||
|
// post.repliedPostId != null && post.repliedPostId!.isNotEmpty
|
||||||
|
// ? () {
|
||||||
|
// mode.value = 2;
|
||||||
|
// }
|
||||||
|
// : null,
|
||||||
|
// enabled:
|
||||||
|
// post.repliedPostId != null && post.repliedPostId!.isNotEmpty,
|
||||||
|
// ),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Pin button
|
||||||
|
FilledButton.icon(
|
||||||
|
onPressed: pinPost,
|
||||||
|
icon: const Icon(Symbols.keep),
|
||||||
|
label: Text('pin'.tr()),
|
||||||
|
).padding(horizontal: 24),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -545,107 +545,119 @@ class PostHeader extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Row(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
spacing: 12,
|
|
||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
if (item.pinMode != null)
|
||||||
onTap:
|
Row(
|
||||||
isInteractive
|
spacing: 4,
|
||||||
? () {
|
|
||||||
context.pushNamed(
|
|
||||||
'publisherProfile',
|
|
||||||
pathParameters: {'name': item.publisher.name},
|
|
||||||
);
|
|
||||||
}
|
|
||||||
: null,
|
|
||||||
child: ProfilePictureWidget(
|
|
||||||
file: item.publisher.picture,
|
|
||||||
radius: 16,
|
|
||||||
borderRadius: item.publisher.type == 0 ? null : 6,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
children: [
|
||||||
Row(
|
const Icon(Symbols.keep, size: 15, fill: 1),
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
Text('pinnedPost').tr().fontSize(13),
|
||||||
spacing: 4,
|
],
|
||||||
|
).opacity(0.8).padding(horizontal: 8, bottom: 4),
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
spacing: 12,
|
||||||
|
children: [
|
||||||
|
GestureDetector(
|
||||||
|
onTap:
|
||||||
|
isInteractive
|
||||||
|
? () {
|
||||||
|
context.pushNamed(
|
||||||
|
'publisherProfile',
|
||||||
|
pathParameters: {'name': item.publisher.name},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
child: ProfilePictureWidget(
|
||||||
|
file: item.publisher.picture,
|
||||||
|
radius: 16,
|
||||||
|
borderRadius: item.publisher.type == 0 ? null : 6,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(item.publisher.nick).bold(),
|
Row(
|
||||||
if (item.publisher.verification != null)
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
VerificationMark(mark: item.publisher.verification!),
|
spacing: 4,
|
||||||
if (item.realm == null)
|
children: [
|
||||||
Text('@${item.publisher.name}').fontSize(11)
|
Text(item.publisher.nick).bold(),
|
||||||
else
|
if (item.publisher.verification != null)
|
||||||
...([
|
VerificationMark(mark: item.publisher.verification!),
|
||||||
const Icon(Symbols.arrow_right, size: 14),
|
if (item.realm == null)
|
||||||
Flexible(
|
Text('@${item.publisher.name}').fontSize(11)
|
||||||
child: InkWell(
|
else
|
||||||
child: Row(
|
...([
|
||||||
mainAxisSize: MainAxisSize.min,
|
const Icon(Symbols.arrow_right, size: 14),
|
||||||
spacing: 5,
|
Flexible(
|
||||||
children: [
|
child: InkWell(
|
||||||
Flexible(
|
child: Row(
|
||||||
child: Text(
|
mainAxisSize: MainAxisSize.min,
|
||||||
item.realm!.name,
|
spacing: 5,
|
||||||
maxLines: 1,
|
children: [
|
||||||
overflow: TextOverflow.ellipsis,
|
Flexible(
|
||||||
),
|
child: Text(
|
||||||
),
|
item.realm!.name,
|
||||||
ProfilePictureWidget(
|
maxLines: 1,
|
||||||
file: item.realm!.picture,
|
overflow: TextOverflow.ellipsis,
|
||||||
fallbackIcon: Symbols.group,
|
),
|
||||||
radius: 9,
|
),
|
||||||
|
ProfilePictureWidget(
|
||||||
|
file: item.realm!.picture,
|
||||||
|
fallbackIcon: Symbols.group,
|
||||||
|
radius: 9,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'realmDetail',
|
||||||
|
pathParameters: {'slug': item.realm!.slug},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Row(
|
||||||
|
spacing: 6,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
!isFullPost && isRelativeTime
|
||||||
|
? (item.publishedAt ?? item.createdAt)!
|
||||||
|
.formatRelative(context)
|
||||||
|
: (item.publishedAt ?? item.createdAt)!
|
||||||
|
.formatSystem(),
|
||||||
|
).fontSize(10),
|
||||||
|
if (item.editedAt != null)
|
||||||
|
Text(
|
||||||
|
'editedAt'.tr(
|
||||||
|
args: [
|
||||||
|
!isFullPost && isRelativeTime
|
||||||
|
? item.editedAt!.formatRelative(context)
|
||||||
|
: item.editedAt!.formatSystem(),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
).fontSize(10),
|
||||||
GoRouter.of(context).pushNamed(
|
if (item.visibility != 0)
|
||||||
'realmDetail',
|
Text(
|
||||||
pathParameters: {'slug': item.realm!.slug},
|
PostVisibilityHelpers.getVisibilityText(
|
||||||
);
|
item.visibility,
|
||||||
},
|
).tr(),
|
||||||
),
|
).fontSize(10),
|
||||||
),
|
],
|
||||||
]),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Row(
|
),
|
||||||
spacing: 6,
|
if (trailing != null) trailing!,
|
||||||
crossAxisAlignment: CrossAxisAlignment.end,
|
],
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
!isFullPost && isRelativeTime
|
|
||||||
? (item.publishedAt ?? item.createdAt)!.formatRelative(
|
|
||||||
context,
|
|
||||||
)
|
|
||||||
: (item.publishedAt ?? item.createdAt)!.formatSystem(),
|
|
||||||
).fontSize(10),
|
|
||||||
if (item.editedAt != null)
|
|
||||||
Text(
|
|
||||||
'editedAt'.tr(
|
|
||||||
args: [
|
|
||||||
!isFullPost && isRelativeTime
|
|
||||||
? item.editedAt!.formatRelative(context)
|
|
||||||
: item.editedAt!.formatSystem(),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
).fontSize(10),
|
|
||||||
if (item.visibility != 0)
|
|
||||||
Text(
|
|
||||||
PostVisibilityHelpers.getVisibilityText(
|
|
||||||
item.visibility,
|
|
||||||
).tr(),
|
|
||||||
).fontSize(10),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
if (trailing != null) trailing!,
|
|
||||||
],
|
],
|
||||||
).padding(horizontal: renderingPadding.horizontal, bottom: 4);
|
).padding(horizontal: renderingPadding.horizontal, bottom: 4);
|
||||||
}
|
}
|
||||||
@@ -750,7 +762,9 @@ class PostBody extends ConsumerWidget {
|
|||||||
).padding(bottom: 4),
|
).padding(bottom: 4),
|
||||||
MarkdownTextContent(
|
MarkdownTextContent(
|
||||||
content:
|
content:
|
||||||
item.isTruncated ? '${item.content!}...' : item.content!,
|
item.isTruncated
|
||||||
|
? '${item.content!}...'
|
||||||
|
: item.content ?? '',
|
||||||
isSelectable: isTextSelectable,
|
isSelectable: isTextSelectable,
|
||||||
),
|
),
|
||||||
if (translationSection != null) translationSection!,
|
if (translationSection != null) translationSection!,
|
||||||
|
@@ -25,7 +25,7 @@ class PostShuffleScreen extends HookConsumerWidget {
|
|||||||
return cardSwiperController.dispose;
|
return cardSwiperController.dispose;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
const kBottomControlHeight = 64.0;
|
const kBottomControlHeight = 80.0;
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('postShuffle').tr()),
|
appBar: AppBar(title: const Text('postShuffle').tr()),
|
||||||
|
@@ -7,6 +7,7 @@
|
|||||||
#include "generated_plugin_registrant.h"
|
#include "generated_plugin_registrant.h"
|
||||||
|
|
||||||
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
|
#include <bitsdojo_window_linux/bitsdojo_window_plugin.h>
|
||||||
|
#include <file_saver/file_saver_plugin.h>
|
||||||
#include <file_selector_linux/file_selector_plugin.h>
|
#include <file_selector_linux/file_selector_plugin.h>
|
||||||
#include <flutter_platform_alert/flutter_platform_alert_plugin.h>
|
#include <flutter_platform_alert/flutter_platform_alert_plugin.h>
|
||||||
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
#include <flutter_secure_storage_linux/flutter_secure_storage_linux_plugin.h>
|
||||||
@@ -28,6 +29,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar =
|
g_autoptr(FlPluginRegistrar) bitsdojo_window_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "BitsdojoWindowPlugin");
|
||||||
bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar);
|
bitsdojo_window_plugin_register_with_registrar(bitsdojo_window_linux_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) file_saver_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSaverPlugin");
|
||||||
|
file_saver_plugin_register_with_registrar(file_saver_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
g_autoptr(FlPluginRegistrar) file_selector_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "FileSelectorPlugin");
|
||||||
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
file_selector_plugin_register_with_registrar(file_selector_linux_registrar);
|
||||||
|
@@ -4,6 +4,7 @@
|
|||||||
|
|
||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
bitsdojo_window_linux
|
bitsdojo_window_linux
|
||||||
|
file_saver
|
||||||
file_selector_linux
|
file_selector_linux
|
||||||
flutter_platform_alert
|
flutter_platform_alert
|
||||||
flutter_secure_storage_linux
|
flutter_secure_storage_linux
|
||||||
|
@@ -9,6 +9,7 @@ import bitsdojo_window_macos
|
|||||||
import connectivity_plus
|
import connectivity_plus
|
||||||
import device_info_plus
|
import device_info_plus
|
||||||
import file_picker
|
import file_picker
|
||||||
|
import file_saver
|
||||||
import file_selector_macos
|
import file_selector_macos
|
||||||
import firebase_analytics
|
import firebase_analytics
|
||||||
import firebase_core
|
import firebase_core
|
||||||
@@ -45,6 +46,7 @@ func RegisterGeneratedPlugins(registry: FlutterPluginRegistry) {
|
|||||||
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
ConnectivityPlusPlugin.register(with: registry.registrar(forPlugin: "ConnectivityPlusPlugin"))
|
||||||
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
DeviceInfoPlusMacosPlugin.register(with: registry.registrar(forPlugin: "DeviceInfoPlusMacosPlugin"))
|
||||||
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
FilePickerPlugin.register(with: registry.registrar(forPlugin: "FilePickerPlugin"))
|
||||||
|
FileSaverPlugin.register(with: registry.registrar(forPlugin: "FileSaverPlugin"))
|
||||||
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
FileSelectorPlugin.register(with: registry.registrar(forPlugin: "FileSelectorPlugin"))
|
||||||
FirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FirebaseAnalyticsPlugin"))
|
FirebaseAnalyticsPlugin.register(with: registry.registrar(forPlugin: "FirebaseAnalyticsPlugin"))
|
||||||
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
FLTFirebaseCorePlugin.register(with: registry.registrar(forPlugin: "FLTFirebaseCorePlugin"))
|
||||||
|
@@ -9,87 +9,89 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- file_picker (0.0.1):
|
- file_picker (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
|
- file_saver (0.0.1):
|
||||||
|
- FlutterMacOS
|
||||||
- file_selector_macos (0.0.1):
|
- file_selector_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- Firebase/CoreOnly (12.0.0):
|
- Firebase/CoreOnly (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- Firebase/Crashlytics (12.0.0):
|
- Firebase/Crashlytics (12.2.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseCrashlytics (~> 12.0.0)
|
- FirebaseCrashlytics (~> 12.2.0)
|
||||||
- Firebase/Messaging (12.0.0):
|
- Firebase/Messaging (12.2.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 12.0.0)
|
- FirebaseMessaging (~> 12.2.0)
|
||||||
- firebase_analytics (12.0.0):
|
- firebase_analytics (12.0.1):
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FirebaseAnalytics (= 12.0.0)
|
- FirebaseAnalytics (= 12.2.0)
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_core (4.0.0):
|
- firebase_core (4.1.0):
|
||||||
- Firebase/CoreOnly (~> 12.0.0)
|
- Firebase/CoreOnly (~> 12.2.0)
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_crashlytics (5.0.0):
|
- firebase_crashlytics (5.0.1):
|
||||||
- Firebase/CoreOnly (~> 12.0.0)
|
- Firebase/CoreOnly (~> 12.2.0)
|
||||||
- Firebase/Crashlytics (~> 12.0.0)
|
- Firebase/Crashlytics (~> 12.2.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_messaging (16.0.0):
|
- firebase_messaging (16.0.1):
|
||||||
- Firebase/CoreOnly (~> 12.0.0)
|
- Firebase/CoreOnly (~> 12.2.0)
|
||||||
- Firebase/Messaging (~> 12.0.0)
|
- Firebase/Messaging (~> 12.2.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- FirebaseAnalytics (12.0.0):
|
- FirebaseAnalytics (12.2.0):
|
||||||
- FirebaseAnalytics/Default (= 12.0.0)
|
- FirebaseAnalytics/Default (= 12.2.0)
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseAnalytics/Default (12.0.0):
|
- FirebaseAnalytics/Default (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleAppMeasurement/Default (= 12.0.0)
|
- GoogleAppMeasurement/Default (= 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseCore (12.0.0):
|
- FirebaseCore (12.2.0):
|
||||||
- FirebaseCoreInternal (~> 12.0.0)
|
- FirebaseCoreInternal (~> 12.2.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- FirebaseCoreExtension (12.0.0):
|
- FirebaseCoreExtension (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseCoreInternal (12.0.0):
|
- FirebaseCoreInternal (12.2.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- FirebaseCrashlytics (12.0.0):
|
- FirebaseCrashlytics (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- FirebaseRemoteConfigInterop (~> 12.0.0)
|
- FirebaseRemoteConfigInterop (~> 12.2.0)
|
||||||
- FirebaseSessions (~> 12.0.0)
|
- FirebaseSessions (~> 12.2.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseInstallations (12.0.0):
|
- FirebaseInstallations (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (12.0.0):
|
- FirebaseMessaging (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Reachability (~> 8.1)
|
- GoogleUtilities/Reachability (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseRemoteConfigInterop (12.0.0)
|
- FirebaseRemoteConfigInterop (12.2.0)
|
||||||
- FirebaseSessions (12.0.0):
|
- FirebaseSessions (12.2.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.2.0)
|
||||||
- FirebaseCoreExtension (~> 12.0.0)
|
- FirebaseCoreExtension (~> 12.2.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.2.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
@@ -107,30 +109,30 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- flutter_webrtc (1.0.0):
|
- flutter_webrtc (1.1.0):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (= 137.7151.02)
|
- WebRTC-SDK (= 137.7151.03)
|
||||||
- FlutterMacOS (1.0.0)
|
- FlutterMacOS (1.0.0)
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- GoogleAppMeasurement/Core (12.0.0):
|
- GoogleAppMeasurement/Core (12.2.0):
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/Default (12.0.0):
|
- GoogleAppMeasurement/Default (12.2.0):
|
||||||
- GoogleAdsOnDeviceConversion (= 2.1.0)
|
- GoogleAdsOnDeviceConversion (= 2.3.0)
|
||||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||||
- GoogleAppMeasurement/IdentitySupport (= 12.0.0)
|
- GoogleAppMeasurement/IdentitySupport (= 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/IdentitySupport (12.0.0):
|
- GoogleAppMeasurement/IdentitySupport (12.2.0):
|
||||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
@@ -171,7 +173,7 @@ PODS:
|
|||||||
- livekit_client (2.5.0):
|
- livekit_client (2.5.0):
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (= 137.7151.02)
|
- WebRTC-SDK (= 137.7151.03)
|
||||||
- local_auth_darwin (0.0.1):
|
- local_auth_darwin (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -241,7 +243,7 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (137.7151.02)
|
- WebRTC-SDK (137.7151.03)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- bitsdojo_window_macos (from `Flutter/ephemeral/.symlinks/plugins/bitsdojo_window_macos/macos`)
|
- bitsdojo_window_macos (from `Flutter/ephemeral/.symlinks/plugins/bitsdojo_window_macos/macos`)
|
||||||
@@ -249,6 +251,7 @@ DEPENDENCIES:
|
|||||||
- croppy (from `Flutter/ephemeral/.symlinks/plugins/croppy/macos`)
|
- croppy (from `Flutter/ephemeral/.symlinks/plugins/croppy/macos`)
|
||||||
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
- device_info_plus (from `Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos`)
|
||||||
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
- file_picker (from `Flutter/ephemeral/.symlinks/plugins/file_picker/macos`)
|
||||||
|
- file_saver (from `Flutter/ephemeral/.symlinks/plugins/file_saver/macos`)
|
||||||
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
|
- file_selector_macos (from `Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos`)
|
||||||
- firebase_analytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos`)
|
- firebase_analytics (from `Flutter/ephemeral/.symlinks/plugins/firebase_analytics/macos`)
|
||||||
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
|
- firebase_core (from `Flutter/ephemeral/.symlinks/plugins/firebase_core/macos`)
|
||||||
@@ -315,6 +318,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/device_info_plus/macos
|
||||||
file_picker:
|
file_picker:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/file_picker/macos
|
||||||
|
file_saver:
|
||||||
|
:path: Flutter/ephemeral/.symlinks/plugins/file_saver/macos
|
||||||
file_selector_macos:
|
file_selector_macos:
|
||||||
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
|
:path: Flutter/ephemeral/.symlinks/plugins/file_selector_macos/macos
|
||||||
firebase_analytics:
|
firebase_analytics:
|
||||||
@@ -384,34 +389,35 @@ SPEC CHECKSUMS:
|
|||||||
croppy: d9bfc8c02f3cd1851f669a421df298a474b78f43
|
croppy: d9bfc8c02f3cd1851f669a421df298a474b78f43
|
||||||
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
|
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
|
||||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||||
|
file_saver: e35bd97de451dde55ff8c38862ed7ad0f3418d0f
|
||||||
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
|
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
|
||||||
Firebase: 800d487043c0557d9faed71477a38d9aafb08a41
|
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
|
||||||
firebase_analytics: 53f0dc87ad10f56a6df8746da60d8a5fe41f886f
|
firebase_analytics: efe6e51156f4565f3791d99072e8e3b0fcca0e91
|
||||||
firebase_core: eeea10f64026b68cd0bc3dee079ab4717e22909e
|
firebase_core: a8d3b82b0a87bd1d0ebc21e686b37e939c56e6e1
|
||||||
firebase_crashlytics: 7be1dacc38809971354def57193b280636a3d51a
|
firebase_crashlytics: fdbe67a1229a9e583ebf2b155541491aa83927bb
|
||||||
firebase_messaging: 5eefcd5bde556bfacdd9968e11c52f39032dfbe5
|
firebase_messaging: 6fb526705903e2e56e38a6ff56b43668b052b01b
|
||||||
FirebaseAnalytics: 6d790cd1b159b4eb61a99948df0934ce505a34f7
|
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
|
||||||
FirebaseCore: 055f4ab117d5964158c833f3d5e7ec6d91648d4a
|
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
|
||||||
FirebaseCoreExtension: 639afb3de6abd611952be78a794c54a47fa0f361
|
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5
|
||||||
FirebaseCoreInternal: dedc28e569a4be85f38f3d6af1070a2e12018d55
|
FirebaseCoreInternal: 56ea29f3dad2894f81b060f706f9d53509b6ed3b
|
||||||
FirebaseCrashlytics: db75aa0cab8d00f68406fa247c32fe17ade884d7
|
FirebaseCrashlytics: f83cbf176d5c637ade108c0aacf1ccbd5ec499bf
|
||||||
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
FirebaseInstallations: 3e884b01feabdf67582a80f3250425a00979b4ed
|
||||||
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
FirebaseMessaging: 43ec73bbfedd0c385a849bb91593ab4ad4b9e48e
|
||||||
FirebaseRemoteConfigInterop: bfa0ea72ba3dc5af739777296424e46bd6f42613
|
FirebaseRemoteConfigInterop: 0896fd52ab72586a355c8f389ff85aaa9e5375e1
|
||||||
FirebaseSessions: 4e784acda213108aafef536535cdfc03504acc42
|
FirebaseSessions: f4692789e770bec66ce17d772c0e9561c4f11737
|
||||||
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
|
flutter_inappwebview_macos: c2d68649f9f8f1831bfcd98d73fd6256366d9d1d
|
||||||
flutter_platform_alert: 8fa7a7c21f95b26d08b4a3891936ca27e375f284
|
flutter_platform_alert: 8fa7a7c21f95b26d08b4a3891936ca27e375f284
|
||||||
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
|
flutter_secure_storage_macos: 7f45e30f838cf2659862a4e4e3ee1c347c2b3b54
|
||||||
flutter_timezone: d59eea86178cbd7943cd2431cc2eaa9850f935d8
|
flutter_timezone: d59eea86178cbd7943cd2431cc2eaa9850f935d8
|
||||||
flutter_udid: d26e455e8c06174e6aff476e147defc6cae38495
|
flutter_udid: d26e455e8c06174e6aff476e147defc6cae38495
|
||||||
flutter_webrtc: 0d70bd8782c19bde286dc52f766eebbea26de201
|
flutter_webrtc: 1ce7fe9a42f085286378355a575e682edd7f114d
|
||||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
FlutterMacOS: d0db08ddef1a9af05a5ec4b724367152bb0500b1
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
GoogleAppMeasurement: 8f6ab04ad6ae493b53fcf56bd26323fb2f1384f3
|
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba
|
irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba
|
||||||
livekit_client: 0b0515e03858b86a7c14cc7fd6f772331f6ee84c
|
livekit_client: 5a5c0f1081978542bbf9a986c7ac9bffcdb73906
|
||||||
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
||||||
media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65
|
media_kit_libs_macos_video: 85a23e549b5f480e72cae3e5634b5514bc692f65
|
||||||
media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758
|
media_kit_video: fa6564e3799a0a28bff39442334817088b7ca758
|
||||||
@@ -434,7 +440,7 @@ SPEC CHECKSUMS:
|
|||||||
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
||||||
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
||||||
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497
|
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497
|
||||||
WebRTC-SDK: d20de357dcbf7c9696b124b39f3ff62125107e4b
|
WebRTC-SDK: 69d4e56b0b4b27d788e87bab9b9a1326ed05b1e3
|
||||||
|
|
||||||
PODFILE CHECKSUM: 346bfb2deb41d4a6ebd6f6799f92188bde2d246f
|
PODFILE CHECKSUM: 346bfb2deb41d4a6ebd6f6799f92188bde2d246f
|
||||||
|
|
||||||
|
@@ -586,7 +586,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
@@ -674,7 +674,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
@@ -724,7 +724,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
MACOSX_DEPLOYMENT_TARGET = 10.14;
|
MACOSX_DEPLOYMENT_TARGET = 10.15;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = macosx;
|
SDKROOT = macosx;
|
||||||
SWIFT_COMPILATION_MODE = wholemodule;
|
SWIFT_COMPILATION_MODE = wholemodule;
|
||||||
|
168
pubspec.lock
168
pubspec.lock
@@ -13,10 +13,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _flutterfire_internals
|
name: _flutterfire_internals
|
||||||
sha256: bb84ee51e527053dd8e25ecc9f97a6abfdc19130fb4d883e4e8585e23e7e6dd8
|
sha256: "948f7d74f41dd6f2d563ea9f4c21d7ea764f8e047d2b24138974c19c24d37eb6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.60"
|
version: "1.3.61"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -569,6 +569,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.3.2"
|
version: "10.3.2"
|
||||||
|
file_saver:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: file_saver
|
||||||
|
sha256: "9d93db09bd4da9e43238f9dd485360fc51a5c138eea5ef5f407ec56e58079ac0"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "0.3.1"
|
||||||
file_selector_linux:
|
file_selector_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -605,34 +613,34 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_analytics
|
name: firebase_analytics
|
||||||
sha256: "07146e89e11302c6b07e3465c2c556ebcdd0053a3c5b1aa9bfd3203b778e5b4c"
|
sha256: dde9d6a7b69b07551a77cfb913c81c64804f7602b07541328322c321e73f2a0e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "12.0.0"
|
version: "12.0.1"
|
||||||
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: "27e81a0efc821bec6cba64abc1083b91c8ddbad28eeb4c6f6b7c78a59d06f259"
|
sha256: "4008d82a58edcbedec34a7b39f457eed24181cb9c89782c104828c42e4c859b2"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "5.0.1"
|
||||||
firebase_analytics_web:
|
firebase_analytics_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_analytics_web
|
name: firebase_analytics_web
|
||||||
sha256: "7d87f47462042a7d9125e3123db2783bc72917d85e2719d4cb6aeaec209605e1"
|
sha256: db2a2e8803f5471a5f89b4abacae95ae27e0644f77526879fb81a2c1abc12b5f
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.6.0"
|
version: "0.6.0+1"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
sha256: "6b343e6f7b72a4f32d7ce8df8c9a28d8f54b4ac20d7c6500f3e8b3969afca457"
|
sha256: "967dae9a65f69377beb9f4ab292ea63ce5befa1ce24682cab1b69ca4b7a46927"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.1.0"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -645,50 +653,50 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_web
|
name: firebase_core_web
|
||||||
sha256: "5d28b14dd32282fb7ce2b22b897362453755b6b8541d491127dc72b755bb7b16"
|
sha256: f7ee08febc1c4451588ce58ffcf28edaee857e9a196fee88b85deb889990094a
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.0"
|
version: "3.1.0"
|
||||||
firebase_crashlytics:
|
firebase_crashlytics:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_crashlytics
|
name: firebase_crashlytics
|
||||||
sha256: "95b6871850b1a7e3b09c284c59a0c71fafcad3eee8ac1b6f06aaf8979290cbb8"
|
sha256: f2e175a967712ee1f616ab8843390891a315428ba497ce3d256d4c46f32db6f8
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.0.0"
|
version: "5.0.1"
|
||||||
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: ba5b7a916f1ebedc6db35b33abdc618f202fc25e0792088dfba698e19fec9c09
|
sha256: b49b90af4a1fd8f30b58abd90af88371969bea51b62838a4f4e737c2098b725e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.8.11"
|
version: "3.8.12"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging
|
name: firebase_messaging
|
||||||
sha256: "10272b553a49c13a6cedfd00121047157521f82a5d3f2a1706b9dd28342cc482"
|
sha256: aad5dcdea5698499b70d74d5a53b1f6a9972f85f97225e4b7ac006dd8d4f9bac
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "16.0.0"
|
version: "16.0.1"
|
||||||
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: b846a305feb3f74ee3f0aace447f65a4696bc6550bc828ecf5a84a1b77473d16
|
sha256: "825bc11767bf50a43dccf49b3026f847ec31d0f176139bfc48d662cc128b5014"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.7.0"
|
version: "4.7.1"
|
||||||
firebase_messaging_web:
|
firebase_messaging_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_web
|
name: firebase_messaging_web
|
||||||
sha256: "28714749880f7242c5fb3b1ee6c66b41f61453f02ae348b43c82957df80b87ae"
|
sha256: db8dbdd79921245c4de02407e33cae2d1868683be18a5ba948d2af5311e3ef5d
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.0.0"
|
version: "4.0.1"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -701,10 +709,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: fl_chart
|
name: fl_chart
|
||||||
sha256: "577aeac8ca414c25333334d7c4bb246775234c0e44b38b10a82b559dd4d764e7"
|
sha256: d3f82f4a38e33ba23d05a08ff304d7d8b22d2a59a5503f20bd802966e915db89
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
flutter:
|
flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description: flutter
|
description: flutter
|
||||||
@@ -878,14 +886,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.0.0"
|
||||||
flutter_langdetect:
|
|
||||||
dependency: "direct main"
|
|
||||||
description:
|
|
||||||
name: flutter_langdetect
|
|
||||||
sha256: "93bd865c7d5723eac614744abb32234ee4f593505a293bc17ef097bd55fbdf38"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.0.2"
|
|
||||||
flutter_launcher_icons:
|
flutter_launcher_icons:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -959,10 +959,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_plugin_android_lifecycle
|
name: flutter_plugin_android_lifecycle
|
||||||
sha256: "6382ce712ff69b0f719640ce957559dde459e55ecd433c767e06d139ddf16cab"
|
sha256: b0694b7fb1689b0e6cc193b3f1fcac6423c4f93c74fb20b806c6b6f196db0c31
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.29"
|
version: "2.0.30"
|
||||||
flutter_popup_card:
|
flutter_popup_card:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1070,21 +1070,21 @@ packages:
|
|||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
flutter_webrtc:
|
flutter_webrtc:
|
||||||
dependency: "direct main"
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_webrtc
|
name: flutter_webrtc
|
||||||
sha256: "69095ba39b83da3de48286dfc0769aa8e9f10491f70058dc8d8ecc960ef7a260"
|
sha256: "945d0a38b90fbca8257eadb167d8fb9fa7075d9a1939fd2953c10054454d1de2"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0"
|
version: "1.1.0"
|
||||||
font_awesome_flutter:
|
font_awesome_flutter:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: font_awesome_flutter
|
name: font_awesome_flutter
|
||||||
sha256: b738e35f8bb4957896c34957baf922f99c5d415b38ddc8b070d14b7fa95715d4
|
sha256: "27af5982e6c510dec1ba038eff634fa284676ee84e3fd807225c80c4ad869177"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.9.1"
|
version: "10.10.0"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -1145,18 +1145,18 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: go_router
|
name: go_router
|
||||||
sha256: ced3fdc143c1437234ac3b8e985f3286cf138968bb83ca9a6f94d22f2951c6b9
|
sha256: eb059dfe59f08546e9787f895bd01652076f996bcbf485a8609ef990419ad227
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "16.2.0"
|
version: "16.2.1"
|
||||||
google_fonts:
|
google_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: google_fonts
|
name: google_fonts
|
||||||
sha256: df9763500dadba0155373e9cb44e202ce21bd9ed5de6bdbd05c5854e86839cb8
|
sha256: ebc94ed30fd13cefd397cb1658b593f21571f014b7d1197eeb41fb95f05d899a
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.0"
|
version: "6.3.1"
|
||||||
graphs:
|
graphs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1249,10 +1249,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image_picker_android
|
name: image_picker_android
|
||||||
sha256: e83b2b05141469c5e19d77e1dfa11096b6b1567d09065b2265d7c6904560050c
|
sha256: "28f3987ca0ec702d346eae1d90eda59603a2101b52f1e234ded62cff1d5cfa6e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.13"
|
version: "0.8.13+1"
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1361,26 +1361,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker
|
name: leak_tracker
|
||||||
sha256: "6bb818ecbdffe216e81182c2f0714a2e62b593f4a4f13098713ff1685dfb6ab0"
|
sha256: "8dcda04c3fc16c14f48a7bb586d4be1f0d1572731b6d81d51772ef47c02081e0"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.0.9"
|
version: "11.0.1"
|
||||||
leak_tracker_flutter_testing:
|
leak_tracker_flutter_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_flutter_testing
|
name: leak_tracker_flutter_testing
|
||||||
sha256: f8b613e7e6a13ec79cfdc0e97638fddb3ab848452eff057653abd3edba760573
|
sha256: "1dbc140bb5a23c75ea9c4811222756104fbcd1a27173f0c34ca01e16bea473c1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.9"
|
version: "3.0.10"
|
||||||
leak_tracker_testing:
|
leak_tracker_testing:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: leak_tracker_testing
|
name: leak_tracker_testing
|
||||||
sha256: "6ba465d5d76e67ddf503e1161d1f4a6bc42306f9d66ca1e8f079a47290fb06d3"
|
sha256: "8d5a2d49f4a66b49744b23b018848400d23e54caf9463f4eb20df3eb8acb2eb1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.2"
|
||||||
lint:
|
lint:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1401,10 +1401,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: livekit_client
|
name: livekit_client
|
||||||
sha256: b3db2d8afa8d1dbe4fd8dfc965fc9d661cb51a8d864ad199919575ce919a40fb
|
sha256: "011affc0fca22b2f9b0e8827219dad9948f84f2bf057980693de13039de904c7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.0+hotfix.1"
|
version: "2.5.0+hotfix.3"
|
||||||
local_auth:
|
local_auth:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1417,10 +1417,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: local_auth_android
|
name: local_auth_android
|
||||||
sha256: "316503f6772dea9c0c038bb7aac4f68ab00112d707d258c770f7fc3c250a2d88"
|
sha256: "48924f4a8b3cc45994ad5993e2e232d3b00788a305c1bf1c7db32cef281ce9a3"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.51"
|
version: "1.0.52"
|
||||||
local_auth_darwin:
|
local_auth_darwin:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1449,10 +1449,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: logger
|
name: logger
|
||||||
sha256: "7ad7215c15420a102ec687bb320a7312afd449bac63bfb1c60d9787c27b9767f"
|
sha256: "55d6c23a6c15db14920e037fe7e0dc32e7cdaf3b64b4b25df2d541b5b6b81c0c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "2.6.1"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1713,10 +1713,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: path_provider_android
|
name: path_provider_android
|
||||||
sha256: d0d310befe2c8ab9e7f393288ccbb11b60c019c6b5afc21973eeee4dda2b35e9
|
sha256: "993381400e94d18469750e5b9dcb8206f15bc09f9da86b9e44a9b0092a0066db"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.2.17"
|
version: "2.2.18"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1753,10 +1753,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: petitparser
|
name: petitparser
|
||||||
sha256: "07c8f0b1913bcde1ff0d26e57ace2f3012ccbf2b204e070290dad3bb22797646"
|
sha256: "1a97266a94f7350d30ae522c0af07890c70b8e62c71e8e3920d1db4d23c057d1"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.1.0"
|
version: "7.0.1"
|
||||||
photo_view:
|
photo_view:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1921,10 +1921,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: record_ios
|
name: record_ios
|
||||||
sha256: "895c9467faec72d8e718a3142b51114958f42f18053836a8b484a74f9372f51a"
|
sha256: "13e241ed9cbc220534a40ae6b66222e21288db364d96dd66fb762ebd3cb77c71"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.1"
|
version: "1.1.2"
|
||||||
record_linux:
|
record_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2041,10 +2041,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: screen_brightness_android
|
name: screen_brightness_android
|
||||||
sha256: fb5fa43cb89d0c9b8534556c427db1e97e46594ac5d66ebdcf16063b773d54ed
|
sha256: d34f5321abd03bc3474f4c381f53d189117eba0b039eac1916aa92cca5fd0a96
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.2"
|
version: "2.1.3"
|
||||||
screen_brightness_platform_interface:
|
screen_brightness_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2105,10 +2105,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "5bcf0772a761b04f8c6bf814721713de6f3e5d9d89caf8d3fe031b02a342379e"
|
sha256: a2608114b1ffdcbc9c120eb71a0e207c71da56202852d4aab8a5e30a82269e74
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.11"
|
version: "2.4.12"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2246,10 +2246,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqflite_android
|
name: sqflite_android
|
||||||
sha256: "2b3070c5fa881839f8b402ee4a39c1b4d561704d4ebbbcfb808a119bc2a1701b"
|
sha256: ecd684501ebc2ae9a83536e8b15731642b9570dc8623e0073d227d0ee2bfea88
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.1"
|
version: "2.4.2+2"
|
||||||
sqflite_common:
|
sqflite_common:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2398,10 +2398,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: test_api
|
name: test_api
|
||||||
sha256: fb31f383e2ee25fbbfe06b40fe21e1e458d14080e3c67e7ba0acfde4df4e0bbd
|
sha256: "522f00f556e73044315fa4585ec3270f1808a4b186c936e612cab0b565ff1e00"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.6"
|
||||||
textfield_tags:
|
textfield_tags:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -2496,10 +2496,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: "0aedad096a85b49df2e4725fa32118f9fa580f3b14af7a2d2221896a02cd5656"
|
sha256: "69ee86740f2847b9a4ba6cffa74ed12ce500bbe2b07f3dc1e643439da60637b7"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.17"
|
version: "6.3.18"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2576,18 +2576,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_graphics_compiler
|
name: vector_graphics_compiler
|
||||||
sha256: ca81fdfaf62a5ab45d7296614aea108d2c7d0efca8393e96174bf4d51e6725b0
|
sha256: d354a7ec6931e6047785f4db12a1f61ec3d43b207fc0790f863818543f8ff0dc
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.18"
|
version: "1.1.19"
|
||||||
vector_math:
|
vector_math:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vector_math
|
name: vector_math
|
||||||
sha256: "80b3257d1492ce4d091729e3a67a60407d227c27241d6927be0130c98e741803"
|
sha256: d530bd74fea330e6e364cda7a85019c434070188383e1cd8d9777ee586914c5b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.1.4"
|
version: "2.2.0"
|
||||||
very_good_infinite_list:
|
very_good_infinite_list:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -2608,10 +2608,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: vm_service
|
name: vm_service
|
||||||
sha256: ddfa8d30d89985b96407efce8acbdd124701f96741f2d981ca860662f1c0dc02
|
sha256: "45caa6c5917fa127b5dbcfbd1fa60b14e583afdc08bfc96dda38886ca252eb60"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.0.0"
|
version: "15.0.2"
|
||||||
volume_controller:
|
volume_controller:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2640,10 +2640,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: watcher
|
name: watcher
|
||||||
sha256: "0b7fd4a0bbc4b92641dbf20adfd7e3fd1398fe17102d94b674234563e110088a"
|
sha256: "5bf046f41320ac97a469d506261797f35254fa61c641741ef32dacda98b7d39c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.1.2"
|
version: "1.1.3"
|
||||||
waveform_flutter:
|
waveform_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -2712,10 +2712,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: xml
|
name: xml
|
||||||
sha256: b015a8ad1c488f66851d762d3090a21c600e479dc75e68328c52774040cf9226
|
sha256: "971043b3a0d3da28727e40ed3e0b5d18b742fa5a68665cca88e74b7876d5e025"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.5.0"
|
version: "6.6.1"
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2725,5 +2725,5 @@ packages:
|
|||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.3"
|
version: "3.1.3"
|
||||||
sdks:
|
sdks:
|
||||||
dart: ">=3.8.0 <4.0.0"
|
dart: ">=3.9.0 <4.0.0"
|
||||||
flutter: ">=3.32.0"
|
flutter: ">=3.32.0"
|
||||||
|
23
pubspec.yaml
23
pubspec.yaml
@@ -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+128
|
version: 3.2.0+129
|
||||||
|
|
||||||
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.0
|
go_router: ^16.2.1
|
||||||
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
|
||||||
@@ -53,7 +53,7 @@ dependencies:
|
|||||||
flutter_highlight: ^0.7.0
|
flutter_highlight: ^0.7.0
|
||||||
uuid: ^4.5.1
|
uuid: ^4.5.1
|
||||||
url_launcher: ^6.3.2
|
url_launcher: ^6.3.2
|
||||||
google_fonts: ^6.3.0
|
google_fonts: ^6.3.1
|
||||||
gap: ^3.0.1
|
gap: ^3.0.1
|
||||||
cached_network_image: ^3.4.1
|
cached_network_image: ^3.4.1
|
||||||
web: ^1.1.1
|
web: ^1.1.1
|
||||||
@@ -76,12 +76,12 @@ dependencies:
|
|||||||
file_picker: ^10.3.2
|
file_picker: ^10.3.2
|
||||||
riverpod_annotation: ^2.6.1
|
riverpod_annotation: ^2.6.1
|
||||||
image_picker_platform_interface: ^2.11.0
|
image_picker_platform_interface: ^2.11.0
|
||||||
image_picker_android: ^0.8.13
|
image_picker_android: ^0.8.13+1
|
||||||
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.0
|
firebase_messaging: ^16.0.1
|
||||||
flutter_udid: ^4.0.0
|
flutter_udid: ^4.0.0
|
||||||
firebase_core: ^4.0.0
|
firebase_core: ^4.1.0
|
||||||
web_socket_channel: ^3.0.3
|
web_socket_channel: ^3.0.3
|
||||||
material_symbols_icons: ^4.2867.0
|
material_symbols_icons: ^4.2867.0
|
||||||
drift: ^2.28.1
|
drift: ^2.28.1
|
||||||
@@ -103,8 +103,7 @@ dependencies:
|
|||||||
gal: ^2.3.2
|
gal: ^2.3.2
|
||||||
dismissible_page: ^1.0.2
|
dismissible_page: ^1.0.2
|
||||||
super_sliver_list: ^0.4.1
|
super_sliver_list: ^0.4.1
|
||||||
flutter_webrtc: ^1.0.0
|
livekit_client: ^2.5.0+hotfix.3
|
||||||
livekit_client: ^2.5.0+hotfix.1
|
|
||||||
pasteboard: ^0.4.0
|
pasteboard: ^0.4.0
|
||||||
flutter_colorpicker: ^1.1.0
|
flutter_colorpicker: ^1.1.0
|
||||||
record: ^6.1.1
|
record: ^6.1.1
|
||||||
@@ -114,7 +113,7 @@ dependencies:
|
|||||||
flutter_popup_card: ^0.0.6
|
flutter_popup_card: ^0.0.6
|
||||||
timezone: ^0.10.1
|
timezone: ^0.10.1
|
||||||
flutter_timezone: ^4.1.1
|
flutter_timezone: ^4.1.1
|
||||||
fl_chart: ^1.0.0
|
fl_chart: ^1.1.0
|
||||||
sign_in_with_apple: ^7.0.1
|
sign_in_with_apple: ^7.0.1
|
||||||
flutter_svg: ^2.2.0
|
flutter_svg: ^2.2.0
|
||||||
native_exif: ^0.6.2
|
native_exif: ^0.6.2
|
||||||
@@ -131,14 +130,14 @@ dependencies:
|
|||||||
mime: ^2.0.0
|
mime: ^2.0.0
|
||||||
html2md: ^1.3.2
|
html2md: ^1.3.2
|
||||||
flutter_typeahead: ^5.2.0
|
flutter_typeahead: ^5.2.0
|
||||||
flutter_langdetect: ^0.0.2
|
|
||||||
waveform_flutter: ^1.2.0
|
waveform_flutter: ^1.2.0
|
||||||
flutter_app_update: ^3.2.2
|
flutter_app_update: ^3.2.2
|
||||||
firebase_crashlytics: ^5.0.0
|
firebase_crashlytics: ^5.0.1
|
||||||
firebase_analytics: ^12.0.0
|
firebase_analytics: ^12.0.1
|
||||||
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
|
||||||
|
file_saver: ^0.3.1
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
|
@@ -8,6 +8,7 @@
|
|||||||
|
|
||||||
#include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
|
#include <bitsdojo_window_windows/bitsdojo_window_plugin.h>
|
||||||
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
#include <connectivity_plus/connectivity_plus_windows_plugin.h>
|
||||||
|
#include <file_saver/file_saver_plugin.h>
|
||||||
#include <file_selector_windows/file_selector_windows.h>
|
#include <file_selector_windows/file_selector_windows.h>
|
||||||
#include <firebase_core/firebase_core_plugin_c_api.h>
|
#include <firebase_core/firebase_core_plugin_c_api.h>
|
||||||
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
#include <flutter_inappwebview_windows/flutter_inappwebview_windows_plugin_c_api.h>
|
||||||
@@ -35,6 +36,8 @@ void RegisterPlugins(flutter::PluginRegistry* registry) {
|
|||||||
registry->GetRegistrarForPlugin("BitsdojoWindowPlugin"));
|
registry->GetRegistrarForPlugin("BitsdojoWindowPlugin"));
|
||||||
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
ConnectivityPlusWindowsPluginRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
registry->GetRegistrarForPlugin("ConnectivityPlusWindowsPlugin"));
|
||||||
|
FileSaverPluginRegisterWithRegistrar(
|
||||||
|
registry->GetRegistrarForPlugin("FileSaverPlugin"));
|
||||||
FileSelectorWindowsRegisterWithRegistrar(
|
FileSelectorWindowsRegisterWithRegistrar(
|
||||||
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
registry->GetRegistrarForPlugin("FileSelectorWindows"));
|
||||||
FirebaseCorePluginCApiRegisterWithRegistrar(
|
FirebaseCorePluginCApiRegisterWithRegistrar(
|
||||||
|
@@ -5,6 +5,7 @@
|
|||||||
list(APPEND FLUTTER_PLUGIN_LIST
|
list(APPEND FLUTTER_PLUGIN_LIST
|
||||||
bitsdojo_window_windows
|
bitsdojo_window_windows
|
||||||
connectivity_plus
|
connectivity_plus
|
||||||
|
file_saver
|
||||||
file_selector_windows
|
file_selector_windows
|
||||||
firebase_core
|
firebase_core
|
||||||
flutter_inappwebview_windows
|
flutter_inappwebview_windows
|
||||||
|
Reference in New Issue
Block a user