Compare commits
38 Commits
3.1.0+114
...
b39e2e2d64
| Author | SHA1 | Date | |
|---|---|---|---|
| b39e2e2d64 | |||
| 84b1d6a346 | |||
| 28335dd548 | |||
| 7253e2d3ef | |||
| 4d489425fa | |||
| 890a8a44cf | |||
| 8e3583f57a | |||
| d0ff14659f | |||
| 1f7caaeaac | |||
| 9f9f42071a | |||
| 6bd6e994cb | |||
| 02e68d76ee | |||
| d04b06089c | |||
| 9be6fea2e0 | |||
| 6b1214a06f | |||
| 4597373ac9 | |||
| 047c8d93aa | |||
| 715f95ca22 | |||
| ba709012d7 | |||
| fd186f8391 | |||
| 262d36cd2d | |||
| f320855348 | |||
| ed90152462 | |||
| 6e5c5f1690 | |||
| 7c92dee097 | |||
| e4bb031138 | |||
| 97226ae96b | |||
| d8cd33e79a | |||
| 5ecd39b6a9 | |||
| 8854305e99 | |||
| 903cade296 | |||
| e48410a528 | |||
| 170ea4f2c0 | |||
| 19f0e11384 | |||
| 80bf6c3bbe | |||
| 8352ce8b5b | |||
| c06abf6e42 | |||
| 37cc0a5291 |
2
.github/workflows/build.yml
vendored
2
.github/workflows/build.yml
vendored
@@ -59,7 +59,7 @@ jobs:
|
|||||||
sudo apt-get install -y libnotify-dev
|
sudo apt-get install -y libnotify-dev
|
||||||
sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||||
sudo apt-get install -y gstreamer-1.0
|
sudo apt-get install -y gstreamer-1.0
|
||||||
sudo apt-get install -y libsecret-1-0
|
sudo apt-get install -y libsecret-1-dev
|
||||||
- run: flutter pub get
|
- run: flutter pub get
|
||||||
- run: flutter build linux
|
- run: flutter build linux
|
||||||
- name: Archive production artifacts
|
- name: Archive production artifacts
|
||||||
|
|||||||
@@ -8,6 +8,9 @@
|
|||||||
|
|
||||||
Hello there! Welcome to the main repository of the DysonNetwork (also known as the Solar Network). The code here is mainly about the front-end app (also known as Solian). But you can still post issues here to get help and request new features!
|
Hello there! Welcome to the main repository of the DysonNetwork (also known as the Solar Network). The code here is mainly about the front-end app (also known as Solian). But you can still post issues here to get help and request new features!
|
||||||
|
|
||||||
|
如果你看得懂这行字,你可以前往我们的文档来了解更多:
|
||||||
|
[Suki - Solar Network](https://kb.solsynth.dev/zh/solar-network)
|
||||||
|
|
||||||
## Server
|
## Server
|
||||||
|
|
||||||
The backend of the Solar Network project is located at [Solsynth/DysonNetwork](https://github.com/Solsynth/DysonNetwork)
|
The backend of the Solar Network project is located at [Solsynth/DysonNetwork](https://github.com/Solsynth/DysonNetwork)
|
||||||
@@ -25,8 +28,6 @@ The content below will lead you to the world of Solar Network.
|
|||||||
|
|
||||||
### For Normal Users
|
### For Normal Users
|
||||||
|
|
||||||
**The v3 Release is not ready, yet.**
|
|
||||||
|
|
||||||
1. Go to the Github Releases page, and download the latest release / pre-release according to your platform.
|
1. Go to the Github Releases page, and download the latest release / pre-release according to your platform.
|
||||||
- **What's the difference between stable and pre-release?** The pre-release is untested by the other users and includes the new cutting-edge features, usually the pre-release is the feature drop. At the same time, due to we're not doing the API versioning, some breaking changes may break the stable release, so use the pre-release one instead.
|
- **What's the difference between stable and pre-release?** The pre-release is untested by the other users and includes the new cutting-edge features, usually the pre-release is the feature drop. At the same time, due to we're not doing the API versioning, some breaking changes may break the stable release, so use the pre-release one instead.
|
||||||
2. Create an account on the Solar Network
|
2. Create an account on the Solar Network
|
||||||
|
|||||||
@@ -147,6 +147,9 @@
|
|||||||
"addVideo": "Add video",
|
"addVideo": "Add video",
|
||||||
"addPhoto": "Add photo",
|
"addPhoto": "Add photo",
|
||||||
"addFile": "Add file",
|
"addFile": "Add file",
|
||||||
|
"linkAttachment": "Link Attachment",
|
||||||
|
"fileIdCannotBeEmpty": "File ID cannot be empty",
|
||||||
|
"failedToFetchFile": "Failed to fetch file: {}",
|
||||||
"createDirectMessage": "Send new DM",
|
"createDirectMessage": "Send new DM",
|
||||||
"gotoDirectMessage": "Go to DM",
|
"gotoDirectMessage": "Go to DM",
|
||||||
"react": "React",
|
"react": "React",
|
||||||
@@ -352,6 +355,8 @@
|
|||||||
"postTitle": "Title",
|
"postTitle": "Title",
|
||||||
"postDescription": "Description",
|
"postDescription": "Description",
|
||||||
"call": "Call",
|
"call": "Call",
|
||||||
|
"callLeave": "Leave",
|
||||||
|
"callEnd": "End this call",
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"loginResetPasswordSent": "Password reset link sent, please check your email inbox.",
|
"loginResetPasswordSent": "Password reset link sent, please check your email inbox.",
|
||||||
"accountDeletion": "Delete Account",
|
"accountDeletion": "Delete Account",
|
||||||
@@ -622,8 +627,8 @@
|
|||||||
"chatJoin": "Join the Chat",
|
"chatJoin": "Join the Chat",
|
||||||
"realmJoin": "Join the Realm",
|
"realmJoin": "Join the Realm",
|
||||||
"realmJoinSuccess": "Successfully joined the realm.",
|
"realmJoinSuccess": "Successfully joined the realm.",
|
||||||
"discoverRealms": "Discover Realms",
|
"discoverRealms": "Discover realms",
|
||||||
"discoverPublishers": "Discover Publishers",
|
"discoverPublishers": "Discover publishers",
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
"publisherMembers": "Collaborators",
|
"publisherMembers": "Collaborators",
|
||||||
"developerHub": "Developer Hub",
|
"developerHub": "Developer Hub",
|
||||||
@@ -702,5 +707,26 @@
|
|||||||
"aboutDeviceName": "Device Name",
|
"aboutDeviceName": "Device Name",
|
||||||
"aboutDeviceIdentifier": "Device Identifier",
|
"aboutDeviceIdentifier": "Device Identifier",
|
||||||
"donate": "Donate",
|
"donate": "Donate",
|
||||||
"donateDescription": "Support us to continue developing the Solar Network and keep the server up and running."
|
"donateDescription": "Support us to continue developing the Solar Network and keep the server up and running.",
|
||||||
|
"fileId": "File ID",
|
||||||
|
"fileIdHint": "The file ID is the ID you get after upload the file via the Solar Network Drive.",
|
||||||
|
"translate": "Translate",
|
||||||
|
"translating": "Translating",
|
||||||
|
"translated": "Translated",
|
||||||
|
"reactionThumbUp": "Thumbs Up",
|
||||||
|
"reactionThumbDown": "Thumbs Down",
|
||||||
|
"reactionJustOkay": "Just Okay",
|
||||||
|
"reactionCry": "Cry",
|
||||||
|
"reactionConfuse": "Confused",
|
||||||
|
"reactionClap": "Clap",
|
||||||
|
"reactionLaugh": "Laugh",
|
||||||
|
"reactionAngry": "Angry",
|
||||||
|
"reactionParty": "Party",
|
||||||
|
"reactionPray": "Pray",
|
||||||
|
"reactionHeart": "Heart",
|
||||||
|
"selectMicrophone": "Select Microphone",
|
||||||
|
"selectCamera": "Select Camera",
|
||||||
|
"switchedTo": "Switched to {}",
|
||||||
|
"connecting": "Connecting",
|
||||||
|
"repliesLoadMore": "Load more replies"
|
||||||
}
|
}
|
||||||
@@ -123,6 +123,10 @@
|
|||||||
"addVideo": "添加视频",
|
"addVideo": "添加视频",
|
||||||
"addPhoto": "添加照片",
|
"addPhoto": "添加照片",
|
||||||
"addFile": "添加文件",
|
"addFile": "添加文件",
|
||||||
|
"addAttachmentById": "通过 ID 添加附件",
|
||||||
|
"enterFileId": "输入文件 ID",
|
||||||
|
"fileIdCannotBeEmpty": "文件 ID 不能为空",
|
||||||
|
"failedToFetchFile": "获取文件失败: {}",
|
||||||
"createDirectMessage": "创建新私人消息",
|
"createDirectMessage": "创建新私人消息",
|
||||||
"gotoDirectMessage": "前往私信",
|
"gotoDirectMessage": "前往私信",
|
||||||
"react": "反应",
|
"react": "反应",
|
||||||
|
|||||||
@@ -123,6 +123,10 @@
|
|||||||
"addVideo": "新增影片",
|
"addVideo": "新增影片",
|
||||||
"addPhoto": "新增照片",
|
"addPhoto": "新增照片",
|
||||||
"addFile": "新增檔案",
|
"addFile": "新增檔案",
|
||||||
|
"addAttachmentById": "透過 ID 新增附件",
|
||||||
|
"enterFileId": "輸入檔案 ID",
|
||||||
|
"fileIdCannotBeEmpty": "檔案 ID 不能為空",
|
||||||
|
"failedToFetchFile": "無法取得檔案: {}",
|
||||||
"createDirectMessage": "建立新私人訊息",
|
"createDirectMessage": "建立新私人訊息",
|
||||||
"gotoDirectMessage": "Go to DM",
|
"gotoDirectMessage": "Go to DM",
|
||||||
"react": "反應",
|
"react": "反應",
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
# Uncomment this line to define a global platform for your project
|
||||||
platform :ios, '13.0'
|
platform :ios, '15.0'
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|||||||
@@ -40,33 +40,33 @@ PODS:
|
|||||||
- file_picker (0.0.1):
|
- file_picker (0.0.1):
|
||||||
- DKImagePickerController/PhotoGallery
|
- DKImagePickerController/PhotoGallery
|
||||||
- Flutter
|
- Flutter
|
||||||
- Firebase/CoreOnly (11.15.0):
|
- Firebase/CoreOnly (12.0.0):
|
||||||
- FirebaseCore (~> 11.15.0)
|
- FirebaseCore (~> 12.0.0)
|
||||||
- Firebase/Messaging (11.15.0):
|
- Firebase/Messaging (12.0.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 11.15.0)
|
- FirebaseMessaging (~> 12.0.0)
|
||||||
- firebase_core (3.15.1):
|
- firebase_core (4.0.0):
|
||||||
- Firebase/CoreOnly (= 11.15.0)
|
- Firebase/CoreOnly (= 12.0.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_messaging (15.2.9):
|
- firebase_messaging (16.0.0):
|
||||||
- Firebase/Messaging (= 11.15.0)
|
- Firebase/Messaging (= 12.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- FirebaseCore (11.15.0):
|
- FirebaseCore (12.0.0):
|
||||||
- FirebaseCoreInternal (~> 11.15.0)
|
- FirebaseCoreInternal (~> 12.0.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- FirebaseCoreInternal (11.15.0):
|
- FirebaseCoreInternal (12.0.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- FirebaseInstallations (11.15.0):
|
- FirebaseInstallations (12.0.0):
|
||||||
- FirebaseCore (~> 11.15.0)
|
- FirebaseCore (~> 12.0.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (11.15.0):
|
- FirebaseMessaging (12.0.0):
|
||||||
- FirebaseCore (~> 11.15.0)
|
- FirebaseCore (~> 12.0.0)
|
||||||
- FirebaseInstallations (~> 11.0)
|
- FirebaseInstallations (~> 12.0.0)
|
||||||
- GoogleDataTransport (~> 10.0)
|
- 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)
|
||||||
@@ -93,9 +93,9 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- flutter_webrtc (0.14.0):
|
- flutter_webrtc (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (= 125.6422.07)
|
- WebRTC-SDK (= 137.7151.02)
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -130,11 +130,11 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- irondash_engine_context (0.0.1):
|
- irondash_engine_context (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Kingfisher (8.4.0)
|
- Kingfisher (8.5.0)
|
||||||
- livekit_client (2.4.9):
|
- livekit_client (2.5.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- WebRTC-SDK (= 125.6422.07)
|
- WebRTC-SDK (= 137.7151.02)
|
||||||
- local_auth_darwin (0.0.1):
|
- local_auth_darwin (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -178,28 +178,31 @@ PODS:
|
|||||||
- sqflite_darwin (0.0.4):
|
- sqflite_darwin (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (3.50.2):
|
- sqlite3 (3.50.3):
|
||||||
- sqlite3/common (= 3.50.2)
|
- sqlite3/common (= 3.50.3)
|
||||||
- sqlite3/common (3.50.2)
|
- sqlite3/common (3.50.3)
|
||||||
- sqlite3/dbstatvtab (3.50.2):
|
- sqlite3/dbstatvtab (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/fts5 (3.50.2):
|
- sqlite3/fts5 (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/math (3.50.2):
|
- sqlite3/math (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/perf-threadsafe (3.50.2):
|
- sqlite3/perf-threadsafe (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/rtree (3.50.2):
|
- sqlite3/rtree (3.50.3):
|
||||||
|
- sqlite3/common
|
||||||
|
- sqlite3/session (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3_flutter_libs (0.0.1):
|
- sqlite3_flutter_libs (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (~> 3.50.1)
|
- sqlite3 (~> 3.50.3)
|
||||||
- sqlite3/dbstatvtab
|
- sqlite3/dbstatvtab
|
||||||
- sqlite3/fts5
|
- sqlite3/fts5
|
||||||
- sqlite3/math
|
- sqlite3/math
|
||||||
- sqlite3/perf-threadsafe
|
- sqlite3/perf-threadsafe
|
||||||
- sqlite3/rtree
|
- sqlite3/rtree
|
||||||
|
- sqlite3/session
|
||||||
- super_native_extensions (0.0.1):
|
- super_native_extensions (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SwiftyGif (5.4.5)
|
- SwiftyGif (5.4.5)
|
||||||
@@ -209,7 +212,7 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (125.6422.07)
|
- WebRTC-SDK (137.7151.02)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Alamofire
|
- Alamofire
|
||||||
@@ -361,13 +364,13 @@ SPEC CHECKSUMS:
|
|||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||||
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
|
Firebase: 800d487043c0557d9faed71477a38d9aafb08a41
|
||||||
firebase_core: ece862f94b2bc72ee0edbeec7ab5c7cb09fe1ab5
|
firebase_core: 633e1851ffe1b9ab875f6467a4f574c79cef02e4
|
||||||
firebase_messaging: e1a5fae495603115be1d0183bc849da748734e2b
|
firebase_messaging: d17feef781edc84ebefe62624fb384358ad96361
|
||||||
FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e
|
FirebaseCore: 055f4ab117d5964158c833f3d5e7ec6d91648d4a
|
||||||
FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4
|
FirebaseCoreInternal: dedc28e569a4be85f38f3d6af1070a2e12018d55
|
||||||
FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843
|
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
||||||
FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09
|
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
||||||
@@ -376,14 +379,14 @@ SPEC CHECKSUMS:
|
|||||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||||
flutter_webrtc: fd0d3bdef8766a0736dbbe2e5b7e85f1f3c52117
|
flutter_webrtc: 6f7da106613d52ade777d5b4875a43f48c28b457
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
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: b14cc47bbfa7a3c150dd12962ee9c86338545629
|
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
||||||
livekit_client: 3f79d79233a5bd13d5b541732624ef959d7c538e
|
livekit_client: e3b79b99405428aac439b6b76a254cd9a11dbbfb
|
||||||
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
|
||||||
@@ -403,15 +406,15 @@ SPEC CHECKSUMS:
|
|||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
||||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||||
sqlite3: 3e82a2daae39ba3b41ae6ee84a130494585460fc
|
sqlite3: 83105acd294c9137c026e2da1931c30b4588ab81
|
||||||
sqlite3_flutter_libs: e7fc8c9ea2200ff3271f08f127842131746b70e2
|
sqlite3_flutter_libs: 616267f2fca40e9c6af8c5d82324e05667040b6e
|
||||||
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||||
WebRTC-SDK: dff00a3892bc570b6014e046297782084071657e
|
WebRTC-SDK: d20de357dcbf7c9696b124b39f3ff62125107e4b
|
||||||
|
|
||||||
PODFILE CHECKSUM: f6df17c2a0cbd7af89692fd3877231eaea40230f
|
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -49,8 +49,7 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateMessage(ChatMessagesCompanion message) {
|
Future<int> updateMessage(ChatMessagesCompanion message) {
|
||||||
return (update(chatMessages)
|
return into(chatMessages).insert(message, mode: InsertMode.insertOrReplace);
|
||||||
..where((m) => m.id.equals(message.id.value))).write(message);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> updateMessageStatus(String id, MessageStatus status) {
|
Future<int> updateMessageStatus(String id, MessageStatus status) {
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ import 'package:bitsdojo_window/bitsdojo_window.dart';
|
|||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/pods/websocket.dart';
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/route.dart';
|
import 'package:island/route.dart';
|
||||||
|
|
||||||
import 'package:island/services/notify.dart';
|
import 'package:island/services/notify.dart';
|
||||||
import 'package:island/services/timezone.dart';
|
import 'package:island/services/timezone.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
@@ -30,6 +29,7 @@ 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 {
|
||||||
@@ -51,6 +51,7 @@ void main() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
|
await langdetect.initLangDetect();
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
await Firebase.initializeApp(
|
await Firebase.initializeApp(
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
|
|||||||
@@ -162,8 +162,6 @@ sealed class CallParticipant with _$CallParticipant {
|
|||||||
required String identity,
|
required String identity,
|
||||||
required String name,
|
required String name,
|
||||||
required DateTime joinedAt,
|
required DateTime joinedAt,
|
||||||
required String? accountId,
|
|
||||||
required SnChatMember? profile,
|
|
||||||
}) = _CallParticipant;
|
}) = _CallParticipant;
|
||||||
|
|
||||||
factory CallParticipant.fromJson(Map<String, dynamic> json) =>
|
factory CallParticipant.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -2498,7 +2498,7 @@ as List<CallParticipant>,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$CallParticipant {
|
mixin _$CallParticipant {
|
||||||
|
|
||||||
String get identity; String get name; DateTime get joinedAt; String? get accountId; SnChatMember? get profile;
|
String get identity; String get name; DateTime get joinedAt;
|
||||||
/// Create a copy of CallParticipant
|
/// Create a copy of CallParticipant
|
||||||
/// 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)
|
||||||
@@ -2511,16 +2511,16 @@ $CallParticipantCopyWith<CallParticipant> get copyWith => _$CallParticipantCopyW
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallParticipant&&(identical(other.identity, identity) || other.identity == identity)&&(identical(other.name, name) || other.name == name)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.profile, profile) || other.profile == profile));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallParticipant&&(identical(other.identity, identity) || other.identity == identity)&&(identical(other.name, name) || other.name == name)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,identity,name,joinedAt,accountId,profile);
|
int get hashCode => Object.hash(runtimeType,identity,name,joinedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt, accountId: $accountId, profile: $profile)';
|
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2531,11 +2531,11 @@ abstract mixin class $CallParticipantCopyWith<$Res> {
|
|||||||
factory $CallParticipantCopyWith(CallParticipant value, $Res Function(CallParticipant) _then) = _$CallParticipantCopyWithImpl;
|
factory $CallParticipantCopyWith(CallParticipant value, $Res Function(CallParticipant) _then) = _$CallParticipantCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile
|
String identity, String name, DateTime joinedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnChatMemberCopyWith<$Res>? get profile;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -2548,29 +2548,15 @@ class _$CallParticipantCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of CallParticipant
|
/// Create a copy of CallParticipant
|
||||||
/// 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? identity = null,Object? name = null,Object? joinedAt = null,Object? accountId = freezed,Object? profile = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? identity = null,Object? name = null,Object? joinedAt = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
identity: null == identity ? _self.identity : identity // ignore: cast_nullable_to_non_nullable
|
identity: null == identity ? _self.identity : identity // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,joinedAt: null == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
as String,joinedAt: null == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as DateTime,
|
||||||
as String?,profile: freezed == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnChatMember?,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of CallParticipant
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnChatMemberCopyWith<$Res>? get profile {
|
|
||||||
if (_self.profile == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $SnChatMemberCopyWith<$Res>(_self.profile!, (value) {
|
|
||||||
return _then(_self.copyWith(profile: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2649,10 +2635,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String identity, String name, DateTime joinedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _CallParticipant() when $default != null:
|
case _CallParticipant() when $default != null:
|
||||||
return $default(_that.identity,_that.name,_that.joinedAt,_that.accountId,_that.profile);case _:
|
return $default(_that.identity,_that.name,_that.joinedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2670,10 +2656,10 @@ return $default(_that.identity,_that.name,_that.joinedAt,_that.accountId,_that.p
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String identity, String name, DateTime joinedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _CallParticipant():
|
case _CallParticipant():
|
||||||
return $default(_that.identity,_that.name,_that.joinedAt,_that.accountId,_that.profile);}
|
return $default(_that.identity,_that.name,_that.joinedAt);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -2687,10 +2673,10 @@ return $default(_that.identity,_that.name,_that.joinedAt,_that.accountId,_that.p
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String identity, String name, DateTime joinedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _CallParticipant() when $default != null:
|
case _CallParticipant() when $default != null:
|
||||||
return $default(_that.identity,_that.name,_that.joinedAt,_that.accountId,_that.profile);case _:
|
return $default(_that.identity,_that.name,_that.joinedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2702,14 +2688,12 @@ return $default(_that.identity,_that.name,_that.joinedAt,_that.accountId,_that.p
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _CallParticipant implements CallParticipant {
|
class _CallParticipant implements CallParticipant {
|
||||||
const _CallParticipant({required this.identity, required this.name, required this.joinedAt, required this.accountId, required this.profile});
|
const _CallParticipant({required this.identity, required this.name, required this.joinedAt});
|
||||||
factory _CallParticipant.fromJson(Map<String, dynamic> json) => _$CallParticipantFromJson(json);
|
factory _CallParticipant.fromJson(Map<String, dynamic> json) => _$CallParticipantFromJson(json);
|
||||||
|
|
||||||
@override final String identity;
|
@override final String identity;
|
||||||
@override final String name;
|
@override final String name;
|
||||||
@override final DateTime joinedAt;
|
@override final DateTime joinedAt;
|
||||||
@override final String? accountId;
|
|
||||||
@override final SnChatMember? profile;
|
|
||||||
|
|
||||||
/// Create a copy of CallParticipant
|
/// Create a copy of CallParticipant
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -2724,16 +2708,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallParticipant&&(identical(other.identity, identity) || other.identity == identity)&&(identical(other.name, name) || other.name == name)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.profile, profile) || other.profile == profile));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallParticipant&&(identical(other.identity, identity) || other.identity == identity)&&(identical(other.name, name) || other.name == name)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,identity,name,joinedAt,accountId,profile);
|
int get hashCode => Object.hash(runtimeType,identity,name,joinedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt, accountId: $accountId, profile: $profile)';
|
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2744,11 +2728,11 @@ abstract mixin class _$CallParticipantCopyWith<$Res> implements $CallParticipant
|
|||||||
factory _$CallParticipantCopyWith(_CallParticipant value, $Res Function(_CallParticipant) _then) = __$CallParticipantCopyWithImpl;
|
factory _$CallParticipantCopyWith(_CallParticipant value, $Res Function(_CallParticipant) _then) = __$CallParticipantCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile
|
String identity, String name, DateTime joinedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnChatMemberCopyWith<$Res>? get profile;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -2761,30 +2745,16 @@ class __$CallParticipantCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of CallParticipant
|
/// Create a copy of CallParticipant
|
||||||
/// 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? identity = null,Object? name = null,Object? joinedAt = null,Object? accountId = freezed,Object? profile = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? identity = null,Object? name = null,Object? joinedAt = null,}) {
|
||||||
return _then(_CallParticipant(
|
return _then(_CallParticipant(
|
||||||
identity: null == identity ? _self.identity : identity // ignore: cast_nullable_to_non_nullable
|
identity: null == identity ? _self.identity : identity // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,joinedAt: null == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
as String,joinedAt: null == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as DateTime,
|
||||||
as String?,profile: freezed == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnChatMember?,
|
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of CallParticipant
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnChatMemberCopyWith<$Res>? get profile {
|
|
||||||
if (_self.profile == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $SnChatMemberCopyWith<$Res>(_self.profile!, (value) {
|
|
||||||
return _then(_self.copyWith(profile: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -285,11 +285,6 @@ _CallParticipant _$CallParticipantFromJson(Map<String, dynamic> json) =>
|
|||||||
identity: json['identity'] as String,
|
identity: json['identity'] as String,
|
||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
joinedAt: DateTime.parse(json['joined_at'] as String),
|
joinedAt: DateTime.parse(json['joined_at'] as String),
|
||||||
accountId: json['account_id'] as String?,
|
|
||||||
profile:
|
|
||||||
json['profile'] == null
|
|
||||||
? null
|
|
||||||
: SnChatMember.fromJson(json['profile'] as Map<String, dynamic>),
|
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$CallParticipantToJson(_CallParticipant instance) =>
|
Map<String, dynamic> _$CallParticipantToJson(_CallParticipant instance) =>
|
||||||
@@ -297,8 +292,6 @@ Map<String, dynamic> _$CallParticipantToJson(_CallParticipant instance) =>
|
|||||||
'identity': instance.identity,
|
'identity': instance.identity,
|
||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'joined_at': instance.joinedAt.toIso8601String(),
|
'joined_at': instance.joinedAt.toIso8601String(),
|
||||||
'account_id': instance.accountId,
|
|
||||||
'profile': instance.profile?.toJson(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_SnRealtimeCall _$SnRealtimeCallFromJson(Map<String, dynamic> json) =>
|
_SnRealtimeCall _$SnRealtimeCallFromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -34,6 +34,7 @@ sealed class SnPost with _$SnPost {
|
|||||||
@Default([]) List<SnCloudFile> attachments,
|
@Default([]) List<SnCloudFile> attachments,
|
||||||
required SnPublisher publisher,
|
required SnPublisher publisher,
|
||||||
@Default({}) Map<String, int> reactionsCount,
|
@Default({}) Map<String, int> reactionsCount,
|
||||||
|
@Default({}) Map<String, bool> reactionsMade,
|
||||||
@Default([]) List<dynamic> reactions,
|
@Default([]) List<dynamic> reactions,
|
||||||
@Default([]) List<PostTag> tags,
|
@Default([]) List<PostTag> tags,
|
||||||
@Default([]) List<PostCategory> categories,
|
@Default([]) List<PostCategory> categories,
|
||||||
@@ -77,6 +78,13 @@ sealed class SnSubscriptionStatus with _$SnSubscriptionStatus {
|
|||||||
sealed class ReactInfo with _$ReactInfo {
|
sealed class ReactInfo with _$ReactInfo {
|
||||||
const factory ReactInfo({required String icon, required int attitude}) =
|
const factory ReactInfo({required String icon, required int attitude}) =
|
||||||
_ReactInfo;
|
_ReactInfo;
|
||||||
|
|
||||||
|
static String getTranslationKey(String templateKey) {
|
||||||
|
final parts = templateKey.split('_');
|
||||||
|
final camelCase =
|
||||||
|
parts.map((p) => p[0].toUpperCase() + p.substring(1)).join();
|
||||||
|
return 'reaction$camelCase';
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
const Map<String, ReactInfo> kReactionTemplates = {
|
const Map<String, ReactInfo> kReactionTemplates = {
|
||||||
|
|||||||
@@ -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; 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; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; List<dynamic> get reactions; List<PostTag> get tags; List<PostCategory> 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; 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; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<PostTag> get tags; List<PostCategory> 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.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)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&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.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)&&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,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),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,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,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, 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, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, 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, 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, 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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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? 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? attachments = null,Object? publisher = null,Object? reactionsCount = 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? 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? 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
|
||||||
@@ -91,7 +91,8 @@ as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwa
|
|||||||
as SnPost?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as SnPost?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, int>,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable
|
as Map<String, int>,reactionsMade: null == reactionsMade ? _self.reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable
|
||||||
as List<PostTag>,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable
|
as List<PostTag>,categories: null == categories ? _self.categories : categories // ignore: cast_nullable_to_non_nullable
|
||||||
as List<PostCategory>,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable
|
as List<PostCategory>,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -226,10 +227,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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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.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.attachments,_that.publisher,_that.reactionsCount,_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.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.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();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -247,10 +248,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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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.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.attachments,_that.publisher,_that.reactionsCount,_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.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.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`
|
||||||
///
|
///
|
||||||
@@ -264,10 +265,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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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.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.attachments,_that.publisher,_that.reactionsCount,_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.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.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;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -279,7 +280,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.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, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final List<dynamic> reactions = const [], final List<PostTag> tags = const [], final List<PostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_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.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, 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<PostTag> tags = const [], final List<PostCategory> 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;
|
||||||
@@ -326,6 +327,13 @@ class _SnPost implements SnPost {
|
|||||||
return EqualUnmodifiableMapView(_reactionsCount);
|
return EqualUnmodifiableMapView(_reactionsCount);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final Map<String, bool> _reactionsMade;
|
||||||
|
@override@JsonKey() Map<String, bool> get reactionsMade {
|
||||||
|
if (_reactionsMade is EqualUnmodifiableMapView) return _reactionsMade;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_reactionsMade);
|
||||||
|
}
|
||||||
|
|
||||||
final List<dynamic> _reactions;
|
final List<dynamic> _reactions;
|
||||||
@override@JsonKey() List<dynamic> get reactions {
|
@override@JsonKey() List<dynamic> get reactions {
|
||||||
if (_reactions is EqualUnmodifiableListView) return _reactions;
|
if (_reactions is EqualUnmodifiableListView) return _reactions;
|
||||||
@@ -372,16 +380,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.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)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&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.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)&&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,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),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,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,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, 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, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, 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, 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, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -392,7 +400,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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> 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, 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, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<PostTag> tags, List<PostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -409,7 +417,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? 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? attachments = null,Object? publisher = null,Object? reactionsCount = 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? 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? 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
|
||||||
@@ -435,7 +443,8 @@ as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwa
|
|||||||
as SnPost?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as SnPost?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, int>,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable
|
as Map<String, int>,reactionsMade: null == reactionsMade ? _self._reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, bool>,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable
|
||||||
as List<PostTag>,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable
|
as List<PostTag>,categories: null == categories ? _self._categories : categories // ignore: cast_nullable_to_non_nullable
|
||||||
as List<PostCategory>,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable
|
as List<PostCategory>,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable
|
||||||
|
|||||||
@@ -54,6 +54,11 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
|||||||
(k, e) => MapEntry(k, (e as num).toInt()),
|
(k, e) => MapEntry(k, (e as num).toInt()),
|
||||||
) ??
|
) ??
|
||||||
const {},
|
const {},
|
||||||
|
reactionsMade:
|
||||||
|
(json['reactions_made'] as Map<String, dynamic>?)?.map(
|
||||||
|
(k, e) => MapEntry(k, e as bool),
|
||||||
|
) ??
|
||||||
|
const {},
|
||||||
reactions: json['reactions'] as List<dynamic>? ?? const [],
|
reactions: json['reactions'] as List<dynamic>? ?? const [],
|
||||||
tags:
|
tags:
|
||||||
(json['tags'] as List<dynamic>?)
|
(json['tags'] as List<dynamic>?)
|
||||||
@@ -106,6 +111,7 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
|||||||
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
||||||
'publisher': instance.publisher.toJson(),
|
'publisher': instance.publisher.toJson(),
|
||||||
'reactions_count': instance.reactionsCount,
|
'reactions_count': instance.reactionsCount,
|
||||||
|
'reactions_made': instance.reactionsMade,
|
||||||
'reactions': instance.reactions,
|
'reactions': instance.reactions,
|
||||||
'tags': instance.tags.map((e) => e.toJson()).toList(),
|
'tags': instance.tags.map((e) => e.toJson()).toList(),
|
||||||
'categories': instance.categories.map((e) => e.toJson()).toList(),
|
'categories': instance.categories.map((e) => e.toJson()).toList(),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ sealed class SnAccount with _$SnAccount {
|
|||||||
required String language,
|
required String language,
|
||||||
required bool isSuperuser,
|
required bool isSuperuser,
|
||||||
required SnAccountProfile profile,
|
required SnAccountProfile profile,
|
||||||
|
required SnWalletSubscriptionRef? perkSubscription,
|
||||||
@Default([]) List<SnAccountBadge> badges,
|
@Default([]) List<SnAccountBadge> badges,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
@@ -45,7 +46,6 @@ sealed class SnAccountProfile with _$SnAccountProfile {
|
|||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
required SnVerificationMark? verification,
|
required SnVerificationMark? verification,
|
||||||
required SnWalletSubscriptionRef? stellarMembership,
|
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAccount {
|
mixin _$SnAccount {
|
||||||
|
|
||||||
String get id; String get name; String get nick; String get language; bool get isSuperuser; SnAccountProfile get profile; List<SnAccountBadge> get badges; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String get name; String get nick; String get language; bool get isSuperuser; SnAccountProfile get profile; SnWalletSubscriptionRef? get perkSubscription; List<SnAccountBadge> get badges; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnAccount
|
/// Create a copy of SnAccount
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -28,16 +28,16 @@ $SnAccountCopyWith<SnAccount> get copyWith => _$SnAccountCopyWithImpl<SnAccount>
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&const DeepCollectionEquality().equals(other.badges, badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other.badges, badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,const DeepCollectionEquality().hash(badges),createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,perkSubscription,const DeepCollectionEquality().hash(badges),createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -48,11 +48,11 @@ abstract mixin class $SnAccountCopyWith<$Res> {
|
|||||||
factory $SnAccountCopyWith(SnAccount value, $Res Function(SnAccount) _then) = _$SnAccountCopyWithImpl;
|
factory $SnAccountCopyWith(SnAccount value, $Res Function(SnAccount) _then) = _$SnAccountCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnAccountProfileCopyWith<$Res> get profile;
|
$SnAccountProfileCopyWith<$Res> get profile;$SnWalletSubscriptionRefCopyWith<$Res>? get perkSubscription;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -65,7 +65,7 @@ class _$SnAccountCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccount
|
/// Create a copy of SnAccount
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? isSuperuser = null,Object? profile = null,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? isSuperuser = null,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -73,7 +73,8 @@ as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non
|
|||||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||||
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
as bool,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccountProfile,badges: null == badges ? _self.badges : badges // ignore: cast_nullable_to_non_nullable
|
as SnAccountProfile,perkSubscription: freezed == perkSubscription ? _self.perkSubscription : perkSubscription // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnWalletSubscriptionRef?,badges: null == badges ? _self.badges : badges // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnAccountBadge>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as List<SnAccountBadge>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -89,6 +90,18 @@ $SnAccountProfileCopyWith<$Res> get profile {
|
|||||||
return $SnAccountProfileCopyWith<$Res>(_self.profile, (value) {
|
return $SnAccountProfileCopyWith<$Res>(_self.profile, (value) {
|
||||||
return _then(_self.copyWith(profile: value));
|
return _then(_self.copyWith(profile: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnAccount
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnWalletSubscriptionRefCopyWith<$Res>? get perkSubscription {
|
||||||
|
if (_self.perkSubscription == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnWalletSubscriptionRefCopyWith<$Res>(_self.perkSubscription!, (value) {
|
||||||
|
return _then(_self.copyWith(perkSubscription: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -168,10 +181,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccount() when $default != null:
|
case _SnAccount() when $default != null:
|
||||||
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.profile,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -189,10 +202,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccount():
|
case _SnAccount():
|
||||||
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.profile,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -206,10 +219,10 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAccount() when $default != null:
|
case _SnAccount() when $default != null:
|
||||||
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.profile,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,_that.profile,_that.perkSubscription,_that.badges,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -221,7 +234,7 @@ return $default(_that.id,_that.name,_that.nick,_that.language,_that.isSuperuser,
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnAccount implements SnAccount {
|
class _SnAccount implements SnAccount {
|
||||||
const _SnAccount({required this.id, required this.name, required this.nick, required this.language, required this.isSuperuser, required this.profile, final List<SnAccountBadge> badges = const [], required this.createdAt, required this.updatedAt, required this.deletedAt}): _badges = badges;
|
const _SnAccount({required this.id, required this.name, required this.nick, required this.language, required this.isSuperuser, required this.profile, required this.perkSubscription, final List<SnAccountBadge> badges = const [], required this.createdAt, required this.updatedAt, required this.deletedAt}): _badges = badges;
|
||||||
factory _SnAccount.fromJson(Map<String, dynamic> json) => _$SnAccountFromJson(json);
|
factory _SnAccount.fromJson(Map<String, dynamic> json) => _$SnAccountFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -230,6 +243,7 @@ class _SnAccount implements SnAccount {
|
|||||||
@override final String language;
|
@override final String language;
|
||||||
@override final bool isSuperuser;
|
@override final bool isSuperuser;
|
||||||
@override final SnAccountProfile profile;
|
@override final SnAccountProfile profile;
|
||||||
|
@override final SnWalletSubscriptionRef? perkSubscription;
|
||||||
final List<SnAccountBadge> _badges;
|
final List<SnAccountBadge> _badges;
|
||||||
@override@JsonKey() List<SnAccountBadge> get badges {
|
@override@JsonKey() List<SnAccountBadge> get badges {
|
||||||
if (_badges is EqualUnmodifiableListView) return _badges;
|
if (_badges is EqualUnmodifiableListView) return _badges;
|
||||||
@@ -254,16 +268,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&const DeepCollectionEquality().equals(other._badges, _badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccount&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.language, language) || other.language == language)&&(identical(other.isSuperuser, isSuperuser) || other.isSuperuser == isSuperuser)&&(identical(other.profile, profile) || other.profile == profile)&&(identical(other.perkSubscription, perkSubscription) || other.perkSubscription == perkSubscription)&&const DeepCollectionEquality().equals(other._badges, _badges)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,const DeepCollectionEquality().hash(_badges),createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,nick,language,isSuperuser,profile,perkSubscription,const DeepCollectionEquality().hash(_badges),createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccount(id: $id, name: $name, nick: $nick, language: $language, isSuperuser: $isSuperuser, profile: $profile, perkSubscription: $perkSubscription, badges: $badges, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -274,11 +288,11 @@ abstract mixin class _$SnAccountCopyWith<$Res> implements $SnAccountCopyWith<$Re
|
|||||||
factory _$SnAccountCopyWith(_SnAccount value, $Res Function(_SnAccount) _then) = __$SnAccountCopyWithImpl;
|
factory _$SnAccountCopyWith(_SnAccount value, $Res Function(_SnAccount) _then) = __$SnAccountCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String nick, String language, bool isSuperuser, SnAccountProfile profile, SnWalletSubscriptionRef? perkSubscription, List<SnAccountBadge> badges, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnAccountProfileCopyWith<$Res> get profile;
|
@override $SnAccountProfileCopyWith<$Res> get profile;@override $SnWalletSubscriptionRefCopyWith<$Res>? get perkSubscription;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -291,7 +305,7 @@ class __$SnAccountCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccount
|
/// Create a copy of SnAccount
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? isSuperuser = null,Object? profile = null,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? nick = null,Object? language = null,Object? isSuperuser = null,Object? profile = null,Object? perkSubscription = freezed,Object? badges = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnAccount(
|
return _then(_SnAccount(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -299,7 +313,8 @@ as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non
|
|||||||
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
as String,language: null == language ? _self.language : language // ignore: cast_nullable_to_non_nullable
|
||||||
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
as String,isSuperuser: null == isSuperuser ? _self.isSuperuser : isSuperuser // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
as bool,profile: null == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccountProfile,badges: null == badges ? _self._badges : badges // ignore: cast_nullable_to_non_nullable
|
as SnAccountProfile,perkSubscription: freezed == perkSubscription ? _self.perkSubscription : perkSubscription // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnWalletSubscriptionRef?,badges: null == badges ? _self._badges : badges // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnAccountBadge>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as List<SnAccountBadge>,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -316,6 +331,18 @@ $SnAccountProfileCopyWith<$Res> get profile {
|
|||||||
return $SnAccountProfileCopyWith<$Res>(_self.profile, (value) {
|
return $SnAccountProfileCopyWith<$Res>(_self.profile, (value) {
|
||||||
return _then(_self.copyWith(profile: value));
|
return _then(_self.copyWith(profile: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnAccount
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnWalletSubscriptionRefCopyWith<$Res>? get perkSubscription {
|
||||||
|
if (_self.perkSubscription == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnWalletSubscriptionRefCopyWith<$Res>(_self.perkSubscription!, (value) {
|
||||||
|
return _then(_self.copyWith(perkSubscription: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -323,7 +350,7 @@ $SnAccountProfileCopyWith<$Res> get profile {
|
|||||||
/// @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; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; SnWalletSubscriptionRef? get stellarMembership; 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; 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;
|
||||||
/// 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)
|
||||||
@@ -336,16 +363,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)&&(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.stellarMembership, stellarMembership) || other.stellarMembership == stellarMembership)&&(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)&&(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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@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,lastSeenAt,activeBadge,experience,level,levelingProgress,picture,background,verification,stellarMembership,createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,lastSeenAt,activeBadge,experience,level,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, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, stellarMembership: $stellarMembership, 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, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -356,11 +383,11 @@ 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, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, SnWalletSubscriptionRef? stellarMembership, 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, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnAccountBadgeCopyWith<$Res>? get activeBadge;$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;$SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership;
|
$SnAccountBadgeCopyWith<$Res>? get activeBadge;$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -373,7 +400,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? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? stellarMembership = 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? 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,}) {
|
||||||
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
|
||||||
@@ -393,8 +420,7 @@ as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : lev
|
|||||||
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
|
||||||
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||||
as SnVerificationMark?,stellarMembership: freezed == stellarMembership ? _self.stellarMembership : stellarMembership // ignore: cast_nullable_to_non_nullable
|
as SnVerificationMark?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as SnWalletSubscriptionRef?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -448,18 +474,6 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
|
|||||||
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||||
return _then(_self.copyWith(verification: value));
|
return _then(_self.copyWith(verification: value));
|
||||||
});
|
});
|
||||||
}/// Create a copy of SnAccountProfile
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership {
|
|
||||||
if (_self.stellarMembership == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $SnWalletSubscriptionRefCopyWith<$Res>(_self.stellarMembership!, (value) {
|
|
||||||
return _then(_self.copyWith(stellarMembership: value));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -539,10 +553,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, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, SnWalletSubscriptionRef? stellarMembership, 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, 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;
|
||||||
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.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.stellarMembership,_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.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -560,10 +574,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, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, SnWalletSubscriptionRef? stellarMembership, 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, 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;
|
||||||
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.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.stellarMembership,_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.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_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`
|
||||||
///
|
///
|
||||||
@@ -577,10 +591,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, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, SnWalletSubscriptionRef? stellarMembership, 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, 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;
|
||||||
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.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.stellarMembership,_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.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -592,7 +606,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, this.lastSeenAt, this.activeBadge, required this.experience, required this.level, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.stellarMembership, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
const _SnAccountProfile({required this.id, this.firstName = '', this.middleName = '', this.lastName = '', this.bio = '', this.gender = '', this.pronouns = '', this.location = '', this.timeZone = '', this.birthday, 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});
|
||||||
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;
|
||||||
@@ -613,7 +627,6 @@ class _SnAccountProfile implements SnAccountProfile {
|
|||||||
@override final SnCloudFile? picture;
|
@override final SnCloudFile? picture;
|
||||||
@override final SnCloudFile? background;
|
@override final SnCloudFile? background;
|
||||||
@override final SnVerificationMark? verification;
|
@override final SnVerificationMark? verification;
|
||||||
@override final SnWalletSubscriptionRef? stellarMembership;
|
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
@@ -631,16 +644,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)&&(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.stellarMembership, stellarMembership) || other.stellarMembership == stellarMembership)&&(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)&&(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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@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,lastSeenAt,activeBadge,experience,level,levelingProgress,picture,background,verification,stellarMembership,createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,lastSeenAt,activeBadge,experience,level,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, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, stellarMembership: $stellarMembership, 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, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -651,11 +664,11 @@ 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, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, SnWalletSubscriptionRef? stellarMembership, 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, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnAccountBadgeCopyWith<$Res>? get activeBadge;@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;@override $SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership;
|
@override $SnAccountBadgeCopyWith<$Res>? get activeBadge;@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -668,7 +681,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? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? stellarMembership = 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? 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,}) {
|
||||||
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
|
||||||
@@ -688,8 +701,7 @@ as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : lev
|
|||||||
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
|
||||||
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||||
as SnVerificationMark?,stellarMembership: freezed == stellarMembership ? _self.stellarMembership : stellarMembership // ignore: cast_nullable_to_non_nullable
|
as SnVerificationMark?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as SnWalletSubscriptionRef?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -744,18 +756,6 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
|
|||||||
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||||
return _then(_self.copyWith(verification: value));
|
return _then(_self.copyWith(verification: value));
|
||||||
});
|
});
|
||||||
}/// Create a copy of SnAccountProfile
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnWalletSubscriptionRefCopyWith<$Res>? get stellarMembership {
|
|
||||||
if (_self.stellarMembership == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $SnWalletSubscriptionRefCopyWith<$Res>(_self.stellarMembership!, (value) {
|
|
||||||
return _then(_self.copyWith(stellarMembership: value));
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -13,6 +13,12 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
|||||||
language: json['language'] as String,
|
language: json['language'] as String,
|
||||||
isSuperuser: json['is_superuser'] as bool,
|
isSuperuser: json['is_superuser'] as bool,
|
||||||
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
||||||
|
perkSubscription:
|
||||||
|
json['perk_subscription'] == null
|
||||||
|
? null
|
||||||
|
: SnWalletSubscriptionRef.fromJson(
|
||||||
|
json['perk_subscription'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
badges:
|
badges:
|
||||||
(json['badges'] as List<dynamic>?)
|
(json['badges'] as List<dynamic>?)
|
||||||
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
||||||
@@ -34,6 +40,7 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
|||||||
'language': instance.language,
|
'language': instance.language,
|
||||||
'is_superuser': instance.isSuperuser,
|
'is_superuser': instance.isSuperuser,
|
||||||
'profile': instance.profile.toJson(),
|
'profile': instance.profile.toJson(),
|
||||||
|
'perk_subscription': instance.perkSubscription?.toJson(),
|
||||||
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
@@ -84,12 +91,6 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
|||||||
: SnVerificationMark.fromJson(
|
: SnVerificationMark.fromJson(
|
||||||
json['verification'] as Map<String, dynamic>,
|
json['verification'] as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
stellarMembership:
|
|
||||||
json['stellar_membership'] == null
|
|
||||||
? null
|
|
||||||
: SnWalletSubscriptionRef.fromJson(
|
|
||||||
json['stellar_membership'] as Map<String, dynamic>,
|
|
||||||
),
|
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
deletedAt:
|
deletedAt:
|
||||||
@@ -118,7 +119,6 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
|||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
'verification': instance.verification?.toJson(),
|
'verification': instance.verification?.toJson(),
|
||||||
'stellar_membership': instance.stellarMembership?.toJson(),
|
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
|||||||
@@ -4,13 +4,13 @@ import 'package:island/models/webfeed.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
|
||||||
/// Provider that fetches a single article by its ID
|
/// Provider that fetches a single article by its ID
|
||||||
final articleDetailProvider = FutureProvider.autoDispose.family<SnWebArticle, String>(
|
final articleDetailProvider = FutureProvider.autoDispose
|
||||||
(ref, articleId) async {
|
.family<SnWebArticle, String>((ref, articleId) async {
|
||||||
final dio = ref.watch(apiClientProvider);
|
final dio = ref.watch(apiClientProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = await dio.get<Map<String, dynamic>>(
|
final response = await dio.get<Map<String, dynamic>>(
|
||||||
'/feeds/articles/$articleId',
|
'/sphere/feeds/articles/$articleId',
|
||||||
);
|
);
|
||||||
|
|
||||||
if (response.statusCode == 200 && response.data != null) {
|
if (response.statusCode == 200 && response.data != null) {
|
||||||
@@ -27,5 +27,4 @@ final articleDetailProvider = FutureProvider.autoDispose.family<SnWebArticle, St
|
|||||||
} catch (e) {
|
} catch (e) {
|
||||||
throw Exception('Failed to load article: $e');
|
throw Exception('Failed to load article: $e');
|
||||||
}
|
}
|
||||||
},
|
});
|
||||||
);
|
|
||||||
|
|||||||
@@ -1,13 +1,10 @@
|
|||||||
import 'package:island/pods/userinfo.dart';
|
import 'dart:async';
|
||||||
import 'package:island/screens/chat/chat.dart';
|
|
||||||
import 'package:island/widgets/chat/call_button.dart';
|
import 'package:island/widgets/chat/call_button.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'dart:async';
|
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:island/pods/websocket.dart';
|
|
||||||
|
|
||||||
part 'call.g.dart';
|
part 'call.g.dart';
|
||||||
part 'call.freezed.dart';
|
part 'call.freezed.dart';
|
||||||
@@ -42,7 +39,8 @@ sealed class CallParticipantLive with _$CallParticipantLive {
|
|||||||
}) = _CallParticipantLive;
|
}) = _CallParticipantLive;
|
||||||
|
|
||||||
bool get isSpeaking => remoteParticipant.isSpeaking;
|
bool get isSpeaking => remoteParticipant.isSpeaking;
|
||||||
bool get isMuted => remoteParticipant.isMuted;
|
bool get isMuted =>
|
||||||
|
remoteParticipant.isMuted || !remoteParticipant.isMicrophoneEnabled();
|
||||||
bool get isScreenSharing => remoteParticipant.isScreenShareEnabled();
|
bool get isScreenSharing => remoteParticipant.isScreenShareEnabled();
|
||||||
bool get isScreenSharingWithAudio =>
|
bool get isScreenSharingWithAudio =>
|
||||||
remoteParticipant.isScreenShareAudioEnabled();
|
remoteParticipant.isScreenShareAudioEnabled();
|
||||||
@@ -57,7 +55,6 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
LocalParticipant? _localParticipant;
|
LocalParticipant? _localParticipant;
|
||||||
List<CallParticipantLive> _participants = [];
|
List<CallParticipantLive> _participants = [];
|
||||||
final Map<String, CallParticipant> _participantInfoByIdentity = {};
|
final Map<String, CallParticipant> _participantInfoByIdentity = {};
|
||||||
StreamSubscription? _wsSubscription;
|
|
||||||
EventsListener? _roomListener;
|
EventsListener? _roomListener;
|
||||||
|
|
||||||
List<CallParticipantLive> get participants =>
|
List<CallParticipantLive> get participants =>
|
||||||
@@ -71,7 +68,6 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
@override
|
@override
|
||||||
CallState build() {
|
CallState build() {
|
||||||
// Subscribe to websocket updates
|
// Subscribe to websocket updates
|
||||||
_subscribeToParticipantsUpdate();
|
|
||||||
return const CallState(
|
return const CallState(
|
||||||
isConnected: false,
|
isConnected: false,
|
||||||
isMicrophoneEnabled: true,
|
isMicrophoneEnabled: true,
|
||||||
@@ -80,27 +76,6 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
void _subscribeToParticipantsUpdate() {
|
|
||||||
// Only subscribe once
|
|
||||||
if (_wsSubscription != null) return;
|
|
||||||
final ws = ref.read(websocketProvider);
|
|
||||||
_wsSubscription = ws.dataStream.listen((packet) {
|
|
||||||
if (packet.type == 'call.participants.update' && packet.data != null) {
|
|
||||||
final participantsData = packet.data!["participants"];
|
|
||||||
if (participantsData is List) {
|
|
||||||
final parsed =
|
|
||||||
participantsData
|
|
||||||
.map(
|
|
||||||
(e) =>
|
|
||||||
CallParticipant.fromJson(Map<String, dynamic>.from(e)),
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
_updateLiveParticipants(parsed);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
void _initRoomListeners() {
|
void _initRoomListeners() {
|
||||||
if (_room == null) return;
|
if (_room == null) return;
|
||||||
_roomListener?.dispose();
|
_roomListener?.dispose();
|
||||||
@@ -143,8 +118,6 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
identity: remote.identity,
|
identity: remote.identity,
|
||||||
name: remote.identity,
|
name: remote.identity,
|
||||||
joinedAt: DateTime.now(),
|
joinedAt: DateTime.now(),
|
||||||
accountId: null,
|
|
||||||
profile: null,
|
|
||||||
);
|
);
|
||||||
return CallParticipantLive(
|
return CallParticipantLive(
|
||||||
participant: match,
|
participant: match,
|
||||||
@@ -169,16 +142,12 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
if (idx != -1) return participants[idx];
|
if (idx != -1) return participants[idx];
|
||||||
}
|
}
|
||||||
|
|
||||||
final userInfo = ref.read(userInfoProvider);
|
|
||||||
final roomIdentity = ref.read(chatroomIdentityProvider(_roomId));
|
|
||||||
// Otherwise, use info from the identity map or fallback to minimal
|
// Otherwise, use info from the identity map or fallback to minimal
|
||||||
return _participantInfoByIdentity[_localParticipant!.identity] ??
|
return _participantInfoByIdentity[_localParticipant!.identity] ??
|
||||||
CallParticipant(
|
CallParticipant(
|
||||||
identity: _localParticipant!.identity,
|
identity: _localParticipant!.identity,
|
||||||
name: _localParticipant!.identity,
|
name: _localParticipant!.identity,
|
||||||
joinedAt: DateTime.now(),
|
joinedAt: DateTime.now(),
|
||||||
accountId: userInfo.value?.id,
|
|
||||||
profile: roomIdentity.value,
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -205,6 +174,7 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
remoteParticipant: _localParticipant!,
|
remoteParticipant: _localParticipant!,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
state = state.copyWith();
|
||||||
}
|
}
|
||||||
// Add remote participants
|
// Add remote participants
|
||||||
_participants.addAll(
|
_participants.addAll(
|
||||||
@@ -264,7 +234,8 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
duration: Duration(
|
duration: Duration(
|
||||||
milliseconds:
|
milliseconds:
|
||||||
(DateTime.now().millisecondsSinceEpoch -
|
(DateTime.now().millisecondsSinceEpoch -
|
||||||
(ongoingCall?.createdAt.millisecondsSinceEpoch ?? 0)),
|
(ongoingCall?.createdAt.millisecondsSinceEpoch ??
|
||||||
|
DateTime.now().millisecondsSinceEpoch)),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
@@ -318,6 +289,7 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
stopOnMute: autostop,
|
stopOnMute: autostop,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
state = state.copyWith();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,6 +298,7 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
final target = !_localParticipant!.isCameraEnabled();
|
final target = !_localParticipant!.isCameraEnabled();
|
||||||
state = state.copyWith(isCameraEnabled: target);
|
state = state.copyWith(isCameraEnabled: target);
|
||||||
await _localParticipant!.setCameraEnabled(target);
|
await _localParticipant!.setCameraEnabled(target);
|
||||||
|
state = state.copyWith();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -334,6 +307,7 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
final target = !_localParticipant!.isScreenShareEnabled();
|
final target = !_localParticipant!.isScreenShareEnabled();
|
||||||
state = state.copyWith(isScreenSharing: target);
|
state = state.copyWith(isScreenSharing: target);
|
||||||
await _localParticipant!.setScreenShareEnabled(target);
|
await _localParticipant!.setScreenShareEnabled(target);
|
||||||
|
state = state.copyWith();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -350,7 +324,13 @@ class CallNotifier extends _$CallNotifier {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void dispose() {
|
void dispose() {
|
||||||
_wsSubscription?.cancel();
|
state = state.copyWith(
|
||||||
|
error: null,
|
||||||
|
isConnected: false,
|
||||||
|
isMicrophoneEnabled: false,
|
||||||
|
isCameraEnabled: false,
|
||||||
|
isScreenSharing: false,
|
||||||
|
);
|
||||||
_roomListener?.dispose();
|
_roomListener?.dispose();
|
||||||
_room?.removeListener(_onRoomChange);
|
_room?.removeListener(_onRoomChange);
|
||||||
_room?.dispose();
|
_room?.dispose();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part of 'call.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$callNotifierHash() => r'107174cd6cfab6bfafe44f8c4a72a67bcb93217b';
|
String _$callNotifierHash() => r'e4312feadb5b34f186b5349a7ee8b671b842dafc';
|
||||||
|
|
||||||
/// See also [CallNotifier].
|
/// See also [CallNotifier].
|
||||||
@ProviderFor(CallNotifier)
|
@ProviderFor(CallNotifier)
|
||||||
|
|||||||
38
lib/pods/translate.dart
Normal file
38
lib/pods/translate.dart
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
||||||
|
|
||||||
|
part 'translate.freezed.dart';
|
||||||
|
part 'translate.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class TranslateQuery with _$TranslateQuery {
|
||||||
|
const factory TranslateQuery({required String text, required String lang}) =
|
||||||
|
_TranslateQuery;
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<String> translateString(Ref ref, TranslateQuery query) async {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
final response = await client.post(
|
||||||
|
'/sphere/translate',
|
||||||
|
queryParameters: {'to': query.lang},
|
||||||
|
data: jsonEncode(query.text),
|
||||||
|
);
|
||||||
|
return response.data as String;
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
String? detectStringLanguage(Ref ref, String text) {
|
||||||
|
try {
|
||||||
|
return langdetect.detectLangs(text).firstOrNull?.lang;
|
||||||
|
} catch (err) {
|
||||||
|
log('[Language] Unable to detect text\'s language: $text');
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
268
lib/pods/translate.freezed.dart
Normal file
268
lib/pods/translate.freezed.dart
Normal file
@@ -0,0 +1,268 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'translate.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$TranslateQuery {
|
||||||
|
|
||||||
|
String get text; String get lang;
|
||||||
|
/// Create a copy of TranslateQuery
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$TranslateQueryCopyWith<TranslateQuery> get copyWith => _$TranslateQueryCopyWithImpl<TranslateQuery>(this as TranslateQuery, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is TranslateQuery&&(identical(other.text, text) || other.text == text)&&(identical(other.lang, lang) || other.lang == lang));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,text,lang);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'TranslateQuery(text: $text, lang: $lang)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $TranslateQueryCopyWith<$Res> {
|
||||||
|
factory $TranslateQueryCopyWith(TranslateQuery value, $Res Function(TranslateQuery) _then) = _$TranslateQueryCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String text, String lang
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$TranslateQueryCopyWithImpl<$Res>
|
||||||
|
implements $TranslateQueryCopyWith<$Res> {
|
||||||
|
_$TranslateQueryCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final TranslateQuery _self;
|
||||||
|
final $Res Function(TranslateQuery) _then;
|
||||||
|
|
||||||
|
/// Create a copy of TranslateQuery
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? text = null,Object? lang = null,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
text: null == text ? _self.text : text // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,lang: null == lang ? _self.lang : lang // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [TranslateQuery].
|
||||||
|
extension TranslateQueryPatterns on TranslateQuery {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _TranslateQuery value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _TranslateQuery() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _TranslateQuery value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _TranslateQuery():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _TranslateQuery value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _TranslateQuery() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String text, String lang)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _TranslateQuery() when $default != null:
|
||||||
|
return $default(_that.text,_that.lang);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String text, String lang) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _TranslateQuery():
|
||||||
|
return $default(_that.text,_that.lang);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String text, String lang)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _TranslateQuery() when $default != null:
|
||||||
|
return $default(_that.text,_that.lang);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _TranslateQuery implements TranslateQuery {
|
||||||
|
const _TranslateQuery({required this.text, required this.lang});
|
||||||
|
|
||||||
|
|
||||||
|
@override final String text;
|
||||||
|
@override final String lang;
|
||||||
|
|
||||||
|
/// Create a copy of TranslateQuery
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$TranslateQueryCopyWith<_TranslateQuery> get copyWith => __$TranslateQueryCopyWithImpl<_TranslateQuery>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _TranslateQuery&&(identical(other.text, text) || other.text == text)&&(identical(other.lang, lang) || other.lang == lang));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,text,lang);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'TranslateQuery(text: $text, lang: $lang)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$TranslateQueryCopyWith<$Res> implements $TranslateQueryCopyWith<$Res> {
|
||||||
|
factory _$TranslateQueryCopyWith(_TranslateQuery value, $Res Function(_TranslateQuery) _then) = __$TranslateQueryCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String text, String lang
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$TranslateQueryCopyWithImpl<$Res>
|
||||||
|
implements _$TranslateQueryCopyWith<$Res> {
|
||||||
|
__$TranslateQueryCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _TranslateQuery _self;
|
||||||
|
final $Res Function(_TranslateQuery) _then;
|
||||||
|
|
||||||
|
/// Create a copy of TranslateQuery
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? text = null,Object? lang = null,}) {
|
||||||
|
return _then(_TranslateQuery(
|
||||||
|
text: null == text ? _self.text : text // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,lang: null == lang ? _self.lang : lang // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
274
lib/pods/translate.g.dart
Normal file
274
lib/pods/translate.g.dart
Normal file
@@ -0,0 +1,274 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'translate.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$translateStringHash() => r'51d638cf07cbf3ffa9469298f5bd9c667bc0ccb7';
|
||||||
|
|
||||||
|
/// Copied from Dart SDK
|
||||||
|
class _SystemHash {
|
||||||
|
_SystemHash._();
|
||||||
|
|
||||||
|
static int combine(int hash, int value) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + value);
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||||
|
return hash ^ (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int finish(int hash) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = hash ^ (hash >> 11);
|
||||||
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [translateString].
|
||||||
|
@ProviderFor(translateString)
|
||||||
|
const translateStringProvider = TranslateStringFamily();
|
||||||
|
|
||||||
|
/// See also [translateString].
|
||||||
|
class TranslateStringFamily extends Family<AsyncValue<String>> {
|
||||||
|
/// See also [translateString].
|
||||||
|
const TranslateStringFamily();
|
||||||
|
|
||||||
|
/// See also [translateString].
|
||||||
|
TranslateStringProvider call(TranslateQuery query) {
|
||||||
|
return TranslateStringProvider(query);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
TranslateStringProvider getProviderOverride(
|
||||||
|
covariant TranslateStringProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.query);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'translateStringProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [translateString].
|
||||||
|
class TranslateStringProvider extends AutoDisposeFutureProvider<String> {
|
||||||
|
/// See also [translateString].
|
||||||
|
TranslateStringProvider(TranslateQuery query)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => translateString(ref as TranslateStringRef, query),
|
||||||
|
from: translateStringProvider,
|
||||||
|
name: r'translateStringProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$translateStringHash,
|
||||||
|
dependencies: TranslateStringFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
TranslateStringFamily._allTransitiveDependencies,
|
||||||
|
query: query,
|
||||||
|
);
|
||||||
|
|
||||||
|
TranslateStringProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.query,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final TranslateQuery query;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<String> Function(TranslateStringRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: TranslateStringProvider._internal(
|
||||||
|
(ref) => create(ref as TranslateStringRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
query: query,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<String> createElement() {
|
||||||
|
return _TranslateStringProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is TranslateStringProvider && other.query == query;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, query.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin TranslateStringRef on AutoDisposeFutureProviderRef<String> {
|
||||||
|
/// The parameter `query` of this provider.
|
||||||
|
TranslateQuery get query;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _TranslateStringProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<String>
|
||||||
|
with TranslateStringRef {
|
||||||
|
_TranslateStringProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
TranslateQuery get query => (origin as TranslateStringProvider).query;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$detectStringLanguageHash() =>
|
||||||
|
r'697b68464b3d00927cc43ccc1ba8ba93f2a470ed';
|
||||||
|
|
||||||
|
/// See also [detectStringLanguage].
|
||||||
|
@ProviderFor(detectStringLanguage)
|
||||||
|
const detectStringLanguageProvider = DetectStringLanguageFamily();
|
||||||
|
|
||||||
|
/// See also [detectStringLanguage].
|
||||||
|
class DetectStringLanguageFamily extends Family<String?> {
|
||||||
|
/// See also [detectStringLanguage].
|
||||||
|
const DetectStringLanguageFamily();
|
||||||
|
|
||||||
|
/// See also [detectStringLanguage].
|
||||||
|
DetectStringLanguageProvider call(String text) {
|
||||||
|
return DetectStringLanguageProvider(text);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
DetectStringLanguageProvider getProviderOverride(
|
||||||
|
covariant DetectStringLanguageProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.text);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'detectStringLanguageProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [detectStringLanguage].
|
||||||
|
class DetectStringLanguageProvider extends AutoDisposeProvider<String?> {
|
||||||
|
/// See also [detectStringLanguage].
|
||||||
|
DetectStringLanguageProvider(String text)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => detectStringLanguage(ref as DetectStringLanguageRef, text),
|
||||||
|
from: detectStringLanguageProvider,
|
||||||
|
name: r'detectStringLanguageProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$detectStringLanguageHash,
|
||||||
|
dependencies: DetectStringLanguageFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
DetectStringLanguageFamily._allTransitiveDependencies,
|
||||||
|
text: text,
|
||||||
|
);
|
||||||
|
|
||||||
|
DetectStringLanguageProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.text,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String text;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
String? Function(DetectStringLanguageRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: DetectStringLanguageProvider._internal(
|
||||||
|
(ref) => create(ref as DetectStringLanguageRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
text: text,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeProviderElement<String?> createElement() {
|
||||||
|
return _DetectStringLanguageProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is DetectStringLanguageProvider && other.text == text;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, text.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin DetectStringLanguageRef on AutoDisposeProviderRef<String?> {
|
||||||
|
/// The parameter `text` of this provider.
|
||||||
|
String get text;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _DetectStringLanguageProviderElement
|
||||||
|
extends AutoDisposeProviderElement<String?>
|
||||||
|
with DetectStringLanguageRef {
|
||||||
|
_DetectStringLanguageProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get text => (origin as DetectStringLanguageProvider).text;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
@@ -46,6 +46,10 @@ class WebSocketService {
|
|||||||
final StreamController<WebSocketState> _statusStreamController =
|
final StreamController<WebSocketState> _statusStreamController =
|
||||||
StreamController<WebSocketState>.broadcast();
|
StreamController<WebSocketState>.broadcast();
|
||||||
Timer? _reconnectTimer;
|
Timer? _reconnectTimer;
|
||||||
|
Timer? _heartbeatTimer;
|
||||||
|
|
||||||
|
DateTime? _heartbeatAt;
|
||||||
|
Duration? _heartbeatDelay;
|
||||||
|
|
||||||
Stream<WebSocketPacket> get dataStream => _streamController.stream;
|
Stream<WebSocketPacket> get dataStream => _streamController.stream;
|
||||||
Stream<WebSocketState> get statusStream => _statusStreamController.stream;
|
Stream<WebSocketState> get statusStream => _statusStreamController.stream;
|
||||||
@@ -71,6 +75,7 @@ class WebSocketService {
|
|||||||
}
|
}
|
||||||
await _channel!.ready;
|
await _channel!.ready;
|
||||||
_statusStreamController.sink.add(WebSocketState.connected());
|
_statusStreamController.sink.add(WebSocketState.connected());
|
||||||
|
_scheduleHeartbeat();
|
||||||
_channel!.stream.listen(
|
_channel!.stream.listen(
|
||||||
(data) {
|
(data) {
|
||||||
final dataStr =
|
final dataStr =
|
||||||
@@ -80,6 +85,13 @@ class WebSocketService {
|
|||||||
log(
|
log(
|
||||||
"[WebSocket] Received packet: ${packet.type} ${packet.errorMessage}",
|
"[WebSocket] Received packet: ${packet.type} ${packet.errorMessage}",
|
||||||
);
|
);
|
||||||
|
if (packet.type == 'pong' && _heartbeatAt != null) {
|
||||||
|
var now = DateTime.now();
|
||||||
|
_heartbeatDelay = now.difference(_heartbeatAt!);
|
||||||
|
log(
|
||||||
|
"[WebSocket] Server respond last heartbeat for ${_heartbeatDelay!.inMilliseconds} ms",
|
||||||
|
);
|
||||||
|
}
|
||||||
},
|
},
|
||||||
onDone: () {
|
onDone: () {
|
||||||
log('[WebSocket] Connection closed, attempting to reconnect...');
|
log('[WebSocket] Connection closed, attempting to reconnect...');
|
||||||
@@ -108,6 +120,19 @@ class WebSocketService {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _scheduleHeartbeat() {
|
||||||
|
_heartbeatTimer?.cancel();
|
||||||
|
_heartbeatTimer = Timer.periodic(const Duration(seconds: 60), (_) {
|
||||||
|
_beatTheHeart();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _beatTheHeart() {
|
||||||
|
_heartbeatAt = DateTime.now();
|
||||||
|
log('[WebSocket] We\'re beating the heart! $_heartbeatAt');
|
||||||
|
sendMessage(jsonEncode(WebSocketPacket(type: 'ping', data: null)));
|
||||||
|
}
|
||||||
|
|
||||||
WebSocketChannel? get ws => _channel;
|
WebSocketChannel? get ws => _channel;
|
||||||
|
|
||||||
void sendMessage(String message) {
|
void sendMessage(String message) {
|
||||||
|
|||||||
@@ -287,12 +287,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
builder: (context, state) => const AboutScreen(),
|
builder: (context, state) => const AboutScreen(),
|
||||||
),
|
),
|
||||||
|
|
||||||
GoRoute(
|
|
||||||
name: 'reportList',
|
|
||||||
path: '/safety/reports/me',
|
|
||||||
builder: (context, state) => const AbuseReportListScreen(),
|
|
||||||
),
|
|
||||||
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'reportDetail',
|
name: 'reportDetail',
|
||||||
path: '/safety/reports/me/:id',
|
path: '/safety/reports/me/:id',
|
||||||
@@ -310,10 +304,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
},
|
},
|
||||||
routes: [
|
routes: [
|
||||||
// Explore tab
|
// Explore tab
|
||||||
ShellRoute(
|
|
||||||
builder:
|
|
||||||
(context, state, child) => ExploreShellScreen(child: child),
|
|
||||||
routes: [
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'explore',
|
name: 'explore',
|
||||||
path: '/',
|
path: '/',
|
||||||
@@ -345,8 +335,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
path: '/discovery/realms',
|
path: '/discovery/realms',
|
||||||
builder: (context, state) => const DiscoveryRealmsScreen(),
|
builder: (context, state) => const DiscoveryRealmsScreen(),
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
// Chat tab
|
// Chat tab
|
||||||
ShellRoute(
|
ShellRoute(
|
||||||
@@ -445,14 +433,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
path: '/account/relationships',
|
path: '/account/relationships',
|
||||||
builder: (context, state) => const RelationshipScreen(),
|
builder: (context, state) => const RelationshipScreen(),
|
||||||
),
|
),
|
||||||
GoRoute(
|
|
||||||
name: 'accountProfile',
|
|
||||||
path: '/account/:name',
|
|
||||||
builder: (context, state) {
|
|
||||||
final name = state.pathParameters['name']!;
|
|
||||||
return AccountProfileScreen(name: name);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'profileUpdate',
|
name: 'profileUpdate',
|
||||||
path: '/account/me/update',
|
path: '/account/me/update',
|
||||||
@@ -468,8 +448,22 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
path: '/account/me/settings',
|
path: '/account/me/settings',
|
||||||
builder: (context, state) => const AccountSettingsScreen(),
|
builder: (context, state) => const AccountSettingsScreen(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
name: 'reportList',
|
||||||
|
path: '/safety/reports/me',
|
||||||
|
builder: (context, state) => const AbuseReportListScreen(),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
GoRoute(
|
||||||
|
name: 'accountProfile',
|
||||||
|
path: '/account/:name',
|
||||||
|
builder: (context, state) {
|
||||||
|
final name = state.pathParameters['name']!;
|
||||||
|
return AccountProfileScreen(name: name);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -93,6 +93,7 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
|
|||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
appBar: AppBar(title: Text('about'.tr()), elevation: 0),
|
appBar: AppBar(title: Text('about'.tr()), elevation: 0),
|
||||||
body:
|
body:
|
||||||
_isLoading
|
_isLoading
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: isWide,
|
isNoBackground: isWide,
|
||||||
appBar: AppBar(backgroundColor: Colors.transparent, toolbarHeight: 0),
|
appBar: AppBar(backgroundColor: Colors.transparent, toolbarHeight: 0),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
padding: getTabbedPadding(context),
|
padding: getTabbedPadding(context),
|
||||||
@@ -231,7 +231,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
ListTile(
|
ListTile(
|
||||||
minTileHeight: 48,
|
minTileHeight: 48,
|
||||||
title: Text('abuseReports').tr(),
|
title: Text('abuseReports').tr(),
|
||||||
contentPadding: const EdgeInsets.only(left: 24, right: 17),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 24),
|
||||||
leading: const Icon(Symbols.gavel),
|
leading: const Icon(Symbols.gavel),
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
onTap: () => context.pushNamed('reportList'),
|
onTap: () => context.pushNamed('reportList'),
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ class EventCalanderScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
title: Text('eventCalander').tr(),
|
title: Text('eventCalander').tr(),
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ part 'leveling.g.dart';
|
|||||||
Future<SnWalletSubscription?> accountStellarSubscription(Ref ref) async {
|
Future<SnWalletSubscription?> accountStellarSubscription(Ref ref) async {
|
||||||
try {
|
try {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
final resp = await client.get('/subscriptions/fuzzy/solian.stellar');
|
final resp = await client.get('/id/subscriptions/fuzzy/solian.stellar');
|
||||||
return SnWalletSubscription.fromJson(resp.data);
|
return SnWalletSubscription.fromJson(resp.data);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
if (err is DioException && err.response?.statusCode == 404) return null;
|
if (err is DioException && err.response?.statusCode == 404) return null;
|
||||||
@@ -432,7 +432,7 @@ class LevelingScreen extends HookConsumerWidget {
|
|||||||
'id': 'solian.stellar.nova',
|
'id': 'solian.stellar.nova',
|
||||||
'name': 'membershipTierNova'.tr(),
|
'name': 'membershipTierNova'.tr(),
|
||||||
'price': 'membershipPriceNova'.tr(),
|
'price': 'membershipPriceNova'.tr(),
|
||||||
'color': Colors.indigo,
|
'color': Color.fromRGBO(57, 197, 187, 1),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
'id': 'solian.stellar.supernova',
|
'id': 'solian.stellar.supernova',
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'leveling.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$accountStellarSubscriptionHash() =>
|
String _$accountStellarSubscriptionHash() =>
|
||||||
r'37fb821460e3ac50b5cf777c933b6779f732daee';
|
r'80abcdefb3868775fd8fe3c980215713efff5948';
|
||||||
|
|
||||||
/// See also [accountStellarSubscription].
|
/// See also [accountStellarSubscription].
|
||||||
@ProviderFor(accountStellarSubscription)
|
@ProviderFor(accountStellarSubscription)
|
||||||
|
|||||||
@@ -94,7 +94,7 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
|||||||
final userInfo = ref.read(userInfoProvider);
|
final userInfo = ref.read(userInfoProvider);
|
||||||
final client = ref.read(apiClientProvider);
|
final client = ref.read(apiClientProvider);
|
||||||
await client.post(
|
await client.post(
|
||||||
'/accounts/recovery/password',
|
'/id/accounts/recovery/password',
|
||||||
data: {'account': userInfo.value!.name, 'captcha_token': captchaTk},
|
data: {'account': userInfo.value!.name, 'captcha_token': captchaTk},
|
||||||
);
|
);
|
||||||
if (context.mounted) {
|
if (context.mounted) {
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import 'package:island/pods/event_calendar.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/services/color.dart';
|
import 'package:island/services/color.dart';
|
||||||
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/services/time.dart';
|
import 'package:island/services/time.dart';
|
||||||
import 'package:island/services/timezone/native.dart';
|
import 'package:island/services/timezone/native.dart';
|
||||||
import 'package:island/widgets/account/account_name.dart';
|
import 'package:island/widgets/account/account_name.dart';
|
||||||
@@ -248,58 +249,12 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
return account.when(
|
Widget accountBasicInfo(SnAccount data) => Padding(
|
||||||
data:
|
|
||||||
(data) => AppScaffold(
|
|
||||||
body: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverAppBar(
|
|
||||||
foregroundColor: appbarColor.value,
|
|
||||||
expandedHeight: 180,
|
|
||||||
pinned: true,
|
|
||||||
leading: PageBackButton(
|
|
||||||
color: appbarColor.value,
|
|
||||||
shadows: [appbarShadow],
|
|
||||||
),
|
|
||||||
flexibleSpace: Stack(
|
|
||||||
children: [
|
|
||||||
Positioned.fill(
|
|
||||||
child:
|
|
||||||
data.profile.background?.id != null
|
|
||||||
? CloudImageWidget(
|
|
||||||
file: data.profile.background,
|
|
||||||
)
|
|
||||||
: Container(
|
|
||||||
color:
|
|
||||||
Theme.of(
|
|
||||||
context,
|
|
||||||
).appBarTheme.backgroundColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FlexibleSpaceBar(
|
|
||||||
title: Text(
|
|
||||||
data.nick,
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
appbarColor.value ??
|
|
||||||
Theme.of(context).appBarTheme.foregroundColor,
|
|
||||||
shadows: [appbarShadow],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ProfilePictureWidget(
|
ProfilePictureWidget(file: data.profile.picture, radius: 32),
|
||||||
file: data.profile.picture,
|
|
||||||
radius: 32,
|
|
||||||
),
|
|
||||||
const Gap(20),
|
const Gap(20),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -307,55 +262,20 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
children: [
|
children: [
|
||||||
AccountName(
|
AccountName(account: data, style: TextStyle(fontSize: 20)),
|
||||||
account: data,
|
|
||||||
style: TextStyle(fontSize: 20),
|
|
||||||
),
|
|
||||||
const Gap(6),
|
const Gap(6),
|
||||||
Text(
|
Text('@${data.name}').fontSize(14).opacity(0.85),
|
||||||
'@${data.name}',
|
|
||||||
).fontSize(14).opacity(0.85),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
AccountStatusWidget(
|
AccountStatusWidget(uname: name, padding: EdgeInsets.zero),
|
||||||
uname: name,
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
);
|
||||||
),
|
|
||||||
if (data.badges.isNotEmpty)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: BadgeList(
|
|
||||||
badges: data.badges,
|
|
||||||
).padding(horizontal: 24, bottom: 24),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Column(
|
|
||||||
spacing: 12,
|
|
||||||
children: [
|
|
||||||
LevelingProgressCard(
|
|
||||||
level: data.profile.level,
|
|
||||||
experience: data.profile.experience,
|
|
||||||
progress: data.profile.levelingProgress,
|
|
||||||
),
|
|
||||||
if (data.profile.verification != null)
|
|
||||||
VerificationStatusCard(
|
|
||||||
mark: data.profile.verification!,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 20),
|
|
||||||
),
|
|
||||||
|
|
||||||
SliverToBoxAdapter(
|
Widget accountProfileDetail(SnAccount data) => Column(
|
||||||
child: const Divider(height: 1).padding(vertical: 24),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
spacing: 24,
|
spacing: 24,
|
||||||
children: [
|
children: [
|
||||||
@@ -393,9 +313,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
).$2.formatCustomGlobal('HH:mm'),
|
).$2.formatCustomGlobal('HH:mm'),
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
getTzInfo(
|
getTzInfo(data.profile.timeZone).$1.formatOffsetLocal(),
|
||||||
data.profile.timeZone,
|
|
||||||
).$1.formatOffsetLocal(),
|
|
||||||
).fontSize(11),
|
).fontSize(11),
|
||||||
Text(
|
Text(
|
||||||
'UTC${getTzInfo(data.profile.timeZone).$1.formatOffset()}',
|
'UTC${getTzInfo(data.profile.timeZone).$1.formatOffset()}',
|
||||||
@@ -405,18 +323,12 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24),
|
).padding(horizontal: 24);
|
||||||
),
|
|
||||||
|
|
||||||
if (user.value != null)
|
Widget accountAction(SnAccount data) => Card(
|
||||||
SliverToBoxAdapter(
|
child: Column(
|
||||||
child: const Divider(
|
children: [
|
||||||
height: 1,
|
Row(
|
||||||
).padding(top: 24, bottom: 12),
|
|
||||||
),
|
|
||||||
if (user.value != null)
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Row(
|
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
if (accountRelationship.value == null ||
|
if (accountRelationship.value == null ||
|
||||||
@@ -432,9 +344,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
foregroundColor: WidgetStatePropertyAll(
|
foregroundColor: WidgetStatePropertyAll(
|
||||||
accountRelationship.value == null
|
accountRelationship.value == null
|
||||||
? null
|
? null
|
||||||
: Theme.of(
|
: Theme.of(context).colorScheme.onSecondary,
|
||||||
context,
|
|
||||||
).colorScheme.onSecondary,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: relationshipAction,
|
onPressed: relationshipAction,
|
||||||
@@ -463,9 +373,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
foregroundColor: WidgetStatePropertyAll(
|
foregroundColor: WidgetStatePropertyAll(
|
||||||
accountRelationship.value == null
|
accountRelationship.value == null
|
||||||
? null
|
? null
|
||||||
: Theme.of(
|
: Theme.of(context).colorScheme.onSecondary,
|
||||||
context,
|
|
||||||
).colorScheme.onSecondary,
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
onPressed: blockAction,
|
onPressed: blockAction,
|
||||||
@@ -483,9 +391,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16),
|
).padding(horizontal: 16),
|
||||||
),
|
Row(
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Row(
|
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
@@ -519,11 +425,179 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, top: 4),
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 16, vertical: 8),
|
||||||
|
);
|
||||||
|
|
||||||
|
return account.when(
|
||||||
|
data:
|
||||||
|
(data) => AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
|
appBar:
|
||||||
|
isWideScreen(context)
|
||||||
|
? AppBar(
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
|
leading: PageBackButton(
|
||||||
|
color: appbarColor.value,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
flexibleSpace: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child:
|
||||||
|
data.profile.background?.id != null
|
||||||
|
? CloudImageWidget(
|
||||||
|
file: data.profile.background,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
color:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
data.nick,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.foregroundColor,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
body:
|
||||||
|
isWideScreen(context)
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverToBoxAdapter(child: accountBasicInfo(data)),
|
||||||
|
if (data.badges.isNotEmpty)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: BadgeList(
|
||||||
|
badges: data.badges,
|
||||||
|
).padding(horizontal: 24, bottom: 24),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: const Divider(height: 1).padding(top: 12),
|
child: Column(
|
||||||
|
spacing: 12,
|
||||||
|
children: [
|
||||||
|
LevelingProgressCard(
|
||||||
|
level: data.profile.level,
|
||||||
|
experience: data.profile.experience,
|
||||||
|
progress: data.profile.levelingProgress,
|
||||||
),
|
),
|
||||||
|
if (data.profile.verification != null)
|
||||||
|
VerificationStatusCard(
|
||||||
|
mark: data.profile.verification!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: accountProfileDetail(data),
|
||||||
|
),
|
||||||
|
|
||||||
|
if (user.value != null)
|
||||||
|
SliverToBoxAdapter(child: accountAction(data)),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Card(
|
||||||
|
child: FortuneGraphWidget(
|
||||||
|
events: accountEvents,
|
||||||
|
eventCalanderUser: data.name,
|
||||||
|
),
|
||||||
|
).padding(all: 8),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
|
expandedHeight: 180,
|
||||||
|
pinned: true,
|
||||||
|
leading: PageBackButton(
|
||||||
|
color: appbarColor.value,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
flexibleSpace: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child:
|
||||||
|
data.profile.background?.id != null
|
||||||
|
? CloudImageWidget(
|
||||||
|
file: data.profile.background,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
color:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
data.nick,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.foregroundColor,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(child: accountBasicInfo(data)),
|
||||||
|
if (data.badges.isNotEmpty)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: BadgeList(
|
||||||
|
badges: data.badges,
|
||||||
|
).padding(horizontal: 24, bottom: 24),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: Column(
|
||||||
|
spacing: 12,
|
||||||
|
children: [
|
||||||
|
LevelingProgressCard(
|
||||||
|
level: data.profile.level,
|
||||||
|
experience: data.profile.experience,
|
||||||
|
progress: data.profile.levelingProgress,
|
||||||
|
),
|
||||||
|
if (data.profile.verification != null)
|
||||||
|
VerificationStatusCard(
|
||||||
|
mark: data.profile.verification!,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20),
|
||||||
|
),
|
||||||
|
|
||||||
|
SliverToBoxAdapter(child: accountProfileDetail(data)),
|
||||||
|
|
||||||
|
if (user.value != null)
|
||||||
|
SliverToBoxAdapter(child: accountAction(data)),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -73,7 +73,7 @@ class CreateAccountScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
title: Text('createAccount').tr(),
|
title: Text('createAccount').tr(),
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ class LoginScreen extends HookConsumerWidget {
|
|||||||
final factorPicked = useState<SnAuthFactor?>(null);
|
final factorPicked = useState<SnAuthFactor?>(null);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
title: Text('login').tr(),
|
title: Text('login').tr(),
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import 'package:flutter_hooks/flutter_hooks.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/pods/call.dart';
|
import 'package:island/pods/call.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/chat/call_button.dart';
|
import 'package:island/widgets/chat/call_button.dart';
|
||||||
import 'package:island/widgets/chat/call_overlay.dart';
|
import 'package:island/widgets/chat/call_overlay.dart';
|
||||||
@@ -21,17 +20,27 @@ class CallScreen extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final ongoingCall = ref.watch(ongoingCallProvider(roomId));
|
final ongoingCall = ref.watch(ongoingCallProvider(roomId));
|
||||||
final callState = ref.watch(callNotifierProvider);
|
final callState = ref.watch(callNotifierProvider);
|
||||||
final callNotifier = ref.read(callNotifierProvider.notifier);
|
final callNotifier = ref.watch(callNotifierProvider.notifier);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
callNotifier.joinRoom(roomId);
|
callNotifier.joinRoom(roomId);
|
||||||
return null;
|
return null;
|
||||||
}, []);
|
}, []);
|
||||||
|
|
||||||
final viewMode = useState<String>('grid');
|
final allAudioOnly = callNotifier.participants.every(
|
||||||
|
(p) =>
|
||||||
|
!(p.hasVideo &&
|
||||||
|
p.remoteParticipant.trackPublications.values.any(
|
||||||
|
(pub) =>
|
||||||
|
pub.track != null &&
|
||||||
|
pub.kind == TrackType.VIDEO &&
|
||||||
|
!pub.muted &&
|
||||||
|
!pub.isDisposed,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: PageBackButton(),
|
leading: PageBackButton(),
|
||||||
title: Column(
|
title: Column(
|
||||||
@@ -44,45 +53,50 @@ class CallScreen extends HookConsumerWidget {
|
|||||||
Text(
|
Text(
|
||||||
callState.isConnected
|
callState.isConnected
|
||||||
? formatDuration(callState.duration)
|
? formatDuration(callState.duration)
|
||||||
: 'Connecting',
|
: 'connecting',
|
||||||
style: const TextStyle(fontSize: 14),
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
Row(
|
if (!allAudioOnly)
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
SingleChildScrollView(
|
||||||
|
child: Row(
|
||||||
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
IconButton(
|
for (final live in callNotifier.participants)
|
||||||
icon: Icon(Symbols.grid_view),
|
SpeakingRippleAvatar(live: live, size: 30),
|
||||||
tooltip: 'Grid View',
|
const Gap(8),
|
||||||
onPressed: () => viewMode.value = 'grid',
|
|
||||||
color:
|
|
||||||
viewMode.value == 'grid'
|
|
||||||
? Theme.of(context).colorScheme.primary
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: Icon(Symbols.view_agenda),
|
|
||||||
tooltip: 'Stage View',
|
|
||||||
onPressed: () => viewMode.value = 'stage',
|
|
||||||
color:
|
|
||||||
viewMode.value == 'stage'
|
|
||||||
? Theme.of(context).colorScheme.primary
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Gap(8),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body:
|
body:
|
||||||
callState.error != null
|
callState.error != null
|
||||||
? Center(
|
? Center(
|
||||||
child: Text(
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 320),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.error_outline, size: 48),
|
||||||
|
const Gap(4),
|
||||||
|
Text(
|
||||||
callState.error!,
|
callState.error!,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(color: Colors.red),
|
style: const TextStyle(color: Color(0xFF757575)),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
callNotifier.disconnect();
|
||||||
|
callNotifier.dispose();
|
||||||
|
callNotifier.joinRoom(roomId);
|
||||||
|
},
|
||||||
|
child: Text('retry').tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
: Column(
|
: Column(
|
||||||
@@ -100,17 +114,8 @@ class CallScreen extends HookConsumerWidget {
|
|||||||
child: Text('No participants in call'),
|
child: Text('No participants in call'),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final participants = callNotifier.participants;
|
final participants = callNotifier.participants;
|
||||||
final allAudioOnly = participants.every(
|
|
||||||
(p) =>
|
|
||||||
!(p.hasVideo &&
|
|
||||||
p.remoteParticipant.trackPublications.values
|
|
||||||
.any(
|
|
||||||
(pub) =>
|
|
||||||
pub.track != null &&
|
|
||||||
pub.kind == TrackType.VIDEO,
|
|
||||||
)),
|
|
||||||
);
|
|
||||||
if (allAudioOnly) {
|
if (allAudioOnly) {
|
||||||
// Audio-only: show avatars in a compact row
|
// Audio-only: show avatars in a compact row
|
||||||
return Center(
|
return Center(
|
||||||
@@ -123,31 +128,16 @@ class CallScreen extends HookConsumerWidget {
|
|||||||
runSpacing: 8,
|
runSpacing: 8,
|
||||||
children: [
|
children: [
|
||||||
for (final live in participants)
|
for (final live in participants)
|
||||||
Padding(
|
SpeakingRippleAvatar(
|
||||||
padding: const EdgeInsets.symmetric(
|
live: live,
|
||||||
horizontal: 8,
|
|
||||||
),
|
|
||||||
child: SpeakingRippleAvatar(
|
|
||||||
isSpeaking: live.isSpeaking,
|
|
||||||
audioLevel:
|
|
||||||
live.remoteParticipant.audioLevel,
|
|
||||||
pictureId:
|
|
||||||
live
|
|
||||||
.participant
|
|
||||||
.profile
|
|
||||||
?.account
|
|
||||||
.profile
|
|
||||||
.picture
|
|
||||||
?.id,
|
|
||||||
size: 72,
|
size: 72,
|
||||||
),
|
).padding(horizontal: 4),
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
if (viewMode.value == 'stage') {
|
|
||||||
// Stage view: show main speaker(s) large, others in row
|
// Stage view: show main speaker(s) large, others in row
|
||||||
final mainSpeakers =
|
final mainSpeakers =
|
||||||
participants
|
participants
|
||||||
@@ -166,95 +156,13 @@ class CallScreen extends HookConsumerWidget {
|
|||||||
if (mainSpeakers.isEmpty && participants.isNotEmpty) {
|
if (mainSpeakers.isEmpty && participants.isNotEmpty) {
|
||||||
mainSpeakers.add(participants.first);
|
mainSpeakers.add(participants.first);
|
||||||
}
|
}
|
||||||
final others =
|
|
||||||
participants
|
|
||||||
.where((p) => !mainSpeakers.contains(p))
|
|
||||||
.toList();
|
|
||||||
return Column(
|
return Column(
|
||||||
children: [
|
|
||||||
Expanded(
|
|
||||||
child: Row(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
children: [
|
children: [
|
||||||
for (final speaker in mainSpeakers)
|
for (final speaker in mainSpeakers)
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child: CallParticipantTile(live: speaker),
|
||||||
AspectRatio(
|
|
||||||
aspectRatio: 16 / 9,
|
|
||||||
child: Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius:
|
|
||||||
BorderRadius.circular(8),
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
CallParticipantTile(
|
|
||||||
live: speaker,
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).center(),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 12),
|
|
||||||
),
|
|
||||||
if (others.isNotEmpty)
|
|
||||||
SizedBox(
|
|
||||||
height: 100,
|
|
||||||
child: ListView(
|
|
||||||
scrollDirection: Axis.horizontal,
|
|
||||||
children: [
|
|
||||||
for (final other in others)
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 8,
|
|
||||||
),
|
|
||||||
child: CallParticipantTile(
|
|
||||||
live: other,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
}
|
|
||||||
// Default: grid view
|
|
||||||
return GridView.builder(
|
|
||||||
padding: const EdgeInsets.symmetric(
|
|
||||||
horizontal: 12,
|
|
||||||
vertical: 8,
|
|
||||||
),
|
|
||||||
gridDelegate:
|
|
||||||
SliverGridDelegateWithFixedCrossAxisCount(
|
|
||||||
crossAxisCount:
|
|
||||||
isWidestScreen(context)
|
|
||||||
? 4
|
|
||||||
: isWiderScreen(context)
|
|
||||||
? 3
|
|
||||||
: 2,
|
|
||||||
childAspectRatio: 16 / 9,
|
|
||||||
crossAxisSpacing: 8,
|
|
||||||
mainAxisSpacing: 8,
|
|
||||||
),
|
|
||||||
itemCount: participants.length,
|
|
||||||
itemBuilder: (context, idx) {
|
|
||||||
final live = participants[idx];
|
|
||||||
return AspectRatio(
|
|
||||||
aspectRatio: 16 / 9,
|
|
||||||
child: Card(
|
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: Column(
|
|
||||||
children: [CallParticipantTile(live: live)],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
).center();
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -21,7 +21,6 @@ import 'package:island/services/responsive.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';
|
||||||
import 'package:island/widgets/chat/call_overlay.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';
|
||||||
import 'package:island/widgets/realms/selection_dropdown.dart';
|
import 'package:island/widgets/realms/selection_dropdown.dart';
|
||||||
@@ -346,9 +345,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
child: const Icon(Symbols.add),
|
child: const Icon(Symbols.add),
|
||||||
),
|
),
|
||||||
floatingActionButtonLocation: TabbedFabLocation(context),
|
floatingActionButtonLocation: TabbedFabLocation(context),
|
||||||
body: Stack(
|
body: Column(
|
||||||
children: [
|
|
||||||
Column(
|
|
||||||
children: [
|
children: [
|
||||||
Consumer(
|
Consumer(
|
||||||
builder: (context, ref, _) {
|
builder: (context, ref, _) {
|
||||||
@@ -383,8 +380,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
selectedTab.value == 0 ||
|
selectedTab.value == 0 ||
|
||||||
(selectedTab.value == 1 &&
|
(selectedTab.value == 1 &&
|
||||||
item.type == 1) ||
|
item.type == 1) ||
|
||||||
(selectedTab.value == 2 &&
|
(selectedTab.value == 2 && item.type != 1),
|
||||||
item.type != 1),
|
|
||||||
)
|
)
|
||||||
.length,
|
.length,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
@@ -413,8 +409,7 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
loading:
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
() => const Center(child: CircularProgressIndicator()),
|
|
||||||
error:
|
error:
|
||||||
(error, stack) => ResponseErrorWidget(
|
(error, stack) => ResponseErrorWidget(
|
||||||
error: error,
|
error: error,
|
||||||
@@ -426,14 +421,6 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
Positioned(
|
|
||||||
left: 0,
|
|
||||||
right: 0,
|
|
||||||
bottom: getTabbedPadding(context).bottom + 8,
|
|
||||||
child: const CallOverlayBar().padding(horizontal: 16, vertical: 12),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
try {
|
try {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
await client.patch(
|
await client.patch(
|
||||||
'/chat/$id/members/me/notify',
|
'/sphere/chat/$id/members/me/notify',
|
||||||
data: {'notify_level': level},
|
data: {'notify_level': level},
|
||||||
);
|
);
|
||||||
ref.invalidate(chatroomIdentityProvider(id));
|
ref.invalidate(chatroomIdentityProvider(id));
|
||||||
@@ -59,7 +59,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
try {
|
try {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
await client.patch(
|
await client.patch(
|
||||||
'/chat/$id/members/me/notify',
|
'/sphere/chat/$id/members/me/notify',
|
||||||
data: {'break_until': until.toUtc().toIso8601String()},
|
data: {'break_until': until.toUtc().toIso8601String()},
|
||||||
);
|
);
|
||||||
ref.invalidate(chatroomProvider(id));
|
ref.invalidate(chatroomProvider(id));
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'room_detail.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$chatMemberListNotifierHash() =>
|
String _$chatMemberListNotifierHash() =>
|
||||||
r'f2191a631ba00ae3de39ccac10e4cdd065ffee17';
|
r'c8fbf4b95df6dae24b1ba21063e9a43351832974';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|||||||
@@ -114,9 +114,9 @@ class CreatorHubShellScreen extends StatelessWidget {
|
|||||||
isRoot: true,
|
isRoot: true,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(width: 360, child: const CreatorHubScreen(isAside: true)),
|
Flexible(flex: 2, child: const CreatorHubScreen(isAside: true)),
|
||||||
const VerticalDivider(width: 1),
|
const VerticalDivider(width: 1),
|
||||||
Expanded(child: child),
|
Flexible(flex: 3, child: child),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ part 'pack_detail.freezed.dart';
|
|||||||
@riverpod
|
@riverpod
|
||||||
Future<List<SnSticker>> stickerPackContent(Ref ref, String packId) async {
|
Future<List<SnSticker>> stickerPackContent(Ref ref, String packId) async {
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
final resp = await apiClient.get('/stickers/$packId/content');
|
final resp = await apiClient.get('/sphere/stickers/$packId/content');
|
||||||
return resp.data
|
return resp.data
|
||||||
.map<SnSticker>((e) => SnSticker.fromJson(e))
|
.map<SnSticker>((e) => SnSticker.fromJson(e))
|
||||||
.cast<SnSticker>()
|
.cast<SnSticker>()
|
||||||
@@ -74,9 +74,12 @@ class StickerPackDetailScreen extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.add_circle),
|
icon: const Icon(Symbols.add_circle),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.pushNamed('creatorStickerNew', pathParameters: {'packId': id}).then((
|
context
|
||||||
value,
|
.pushNamed(
|
||||||
) {
|
'creatorStickerNew',
|
||||||
|
pathParameters: {'name': pubName, 'packId': id},
|
||||||
|
)
|
||||||
|
.then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
ref.invalidate(stickerPackContentProvider(id));
|
ref.invalidate(stickerPackContentProvider(id));
|
||||||
}
|
}
|
||||||
@@ -173,9 +176,13 @@ class StickerPackDetailScreen extends HookConsumerWidget {
|
|||||||
title: 'edit'.tr(),
|
title: 'edit'.tr(),
|
||||||
image: MenuImage.icon(Symbols.edit),
|
image: MenuImage.icon(Symbols.edit),
|
||||||
callback: () {
|
callback: () {
|
||||||
context.pushNamed(
|
context
|
||||||
|
.pushNamed(
|
||||||
'creatorStickerEdit',
|
'creatorStickerEdit',
|
||||||
pathParameters: {'packId': id, 'id': sticker.id},
|
pathParameters: {
|
||||||
|
'packId': id,
|
||||||
|
'id': sticker.id,
|
||||||
|
},
|
||||||
)
|
)
|
||||||
.then((value) {
|
.then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@@ -259,9 +266,7 @@ class _StickerPackActionMenu extends HookConsumerWidget {
|
|||||||
(context) => [
|
(context) => [
|
||||||
PopupMenuItem(
|
PopupMenuItem(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.push(
|
context.push('/creators/$pubName/stickers/$packId/edit');
|
||||||
'/creators/$pubName/stickers/$packId/edit',
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'pack_detail.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$stickerPackContentHash() =>
|
String _$stickerPackContentHash() =>
|
||||||
r'78de848fba1f341f217f8ae4b9eef2d8afa67964';
|
r'42d74f51022e67e35cb601c2f30f4f02e1f2be9d';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ class StickersScreen extends HookConsumerWidget {
|
|||||||
context
|
context
|
||||||
.pushNamed(
|
.pushNamed(
|
||||||
'creatorStickerPackNew',
|
'creatorStickerPackNew',
|
||||||
queryParameters: {'pubName': pubName},
|
queryParameters: {'name': pubName},
|
||||||
)
|
)
|
||||||
.then((value) {
|
.then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
@@ -76,7 +76,7 @@ class SliverStickerPacksList extends HookConsumerWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed(
|
context.pushNamed(
|
||||||
'creatorStickerPackDetail',
|
'creatorStickerPackDetail',
|
||||||
pathParameters: {'pubName': pubName, 'packId': sticker.id},
|
pathParameters: {'name': pubName, 'packId': sticker.id},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -51,12 +51,9 @@ class DeveloperHubShellScreen extends StatelessWidget {
|
|||||||
isRoot: true,
|
isRoot: true,
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
SizedBox(
|
Flexible(flex: 2, child: const DeveloperHubScreen(isAside: true)),
|
||||||
width: 360,
|
|
||||||
child: const DeveloperHubScreen(isAside: true),
|
|
||||||
),
|
|
||||||
const VerticalDivider(width: 1),
|
const VerticalDivider(width: 1),
|
||||||
Expanded(child: child),
|
Flexible(flex: 3, child: child),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -114,7 +111,7 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: !isWide ? const PageBackButton() : null,
|
leading: !isWide ? const PageBackButton() : null,
|
||||||
title: Text('developerHub').tr(),
|
title: Text('developerHub').tr(),
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'articles.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$articlesListNotifierHash() =>
|
String _$articlesListNotifierHash() =>
|
||||||
r'924f2344c3bbf0ff7b92fe69e88d3b64a534b538';
|
r'579741af4d90c7c81f2e2697e57c4895b7a9dabc';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ class DiscoveryRealmsScreen extends HookConsumerWidget {
|
|||||||
final currentQuery = useState<String?>(null);
|
final currentQuery = useState<String?>(null);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
appBar: AppBar(title: Text('discoverRealms'.tr())),
|
appBar: AppBar(title: Text('discoverRealms'.tr())),
|
||||||
body: Stack(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -9,8 +9,11 @@ import 'package:island/models/activity.dart';
|
|||||||
import 'package:island/models/publisher.dart';
|
import 'package:island/models/publisher.dart';
|
||||||
import 'package:island/models/realm.dart';
|
import 'package:island/models/realm.dart';
|
||||||
import 'package:island/models/webfeed.dart';
|
import 'package:island/models/webfeed.dart';
|
||||||
|
import 'package:island/pods/event_calendar.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
|
import 'package:island/widgets/account/event_calendar.dart';
|
||||||
|
import 'package:island/widgets/account/fortune_graph.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/widgets/check_in.dart';
|
import 'package:island/widgets/check_in.dart';
|
||||||
@@ -27,42 +30,11 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
|
|
||||||
part 'explore.g.dart';
|
part 'explore.g.dart';
|
||||||
|
|
||||||
class ExploreShellScreen extends HookConsumerWidget {
|
|
||||||
final Widget child;
|
|
||||||
const ExploreShellScreen({super.key, required this.child});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
|
||||||
final isWide = MediaQuery.of(context).size.width > 640;
|
|
||||||
|
|
||||||
if (isWide) {
|
|
||||||
return AppBackground(
|
|
||||||
isRoot: true,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
Flexible(flex: 2, child: ExploreScreen(isAside: true)),
|
|
||||||
VerticalDivider(width: 1),
|
|
||||||
Flexible(flex: 3, child: child),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
return AppBackground(isRoot: true, child: child);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class ExploreScreen extends HookConsumerWidget {
|
class ExploreScreen extends HookConsumerWidget {
|
||||||
final bool isAside;
|
const ExploreScreen({super.key});
|
||||||
const ExploreScreen({super.key, this.isAside = false});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final isWide = isWideScreen(context);
|
|
||||||
if (isWide && !isAside) {
|
|
||||||
return const EmptyPageHolder();
|
|
||||||
}
|
|
||||||
|
|
||||||
final tabController = useTabController(initialLength: 3);
|
final tabController = useTabController(initialLength: 3);
|
||||||
final currentFilter = useState<String?>(null);
|
final currentFilter = useState<String?>(null);
|
||||||
|
|
||||||
@@ -89,8 +61,33 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
activityListNotifierProvider(currentFilter.value).notifier,
|
activityListNotifierProvider(currentFilter.value).notifier,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final now = DateTime.now();
|
||||||
|
|
||||||
|
final query = useState(
|
||||||
|
EventCalendarQuery(uname: 'me', year: now.year, month: now.month),
|
||||||
|
);
|
||||||
|
|
||||||
|
final events = ref.watch(eventCalendarProvider(query.value));
|
||||||
|
|
||||||
|
final selectedDay = useState(now);
|
||||||
|
|
||||||
|
void onMonthChanged(int year, int month) {
|
||||||
|
query.value = EventCalendarQuery(
|
||||||
|
uname: query.value.uname,
|
||||||
|
year: year,
|
||||||
|
month: month,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Function to handle day selection for synchronizing between widgets
|
||||||
|
void onDaySelected(DateTime day) {
|
||||||
|
selectedDay.value = day;
|
||||||
|
}
|
||||||
|
|
||||||
|
final user = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
extendBody: false, // Prevent conflicts with tabs navigation
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
toolbarHeight: 0,
|
toolbarHeight: 0,
|
||||||
bottom: PreferredSize(
|
bottom: PreferredSize(
|
||||||
@@ -172,7 +169,17 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: InkWell(
|
||||||
|
onLongPress: () {
|
||||||
|
context.pushNamed('postCompose', queryParameters: {'type': '1'}).then(
|
||||||
|
(value) {
|
||||||
|
if (value != null) {
|
||||||
|
activitiesNotifier.forceRefresh();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: FloatingActionButton(
|
||||||
heroTag: Key("explore-page-fab"),
|
heroTag: Key("explore-page-fab"),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
context.pushNamed('postCompose').then((value) {
|
context.pushNamed('postCompose').then((value) {
|
||||||
@@ -183,24 +190,100 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
child: const Icon(Symbols.edit),
|
child: const Icon(Symbols.edit),
|
||||||
),
|
),
|
||||||
|
),
|
||||||
floatingActionButtonLocation: TabbedFabLocation(context),
|
floatingActionButtonLocation: TabbedFabLocation(context),
|
||||||
body: TabBarView(
|
body: Builder(
|
||||||
controller: tabController,
|
builder: (context) {
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
final isWider = isWiderScreen(context);
|
||||||
|
|
||||||
|
final bodyView = _buildActivityList(
|
||||||
|
context,
|
||||||
|
ref,
|
||||||
|
currentFilter.value,
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isWider) {
|
||||||
|
return Row(
|
||||||
children: [
|
children: [
|
||||||
_buildActivityList(ref, null),
|
Flexible(flex: 3, child: bodyView.padding(left: 8)),
|
||||||
_buildActivityList(ref, 'subscriptions'),
|
if (user.value != null)
|
||||||
_buildActivityList(ref, 'friends'),
|
Flexible(
|
||||||
|
flex: 2,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CheckInWidget(
|
||||||
|
margin: EdgeInsets.only(
|
||||||
|
left: 8,
|
||||||
|
right: 12,
|
||||||
|
top: 16,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Card(
|
||||||
|
margin: EdgeInsets.only(left: 8, right: 12, top: 8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
// Use the reusable EventCalendarWidget
|
||||||
|
EventCalendarWidget(
|
||||||
|
events: events,
|
||||||
|
initialDate: now,
|
||||||
|
showEventDetails: true,
|
||||||
|
onMonthChanged: onMonthChanged,
|
||||||
|
onDaySelected: onDaySelected,
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
FortuneGraphWidget(
|
||||||
|
margin: EdgeInsets.only(left: 8, right: 12, top: 8),
|
||||||
|
events: events,
|
||||||
|
constrainWidth: true,
|
||||||
|
onPointSelected: onDaySelected,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
Flexible(
|
||||||
|
flex: 2,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Welcome to\nthe Solar Network',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
).bold(),
|
||||||
|
const Gap(2),
|
||||||
|
Text(
|
||||||
|
'Login to explore more!',
|
||||||
|
style: Theme.of(context).textTheme.bodyLarge,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 36, vertical: 16),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return bodyView;
|
||||||
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget _buildActivityList(WidgetRef ref, String? filter) {
|
Widget _buildActivityList(
|
||||||
|
BuildContext context,
|
||||||
|
WidgetRef ref,
|
||||||
|
String? filter,
|
||||||
|
) {
|
||||||
final activitiesNotifier = ref.watch(
|
final activitiesNotifier = ref.watch(
|
||||||
activityListNotifierProvider(filter).notifier,
|
activityListNotifierProvider(filter).notifier,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final isWider = isWiderScreen(context);
|
||||||
|
|
||||||
return RefreshIndicator(
|
return RefreshIndicator(
|
||||||
onRefresh: () => Future.sync(activitiesNotifier.forceRefresh),
|
onRefresh: () => Future.sync(activitiesNotifier.forceRefresh),
|
||||||
child: PagingHelperView(
|
child: PagingHelperView(
|
||||||
@@ -214,7 +297,7 @@ class ExploreScreen extends HookConsumerWidget {
|
|||||||
widgetCount: widgetCount,
|
widgetCount: widgetCount,
|
||||||
endItemView: endItemView,
|
endItemView: endItemView,
|
||||||
activitiesNotifier: activitiesNotifier,
|
activitiesNotifier: activitiesNotifier,
|
||||||
contentOnly: filter != null,
|
contentOnly: isWider || filter != null,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -232,7 +315,9 @@ class _DiscoveryActivityItem extends StatelessWidget {
|
|||||||
final items = data['items'] as List;
|
final items = data['items'] as List;
|
||||||
final type = items.firstOrNull?['type'] ?? 'unknown';
|
final type = items.firstOrNull?['type'] ?? 'unknown';
|
||||||
|
|
||||||
return Column(
|
return Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
@@ -253,35 +338,39 @@ class _DiscoveryActivityItem extends StatelessWidget {
|
|||||||
).padding(horizontal: 20, top: 8, bottom: 4),
|
).padding(horizontal: 20, top: 8, bottom: 4),
|
||||||
SizedBox(
|
SizedBox(
|
||||||
height: 180,
|
height: 180,
|
||||||
child: ListView.builder(
|
child: ConstrainedBox(
|
||||||
scrollDirection: Axis.horizontal,
|
constraints: const BoxConstraints(maxHeight: 200),
|
||||||
itemCount: items.length,
|
child: CarouselView.weighted(
|
||||||
padding: const EdgeInsets.symmetric(horizontal: 8),
|
flexWeights:
|
||||||
itemBuilder: (context, index) {
|
isWideScreen(context) ? <int>[3, 2, 1] : <int>[4, 1],
|
||||||
final item = items[index];
|
consumeMaxWeight: false,
|
||||||
|
enableSplash: false,
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
children: [
|
||||||
|
for (final item in items)
|
||||||
switch (type) {
|
switch (type) {
|
||||||
case 'realm':
|
'realm' => RealmCard(
|
||||||
return RealmCard(
|
|
||||||
realm: SnRealm.fromJson(item['data']),
|
realm: SnRealm.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
);
|
),
|
||||||
case 'publisher':
|
'publisher' => PublisherCard(
|
||||||
return PublisherCard(
|
|
||||||
publisher: SnPublisher.fromJson(item['data']),
|
publisher: SnPublisher.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
);
|
),
|
||||||
case 'article':
|
'article' => WebArticleCard(
|
||||||
return WebArticleCard(
|
|
||||||
article: SnWebArticle.fromJson(item['data']),
|
article: SnWebArticle.fromJson(item['data']),
|
||||||
maxWidth: 280,
|
maxWidth: 280,
|
||||||
);
|
|
||||||
default:
|
|
||||||
return Placeholder();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
).padding(bottom: 4),
|
_ => Placeholder(),
|
||||||
|
},
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).padding(bottom: 8, horizontal: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -307,8 +396,13 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
|
|
||||||
return CustomScrollView(
|
return CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
|
SliverGap(12),
|
||||||
if (user.value != null && !contentOnly)
|
if (user.value != null && !contentOnly)
|
||||||
SliverToBoxAdapter(child: CheckInWidget()),
|
SliverToBoxAdapter(
|
||||||
|
child: CheckInWidget(
|
||||||
|
margin: EdgeInsets.only(left: 8, right: 8, bottom: 4),
|
||||||
|
),
|
||||||
|
),
|
||||||
SliverList.builder(
|
SliverList.builder(
|
||||||
itemCount: widgetCount,
|
itemCount: widgetCount,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
@@ -325,19 +419,9 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'posts.new':
|
case 'posts.new':
|
||||||
case 'posts.new.replies':
|
case 'posts.new.replies':
|
||||||
final isReply = item.type == 'posts.new.replies';
|
itemWidget = PostActionableItem(
|
||||||
itemWidget = PostItem(
|
borderRadius: 8,
|
||||||
backgroundColor:
|
|
||||||
isWideScreen(context) ? Colors.transparent : null,
|
|
||||||
item: SnPost.fromJson(item.data!),
|
item: SnPost.fromJson(item.data!),
|
||||||
padding:
|
|
||||||
isReply
|
|
||||||
? const EdgeInsets.only(
|
|
||||||
left: 16,
|
|
||||||
right: 16,
|
|
||||||
bottom: 16,
|
|
||||||
)
|
|
||||||
: null,
|
|
||||||
onRefresh: () {
|
onRefresh: () {
|
||||||
activitiesNotifier.forceRefresh();
|
activitiesNotifier.forceRefresh();
|
||||||
},
|
},
|
||||||
@@ -348,21 +432,10 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
if (isReply) {
|
itemWidget = Card(
|
||||||
itemWidget = Column(
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
child: itemWidget,
|
||||||
children: [
|
|
||||||
Row(
|
|
||||||
children: [
|
|
||||||
const Icon(Symbols.reply),
|
|
||||||
const Gap(8),
|
|
||||||
Text('Replying your post'),
|
|
||||||
],
|
|
||||||
).padding(horizontal: 20, vertical: 8),
|
|
||||||
itemWidget,
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
case 'discovery':
|
case 'discovery':
|
||||||
itemWidget = _DiscoveryActivityItem(data: item.data!);
|
itemWidget = _DiscoveryActivityItem(data: item.data!);
|
||||||
@@ -371,7 +444,7 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
itemWidget = const Placeholder();
|
itemWidget = const Placeholder();
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(children: [itemWidget, const Divider(height: 1)]);
|
return itemWidget;
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
SliverGap(getTabbedPadding(context).bottom),
|
SliverGap(getTabbedPadding(context).bottom),
|
||||||
|
|||||||
@@ -18,7 +18,8 @@ import 'package:island/widgets/post/publishers_modal.dart';
|
|||||||
import 'package:island/screens/posts/post_detail.dart';
|
import 'package:island/screens/posts/post_detail.dart';
|
||||||
import 'package:island/widgets/post/compose_settings_sheet.dart';
|
import 'package:island/widgets/post/compose_settings_sheet.dart';
|
||||||
import 'package:island/services/compose_storage_db.dart';
|
import 'package:island/services/compose_storage_db.dart';
|
||||||
import 'package:island/widgets/post/draft_manager.dart';
|
// DraftManagerSheet is now imported through compose_toolbar.dart
|
||||||
|
import 'package:island/widgets/post/compose_toolbar.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';
|
||||||
|
|
||||||
@@ -52,13 +53,13 @@ class PostEditScreen extends HookConsumerWidget {
|
|||||||
data: (post) => PostComposeScreen(originalPost: post),
|
data: (post) => PostComposeScreen(originalPost: post),
|
||||||
loading:
|
loading:
|
||||||
() => AppScaffold(
|
() => AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(leading: const PageBackButton()),
|
appBar: AppBar(leading: const PageBackButton()),
|
||||||
body: const Center(child: CircularProgressIndicator()),
|
body: const Center(child: CircularProgressIndicator()),
|
||||||
),
|
),
|
||||||
error:
|
error:
|
||||||
(e, _) => AppScaffold(
|
(e, _) => AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(leading: const PageBackButton()),
|
appBar: AppBar(leading: const PageBackButton()),
|
||||||
body: Text('Error: $e', textAlign: TextAlign.center),
|
body: Text('Error: $e', textAlign: TextAlign.center),
|
||||||
),
|
),
|
||||||
@@ -92,7 +93,6 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Otherwise, continue with regular post compose
|
// Otherwise, continue with regular post compose
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
final colorScheme = theme.colorScheme;
|
|
||||||
|
|
||||||
// When editing, preserve the original replied/forwarded post references
|
// When editing, preserve the original replied/forwarded post references
|
||||||
final effectiveRepliedPost = repliedPost ?? originalPost?.repliedPost;
|
final effectiveRepliedPost = repliedPost ?? originalPost?.repliedPost;
|
||||||
@@ -287,43 +287,10 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: AppScaffold(
|
child: AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
actions: [
|
actions: [
|
||||||
if (originalPost == null) // Only show drafts for new posts
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.draft),
|
|
||||||
onPressed: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
builder:
|
|
||||||
(context) => DraftManagerSheet(
|
|
||||||
onDraftSelected: (draftId) {
|
|
||||||
final draft =
|
|
||||||
ref.read(
|
|
||||||
composeStorageNotifierProvider,
|
|
||||||
)[draftId];
|
|
||||||
if (draft != null) {
|
|
||||||
state.titleController.text = draft.title ?? '';
|
|
||||||
state.descriptionController.text =
|
|
||||||
draft.description ?? '';
|
|
||||||
state.contentController.text =
|
|
||||||
draft.content ?? '';
|
|
||||||
state.visibility.value = draft.visibility;
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
tooltip: 'drafts'.tr(),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.save),
|
|
||||||
onPressed: () => ComposeLogic.saveDraft(ref, state),
|
|
||||||
tooltip: 'saveDraft'.tr(),
|
|
||||||
),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.settings),
|
icon: const Icon(Symbols.settings),
|
||||||
onPressed: showSettingsSheet,
|
onPressed: showSettingsSheet,
|
||||||
@@ -455,27 +422,7 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Bottom toolbar
|
// Bottom toolbar
|
||||||
Material(
|
ComposeToolbar(state: state, originalPost: originalPost),
|
||||||
elevation: 4,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => ComposeLogic.pickPhotoMedia(ref, state),
|
|
||||||
icon: const Icon(Symbols.add_a_photo),
|
|
||||||
color: colorScheme.primary,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => ComposeLogic.pickVideoMedia(ref, state),
|
|
||||||
icon: const Icon(Symbols.videocam),
|
|
||||||
color: colorScheme.primary,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(
|
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 16,
|
|
||||||
horizontal: 16,
|
|
||||||
top: 8,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -650,7 +597,7 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
controller: scrollController,
|
controller: scrollController,
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: PostItem(item: post, isOpenable: false),
|
child: PostItem(item: post),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -19,8 +19,8 @@ import 'package:island/widgets/content/markdown.dart';
|
|||||||
import 'package:island/widgets/post/compose_shared.dart';
|
import 'package:island/widgets/post/compose_shared.dart';
|
||||||
import 'package:island/widgets/post/compose_settings_sheet.dart';
|
import 'package:island/widgets/post/compose_settings_sheet.dart';
|
||||||
import 'package:island/services/compose_storage_db.dart';
|
import 'package:island/services/compose_storage_db.dart';
|
||||||
|
import 'package:island/widgets/post/compose_toolbar.dart';
|
||||||
import 'package:island/widgets/post/publishers_modal.dart';
|
import 'package:island/widgets/post/publishers_modal.dart';
|
||||||
import 'package:island/widgets/post/draft_manager.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';
|
||||||
@@ -153,6 +153,57 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Widget buildPreviewPane() {
|
Widget buildPreviewPane() {
|
||||||
|
final widgetItem = SingleChildScrollView(
|
||||||
|
padding: const EdgeInsets.symmetric(vertical: 14, horizontal: 8),
|
||||||
|
child: ValueListenableBuilder<TextEditingValue>(
|
||||||
|
valueListenable: state.titleController,
|
||||||
|
builder: (context, titleValue, _) {
|
||||||
|
return ValueListenableBuilder<TextEditingValue>(
|
||||||
|
valueListenable: state.descriptionController,
|
||||||
|
builder: (context, descriptionValue, _) {
|
||||||
|
return ValueListenableBuilder<TextEditingValue>(
|
||||||
|
valueListenable: state.contentController,
|
||||||
|
builder: (context, contentValue, _) {
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (titleValue.text.isNotEmpty) ...[
|
||||||
|
Text(
|
||||||
|
titleValue.text,
|
||||||
|
style: theme.textTheme.headlineSmall?.copyWith(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(16),
|
||||||
|
],
|
||||||
|
if (descriptionValue.text.isNotEmpty) ...[
|
||||||
|
Text(
|
||||||
|
descriptionValue.text,
|
||||||
|
style: theme.textTheme.bodyLarge?.copyWith(
|
||||||
|
color: colorScheme.onSurface.withOpacity(0.7),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(16),
|
||||||
|
],
|
||||||
|
if (contentValue.text.isNotEmpty)
|
||||||
|
MarkdownTextContent(
|
||||||
|
content: contentValue.text,
|
||||||
|
textStyle: theme.textTheme.bodyMedium,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (isWideScreen(context)) {
|
||||||
|
return Align(alignment: Alignment.topLeft, child: widgetItem);
|
||||||
|
}
|
||||||
|
|
||||||
return Container(
|
return Container(
|
||||||
decoration: BoxDecoration(
|
decoration: BoxDecoration(
|
||||||
border: Border.all(color: colorScheme.outline.withOpacity(0.3)),
|
border: Border.all(color: colorScheme.outline.withOpacity(0.3)),
|
||||||
@@ -178,115 +229,19 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
Expanded(
|
Expanded(child: widgetItem),
|
||||||
child: SingleChildScrollView(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: ValueListenableBuilder<TextEditingValue>(
|
|
||||||
valueListenable: state.titleController,
|
|
||||||
builder: (context, titleValue, _) {
|
|
||||||
return ValueListenableBuilder<TextEditingValue>(
|
|
||||||
valueListenable: state.descriptionController,
|
|
||||||
builder: (context, descriptionValue, _) {
|
|
||||||
return ValueListenableBuilder<TextEditingValue>(
|
|
||||||
valueListenable: state.contentController,
|
|
||||||
builder: (context, contentValue, _) {
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
if (titleValue.text.isNotEmpty) ...[
|
|
||||||
Text(
|
|
||||||
titleValue.text,
|
|
||||||
style: theme.textTheme.headlineSmall
|
|
||||||
?.copyWith(fontWeight: FontWeight.bold),
|
|
||||||
),
|
|
||||||
const Gap(16),
|
|
||||||
],
|
|
||||||
if (descriptionValue.text.isNotEmpty) ...[
|
|
||||||
Text(
|
|
||||||
descriptionValue.text,
|
|
||||||
style: theme.textTheme.bodyLarge?.copyWith(
|
|
||||||
color: colorScheme.onSurface.withOpacity(
|
|
||||||
0.7,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Gap(16),
|
|
||||||
],
|
|
||||||
if (contentValue.text.isNotEmpty)
|
|
||||||
MarkdownTextContent(
|
|
||||||
content: contentValue.text,
|
|
||||||
textStyle: theme.textTheme.bodyMedium,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
Widget buildEditorPane() {
|
Widget buildEditorPane() {
|
||||||
return Column(
|
return Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 560),
|
||||||
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
// Publisher row
|
|
||||||
Card(
|
|
||||||
margin: EdgeInsets.only(top: 8),
|
|
||||||
elevation: 1,
|
|
||||||
child: Padding(
|
|
||||||
padding: const EdgeInsets.all(12),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
GestureDetector(
|
|
||||||
child: ProfilePictureWidget(
|
|
||||||
fileId: state.currentPublisher.value?.picture?.id,
|
|
||||||
radius: 20,
|
|
||||||
fallbackIcon:
|
|
||||||
state.currentPublisher.value == null
|
|
||||||
? Symbols.question_mark
|
|
||||||
: null,
|
|
||||||
),
|
|
||||||
onTap: () {
|
|
||||||
showModalBottomSheet(
|
|
||||||
isScrollControlled: true,
|
|
||||||
context: context,
|
|
||||||
builder: (context) => const PublisherModal(),
|
|
||||||
).then((value) {
|
|
||||||
if (value != null) {
|
|
||||||
state.currentPublisher.value = value;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Gap(16),
|
|
||||||
if (state.currentPublisher.value == null)
|
|
||||||
Text(
|
|
||||||
'postPublisherUnselected'.tr(),
|
|
||||||
style: theme.textTheme.bodyMedium,
|
|
||||||
)
|
|
||||||
else
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(state.currentPublisher.value!.nick).bold(),
|
|
||||||
Text(
|
|
||||||
'@${state.currentPublisher.value!.name}',
|
|
||||||
).fontSize(12),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
|
|
||||||
// Content field with keyboard listener
|
|
||||||
Expanded(
|
Expanded(
|
||||||
child: RawKeyboardListener(
|
child: RawKeyboardListener(
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
@@ -304,7 +259,10 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
border: InputBorder.none,
|
border: InputBorder.none,
|
||||||
hintText: 'postContent'.tr(),
|
hintText: 'postContent'.tr(),
|
||||||
contentPadding: const EdgeInsets.all(8),
|
contentPadding: const EdgeInsets.symmetric(
|
||||||
|
vertical: 16,
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
maxLines: null,
|
maxLines: null,
|
||||||
expands: true,
|
expands: true,
|
||||||
@@ -382,6 +340,8 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -392,7 +352,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
child: AppScaffold(
|
child: AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
title: ValueListenableBuilder<TextEditingValue>(
|
title: ValueListenableBuilder<TextEditingValue>(
|
||||||
@@ -406,39 +366,27 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
actions: [
|
actions: [
|
||||||
// Info banner for article compose
|
// Info banner for article compose
|
||||||
const SizedBox.shrink(),
|
const SizedBox.shrink(),
|
||||||
if (originalPost == null) // Only show drafts for new articles
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.draft),
|
icon: ProfilePictureWidget(
|
||||||
|
fileId: state.currentPublisher.value?.picture?.id,
|
||||||
|
radius: 12,
|
||||||
|
fallbackIcon:
|
||||||
|
state.currentPublisher.value == null
|
||||||
|
? Symbols.question_mark
|
||||||
|
: null,
|
||||||
|
),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
builder:
|
context: context,
|
||||||
(context) => DraftManagerSheet(
|
builder: (context) => const PublisherModal(),
|
||||||
onDraftSelected: (draftId) {
|
).then((value) {
|
||||||
final draft =
|
if (value != null) {
|
||||||
ref.read(
|
state.currentPublisher.value = value;
|
||||||
composeStorageNotifierProvider,
|
|
||||||
)[draftId];
|
|
||||||
if (draft != null) {
|
|
||||||
state.titleController.text = draft.title ?? '';
|
|
||||||
state.descriptionController.text =
|
|
||||||
draft.description ?? '';
|
|
||||||
state.contentController.text =
|
|
||||||
draft.content ?? '';
|
|
||||||
state.visibility.value = draft.visibility;
|
|
||||||
}
|
}
|
||||||
|
});
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
|
||||||
},
|
|
||||||
tooltip: 'drafts'.tr(),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.save),
|
|
||||||
onPressed: () => ComposeLogic.saveDraft(ref, state),
|
|
||||||
tooltip: 'saveDraft'.tr(),
|
|
||||||
),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.settings),
|
icon: const Icon(Symbols.settings),
|
||||||
onPressed: showSettingsSheet,
|
onPressed: showSettingsSheet,
|
||||||
@@ -499,6 +447,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
flex: showPreview.value ? 1 : 2,
|
flex: showPreview.value ? 1 : 2,
|
||||||
child: buildEditorPane(),
|
child: buildEditorPane(),
|
||||||
),
|
),
|
||||||
|
const VerticalDivider(),
|
||||||
if (showPreview.value)
|
if (showPreview.value)
|
||||||
Expanded(child: buildPreviewPane()),
|
Expanded(child: buildPreviewPane()),
|
||||||
],
|
],
|
||||||
@@ -510,27 +459,7 @@ class ArticleComposeScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
|
|
||||||
// Bottom toolbar
|
// Bottom toolbar
|
||||||
Material(
|
ComposeToolbar(state: state, originalPost: originalPost),
|
||||||
elevation: 4,
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => ComposeLogic.pickPhotoMedia(ref, state),
|
|
||||||
icon: const Icon(Symbols.add_a_photo),
|
|
||||||
color: colorScheme.primary,
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
onPressed: () => ComposeLogic.pickVideoMedia(ref, state),
|
|
||||||
icon: const Icon(Symbols.videocam),
|
|
||||||
color: colorScheme.primary,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(
|
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 16,
|
|
||||||
horizontal: 16,
|
|
||||||
top: 8,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
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/post/post_quick_reply.dart';
|
import 'package:island/widgets/post/post_quick_reply.dart';
|
||||||
@@ -54,9 +53,8 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
final postState = ref.watch(postStateProvider(id));
|
final postState = ref.watch(postStateProvider(id));
|
||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
|
|
||||||
final isWide = isWideScreen(context);
|
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
appBar: AppBar(title: const Text('Post')),
|
appBar: AppBar(title: const Text('Post')),
|
||||||
body: postState.when(
|
body: postState.when(
|
||||||
data: (post) {
|
data: (post) {
|
||||||
@@ -66,13 +64,13 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
CustomScrollView(
|
CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: Center(
|
||||||
children: [
|
child: ConstrainedBox(
|
||||||
PostItem(
|
constraints: BoxConstraints(maxWidth: 600),
|
||||||
|
child: PostItem(
|
||||||
item: post!,
|
item: post!,
|
||||||
isOpenable: false,
|
|
||||||
isFullPost: true,
|
isFullPost: true,
|
||||||
backgroundColor: isWide ? Colors.transparent : null,
|
isEmbedReply: false,
|
||||||
onUpdate: (newItem) {
|
onUpdate: (newItem) {
|
||||||
// Update the local state with the new post data
|
// Update the local state with the new post data
|
||||||
ref
|
ref
|
||||||
@@ -80,11 +78,10 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
.updatePost(newItem);
|
.updatePost(newItem);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
PostRepliesList(postId: id),
|
),
|
||||||
|
PostRepliesList(postId: id, maxWidth: 600),
|
||||||
SliverGap(MediaQuery.of(context).padding.bottom + 80),
|
SliverGap(MediaQuery.of(context).padding.bottom + 80),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import 'package:island/models/post.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
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:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
|
|
||||||
final postSearchNotifierProvider = StateNotifierProvider.autoDispose<
|
final postSearchNotifierProvider = StateNotifierProvider.autoDispose<
|
||||||
@@ -55,7 +56,7 @@ class PostSearchNotifier
|
|||||||
'query': _currentQuery,
|
'query': _currentQuery,
|
||||||
'offset': offset,
|
'offset': offset,
|
||||||
'take': _pageSize,
|
'take': _pageSize,
|
||||||
'useVector': true,
|
'useVector': false,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -109,6 +110,7 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: TextField(
|
title: TextField(
|
||||||
controller: _searchController,
|
controller: _searchController,
|
||||||
@@ -140,6 +142,7 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
itemCount: data.items.length + (data.hasMore ? 1 : 0),
|
itemCount: data.items.length + (data.hasMore ? 1 : 0),
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index >= data.items.length) {
|
if (index >= data.items.length) {
|
||||||
@@ -150,14 +153,27 @@ class _PostSearchScreenState extends ConsumerState<PostSearchScreen> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final post = data.items[index];
|
final post = data.items[index];
|
||||||
return Column(
|
return Center(
|
||||||
children: [PostItem(item: post), const Divider(height: 1)],
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: 600),
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
|
child: PostActionableItem(item: post, borderRadius: 8),
|
||||||
|
),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
error:
|
||||||
|
(error, stack) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => ref.invalidate(postSearchNotifierProvider),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ import 'package:island/models/user.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/services/color.dart';
|
import 'package:island/services/color.dart';
|
||||||
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/account/account_name.dart';
|
import 'package:island/widgets/account/account_name.dart';
|
||||||
import 'package:island/widgets/account/badge.dart';
|
import 'package:island/widgets/account/badge.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
@@ -121,50 +122,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
offset: Offset(1.0, 1.0),
|
offset: Offset(1.0, 1.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
return publisher.when(
|
Widget publisherBasisWidget(SnPublisher data) => Row(
|
||||||
data:
|
|
||||||
(data) => AppScaffold(
|
|
||||||
body: CustomScrollView(
|
|
||||||
slivers: [
|
|
||||||
SliverAppBar(
|
|
||||||
foregroundColor: appbarColor.value,
|
|
||||||
expandedHeight: 180,
|
|
||||||
pinned: true,
|
|
||||||
leading: PageBackButton(
|
|
||||||
color: appbarColor.value,
|
|
||||||
shadows: [appbarShadow],
|
|
||||||
),
|
|
||||||
flexibleSpace: Stack(
|
|
||||||
children: [
|
|
||||||
Positioned.fill(
|
|
||||||
child:
|
|
||||||
data.background?.id != null
|
|
||||||
? CloudImageWidget(file: data.background)
|
|
||||||
: Container(
|
|
||||||
color:
|
|
||||||
Theme.of(
|
|
||||||
context,
|
|
||||||
).appBarTheme.backgroundColor,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
FlexibleSpaceBar(
|
|
||||||
title: Text(
|
|
||||||
data.nick,
|
|
||||||
style: TextStyle(
|
|
||||||
color:
|
|
||||||
appbarColor.value ??
|
|
||||||
Theme.of(context).appBarTheme.foregroundColor,
|
|
||||||
shadows: [appbarShadow],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
background:
|
|
||||||
Container(), // Empty container since background is handled by Stack
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
|
||||||
child: Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
@@ -177,13 +135,9 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
size: 16,
|
size: 16,
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
),
|
),
|
||||||
backgroundColor:
|
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||||
Theme.of(context).colorScheme.primary,
|
|
||||||
offset: Offset(0, 48),
|
offset: Offset(0, 48),
|
||||||
child: ProfilePictureWidget(
|
child: ProfilePictureWidget(file: data.picture, radius: 32),
|
||||||
file: data.picture,
|
|
||||||
radius: 32,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
Navigator.pop(context, true);
|
Navigator.pop(context, true);
|
||||||
@@ -205,9 +159,13 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
Text(data.nick).fontSize(20),
|
Text(data.nick).fontSize(20),
|
||||||
if (data.verification != null)
|
if (data.verification != null)
|
||||||
VerificationMark(mark: data.verification!),
|
VerificationMark(mark: data.verification!),
|
||||||
Text(
|
Expanded(
|
||||||
|
child: Text(
|
||||||
'@${data.name}',
|
'@${data.name}',
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
).fontSize(14).opacity(0.85),
|
).fontSize(14).opacity(0.85),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (data.type == 0 && data.account != null)
|
if (data.type == 0 && data.account != null)
|
||||||
@@ -216,16 +174,12 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
data.type == 0
|
data.type == 0 ? Symbols.person : Symbols.workspaces,
|
||||||
? Symbols.person
|
|
||||||
: Symbols.workspaces,
|
|
||||||
fill: 1,
|
fill: 1,
|
||||||
size: 17,
|
size: 17,
|
||||||
),
|
),
|
||||||
Text(
|
Text(
|
||||||
'publisherBelongsTo'.tr(
|
'publisherBelongsTo'.tr(args: ['@${data.account!.name}']),
|
||||||
args: ['@${data.account!.name}'],
|
|
||||||
),
|
|
||||||
).fontSize(14),
|
).fontSize(14),
|
||||||
],
|
],
|
||||||
).opacity(0.85).padding(bottom: 6),
|
).opacity(0.85).padding(bottom: 6),
|
||||||
@@ -256,9 +210,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
: 'subscribe',
|
: 'subscribe',
|
||||||
).tr(),
|
).tr(),
|
||||||
style: ButtonStyle(
|
style: ButtonStyle(
|
||||||
visualDensity: VisualDensity(
|
visualDensity: VisualDensity(vertical: -2),
|
||||||
vertical: -2,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
error: (_, _) => const SizedBox(),
|
error: (_, _) => const SizedBox(),
|
||||||
@@ -269,9 +221,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
child: SizedBox(
|
child: SizedBox(
|
||||||
width: 20,
|
width: 20,
|
||||||
height: 20,
|
height: 20,
|
||||||
child: CircularProgressIndicator(
|
child: CircularProgressIndicator(strokeWidth: 2),
|
||||||
strokeWidth: 2,
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -281,37 +231,157 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, top: 24),
|
).padding(horizontal: 24, top: 24);
|
||||||
),
|
|
||||||
SliverToBoxAdapter(
|
Widget publisherVerificationWidget(SnPublisher data) => Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
if (badges.value?.isNotEmpty ?? false)
|
if (badges.value?.isNotEmpty ?? false)
|
||||||
BadgeList(badges: badges.value!).padding(top: 16),
|
BadgeList(badges: badges.value!).padding(top: 16),
|
||||||
if (data.verification != null)
|
if (data.verification != null)
|
||||||
VerificationStatusCard(
|
VerificationStatusCard(mark: data.verification!),
|
||||||
mark: data.verification!,
|
|
||||||
).padding(top: 16),
|
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24),
|
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
).padding(top: 16);
|
||||||
child: const Divider(height: 1).padding(vertical: 24),
|
|
||||||
),
|
Widget publisherDetailWidget(SnPublisher data) => Card(
|
||||||
SliverToBoxAdapter(
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Text('bio').tr().bold(),
|
Text('bio').tr().bold().padding(bottom: 2),
|
||||||
Text(
|
Text(data.bio.isEmpty ? 'descriptionNone'.tr() : data.bio),
|
||||||
data.bio.isEmpty ? 'descriptionNone'.tr() : data.bio,
|
],
|
||||||
|
).padding(horizontal: 20, vertical: 16),
|
||||||
|
);
|
||||||
|
|
||||||
|
return publisher.when(
|
||||||
|
data:
|
||||||
|
(data) => AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
|
appBar:
|
||||||
|
isWideScreen(context)
|
||||||
|
? AppBar(
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
|
leading: PageBackButton(
|
||||||
|
color: appbarColor.value,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
flexibleSpace: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child:
|
||||||
|
data.background?.id != null
|
||||||
|
? CloudImageWidget(file: data.background)
|
||||||
|
: Container(
|
||||||
|
color:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
data.nick,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.foregroundColor,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
background:
|
||||||
|
Container(), // Empty container since background is handled by Stack
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24),
|
|
||||||
),
|
),
|
||||||
|
)
|
||||||
|
: null,
|
||||||
|
body:
|
||||||
|
isWideScreen(context)
|
||||||
|
? Row(
|
||||||
|
children: [
|
||||||
|
Flexible(
|
||||||
|
flex: 4,
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverGap(16),
|
||||||
|
SliverPostList(pubName: name),
|
||||||
|
SliverGap(
|
||||||
|
MediaQuery.of(context).padding.bottom + 16,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(left: 8),
|
||||||
|
),
|
||||||
|
Flexible(
|
||||||
|
flex: 3,
|
||||||
|
child: Align(
|
||||||
|
alignment: Alignment.topLeft,
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
publisherBasisWidget(data),
|
||||||
|
publisherVerificationWidget(data),
|
||||||
|
publisherDetailWidget(data),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
SliverAppBar(
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
|
expandedHeight: 180,
|
||||||
|
pinned: true,
|
||||||
|
leading: PageBackButton(
|
||||||
|
color: appbarColor.value,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
flexibleSpace: Stack(
|
||||||
|
children: [
|
||||||
|
Positioned.fill(
|
||||||
|
child:
|
||||||
|
data.background?.id != null
|
||||||
|
? CloudImageWidget(
|
||||||
|
file: data.background,
|
||||||
|
)
|
||||||
|
: Container(
|
||||||
|
color:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
data.nick,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).appBarTheme.foregroundColor,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
background:
|
||||||
|
Container(), // Empty container since background is handled by Stack
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
SliverToBoxAdapter(child: publisherBasisWidget(data)),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: const Divider(height: 1).padding(top: 24),
|
child: publisherVerificationWidget(data),
|
||||||
),
|
),
|
||||||
|
SliverToBoxAdapter(child: publisherDetailWidget(data)),
|
||||||
SliverPostList(pubName: name),
|
SliverPostList(pubName: name),
|
||||||
SliverGap(MediaQuery.of(context).padding.bottom + 16),
|
SliverGap(MediaQuery.of(context).padding.bottom + 16),
|
||||||
],
|
],
|
||||||
@@ -319,11 +389,13 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
error:
|
error:
|
||||||
(error, stackTrace) => AppScaffold(
|
(error, stackTrace) => AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
appBar: AppBar(leading: const PageBackButton()),
|
appBar: AppBar(leading: const PageBackButton()),
|
||||||
body: Center(child: Text(error.toString())),
|
body: Center(child: Text(error.toString())),
|
||||||
),
|
),
|
||||||
loading:
|
loading:
|
||||||
() => AppScaffold(
|
() => AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
appBar: AppBar(leading: const PageBackButton()),
|
appBar: AppBar(leading: const PageBackButton()),
|
||||||
body: Center(child: CircularProgressIndicator()),
|
body: Center(child: CircularProgressIndicator()),
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part of 'pub_profile.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$publisherHash() => r'3a7ae4d48765170aea42c7d6f4502d68f984dfab';
|
String _$publisherHash() => r'a1da21f0275421382e2882fd52c4e061c4675cf7';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -145,7 +145,7 @@ class _PublisherProviderElement
|
|||||||
String get uname => (origin as PublisherProvider).uname;
|
String get uname => (origin as PublisherProvider).uname;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$publisherBadgesHash() => r'a5781deded7e682a781ccd7854418f050438e3f4';
|
String _$publisherBadgesHash() => r'527efad74225fbacf558ac5db160ecce53a60c62';
|
||||||
|
|
||||||
/// See also [publisherBadges].
|
/// See also [publisherBadges].
|
||||||
@ProviderFor(publisherBadges)
|
@ProviderFor(publisherBadges)
|
||||||
@@ -268,7 +268,7 @@ class _PublisherBadgesProviderElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$publisherSubscriptionStatusHash() =>
|
String _$publisherSubscriptionStatusHash() =>
|
||||||
r'4eb6741c40775c814e71b6a98b8f1e2d84bf7e30';
|
r'634262ce519e1c8288267df11e08e1d4acaa4a44';
|
||||||
|
|
||||||
/// See also [publisherSubscriptionStatus].
|
/// See also [publisherSubscriptionStatus].
|
||||||
@ProviderFor(publisherSubscriptionStatus)
|
@ProviderFor(publisherSubscriptionStatus)
|
||||||
|
|||||||
@@ -79,7 +79,7 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
body: realmState.when(
|
body: realmState.when(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (error, _) => Center(child: Text('Error: $error')),
|
error: (error, _) => Center(child: Text('Error: $error')),
|
||||||
|
|||||||
@@ -41,7 +41,7 @@ class RealmListScreen extends HookConsumerWidget {
|
|||||||
final realmInvites = ref.watch(realmInvitesProvider);
|
final realmInvites = ref.watch(realmInvitesProvider);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('realms').tr(),
|
title: const Text('realms').tr(),
|
||||||
actions: [
|
actions: [
|
||||||
@@ -279,7 +279,7 @@ class EditRealmScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(slug == null ? 'createRealm'.tr() : 'editRealm'.tr()),
|
title: Text(slug == null ? 'createRealm'.tr() : 'editRealm'.tr()),
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
|
|||||||
@@ -552,7 +552,7 @@ class SettingsScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
noBackground: false,
|
isNoBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text('settings').tr(),
|
title: Text('settings').tr(),
|
||||||
actions:
|
actions:
|
||||||
|
|||||||
@@ -22,11 +22,11 @@ class AccountName extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var nameStyle = (style ?? TextStyle());
|
var nameStyle = (style ?? TextStyle());
|
||||||
if (account.profile.stellarMembership != null) {
|
if (account.perkSubscription != null) {
|
||||||
nameStyle = nameStyle.copyWith(
|
nameStyle = nameStyle.copyWith(
|
||||||
color: (switch (account.profile.stellarMembership!.identifier) {
|
color: (switch (account.perkSubscription!.identifier) {
|
||||||
'solian.stellar.primary' => Colors.blueAccent,
|
'solian.stellar.primary' => Colors.blueAccent,
|
||||||
'solian.stellar.nova' => Colors.indigoAccent,
|
'solian.stellar.nova' => Color.fromRGBO(57, 197, 187, 1),
|
||||||
'solian.stellar.supernova' => Colors.amberAccent,
|
'solian.stellar.supernova' => Colors.amberAccent,
|
||||||
_ => null,
|
_ => null,
|
||||||
}),
|
}),
|
||||||
@@ -38,8 +38,8 @@ class AccountName extends StatelessWidget {
|
|||||||
spacing: 4,
|
spacing: 4,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: Text(account.nick, style: nameStyle)),
|
Flexible(child: Text(account.nick, style: nameStyle)),
|
||||||
if (account.profile.stellarMembership != null)
|
if (account.perkSubscription != null)
|
||||||
StellarMembershipMark(membership: account.profile.stellarMembership!),
|
StellarMembershipMark(membership: account.perkSubscription!),
|
||||||
if (account.profile.verification != null)
|
if (account.profile.verification != null)
|
||||||
VerificationMark(mark: account.profile.verification!),
|
VerificationMark(mark: account.profile.verification!),
|
||||||
],
|
],
|
||||||
@@ -101,7 +101,7 @@ class StellarMembershipMark extends StatelessWidget {
|
|||||||
case 'solian.stellar.primary':
|
case 'solian.stellar.primary':
|
||||||
return Colors.blue;
|
return Colors.blue;
|
||||||
case 'solian.stellar.nova':
|
case 'solian.stellar.nova':
|
||||||
return Colors.indigo;
|
return Color.fromRGBO(57, 197, 187, 1);
|
||||||
case 'solian.stellar.supernova':
|
case 'solian.stellar.supernova':
|
||||||
return Colors.amber;
|
return Colors.amber;
|
||||||
default:
|
default:
|
||||||
@@ -115,7 +115,7 @@ class StellarMembershipMark extends StatelessWidget {
|
|||||||
|
|
||||||
final tierName = _getMembershipTierName(membership.identifier);
|
final tierName = _getMembershipTierName(membership.identifier);
|
||||||
final tierColor = _getMembershipTierColor(membership.identifier);
|
final tierColor = _getMembershipTierColor(membership.identifier);
|
||||||
final tierIcon = Symbols.award_star;
|
final tierIcon = Symbols.kid_star;
|
||||||
|
|
||||||
return Tooltip(
|
return Tooltip(
|
||||||
richMessage: TextSpan(
|
richMessage: TextSpan(
|
||||||
@@ -140,9 +140,7 @@ class VerificationStatusCard extends StatelessWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return Card(
|
return Column(
|
||||||
margin: EdgeInsets.zero,
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
@@ -163,7 +161,6 @@ class VerificationStatusCard extends StatelessWidget {
|
|||||||
'Verified by\n${mark.verifiedBy ?? 'No one verified it'}',
|
'Verified by\n${mark.verifiedBy ?? 'No one verified it'}',
|
||||||
).fontSize(11).opacity(0.8),
|
).fontSize(11).opacity(0.8),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 24, vertical: 16),
|
).padding(horizontal: 24, vertical: 16);
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ class AccountProfileCard extends HookConsumerWidget {
|
|||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final account = ref.watch(accountProvider(uname));
|
final account = ref.watch(accountProvider(uname));
|
||||||
final width =
|
final width =
|
||||||
math.max(MediaQuery.of(context).size.width - 80, 360).toDouble();
|
math.min(MediaQuery.of(context).size.width - 80, 360).toDouble();
|
||||||
return PopupCard(
|
return PopupCard(
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
||||||
@@ -105,7 +105,10 @@ class AccountProfileCard extends HookConsumerWidget {
|
|||||||
FilledButton.tonalIcon(
|
FilledButton.tonalIcon(
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
Navigator.pop(context);
|
Navigator.pop(context);
|
||||||
context.pushNamed('accountProfile', pathParameters: {'name': data.name});
|
context.pushNamed(
|
||||||
|
'accountProfile',
|
||||||
|
pathParameters: {'name': data.name},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
icon: const Icon(Symbols.launch),
|
icon: const Icon(Symbols.launch),
|
||||||
label: Text('accountProfileView').tr(),
|
label: Text('accountProfileView').tr(),
|
||||||
@@ -164,6 +167,7 @@ Future<void> showAccountProfileCard(
|
|||||||
offset: offset ?? Offset.zero,
|
offset: offset ?? Offset.zero,
|
||||||
context: context,
|
context: context,
|
||||||
builder: (context) => AccountProfileCard(uname: uname),
|
builder: (context) => AccountProfileCard(uname: uname),
|
||||||
|
alignment: Alignment.center,
|
||||||
dimBackground: true,
|
dimBackground: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,8 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
|
|
||||||
final String? eventCalanderUser;
|
final String? eventCalanderUser;
|
||||||
|
|
||||||
|
final EdgeInsets? margin;
|
||||||
|
|
||||||
const FortuneGraphWidget({
|
const FortuneGraphWidget({
|
||||||
super.key,
|
super.key,
|
||||||
required this.events,
|
required this.events,
|
||||||
@@ -34,6 +36,7 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
this.height = 180,
|
this.height = 180,
|
||||||
this.onPointSelected,
|
this.onPointSelected,
|
||||||
this.eventCalanderUser,
|
this.eventCalanderUser,
|
||||||
|
this.margin,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -249,7 +252,7 @@ class FortuneGraphWidget extends HookConsumerWidget {
|
|||||||
if (constrainWidth) {
|
if (constrainWidth) {
|
||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: maxWidth),
|
constraints: BoxConstraints(maxWidth: maxWidth),
|
||||||
child: Card(margin: EdgeInsets.all(16), child: content),
|
child: Card(margin: margin ?? EdgeInsets.all(16), child: content),
|
||||||
).center();
|
).center();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -86,6 +86,7 @@ class AccountStatusCreationWidget extends HookConsumerWidget {
|
|||||||
onTap: () {
|
onTap: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
context: context,
|
context: context,
|
||||||
|
useRootNavigator: true,
|
||||||
builder:
|
builder:
|
||||||
(context) => AccountStatusCreationSheet(
|
(context) => AccountStatusCreationSheet(
|
||||||
initialStatus:
|
initialStatus:
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ class AccountStatusCreationSheet extends HookConsumerWidget {
|
|||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
final apiClient = ref.read(apiClientProvider);
|
final apiClient = ref.read(apiClientProvider);
|
||||||
await apiClient.request(
|
await apiClient.request(
|
||||||
'/accounts/me/statuses',
|
'/id/accounts/me/statuses',
|
||||||
data: {
|
data: {
|
||||||
'attitude': attitude.value,
|
'attitude': attitude.value,
|
||||||
'is_invisible': isInvisible.value,
|
'is_invisible': isInvisible.value,
|
||||||
|
|||||||
@@ -165,7 +165,7 @@ class AppScaffold extends StatelessWidget {
|
|||||||
final AppBar? appBar;
|
final AppBar? appBar;
|
||||||
final DrawerCallback? onDrawerChanged;
|
final DrawerCallback? onDrawerChanged;
|
||||||
final DrawerCallback? onEndDrawerChanged;
|
final DrawerCallback? onEndDrawerChanged;
|
||||||
final bool? noBackground;
|
final bool? isNoBackground;
|
||||||
final bool? extendBody;
|
final bool? extendBody;
|
||||||
|
|
||||||
const AppScaffold({
|
const AppScaffold({
|
||||||
@@ -181,7 +181,7 @@ class AppScaffold extends StatelessWidget {
|
|||||||
this.endDrawer,
|
this.endDrawer,
|
||||||
this.onDrawerChanged,
|
this.onDrawerChanged,
|
||||||
this.onEndDrawerChanged,
|
this.onEndDrawerChanged,
|
||||||
this.noBackground,
|
this.isNoBackground,
|
||||||
this.extendBody,
|
this.extendBody,
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -190,7 +190,7 @@ class AppScaffold extends StatelessWidget {
|
|||||||
final appBarHeight = appBar?.preferredSize.height ?? 0;
|
final appBarHeight = appBar?.preferredSize.height ?? 0;
|
||||||
final safeTop = MediaQuery.of(context).padding.top;
|
final safeTop = MediaQuery.of(context).padding.top;
|
||||||
|
|
||||||
final noBackground = this.noBackground ?? isWideScreen(context);
|
final noBackground = isNoBackground ?? isWideScreen(context);
|
||||||
|
|
||||||
final content = Column(
|
final content = Column(
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -4,9 +4,11 @@ import 'package:go_router/go_router.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/pods/call.dart';
|
import 'package:island/pods/call.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/chat/call_participant_tile.dart';
|
import 'package:island/widgets/chat/call_participant_tile.dart';
|
||||||
import 'package:island/widgets/content/sheet.dart';
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
|
|
||||||
@@ -55,7 +57,49 @@ class CallControlsBar extends HookConsumerWidget {
|
|||||||
const Gap(16),
|
const Gap(16),
|
||||||
_buildCircularButton(
|
_buildCircularButton(
|
||||||
icon: Icons.call_end,
|
icon: Icons.call_end,
|
||||||
onPressed: () => callNotifier.disconnect(),
|
onPressed:
|
||||||
|
() => showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
useRootNavigator: true,
|
||||||
|
builder:
|
||||||
|
(context) => ClipRRect(
|
||||||
|
borderRadius: BorderRadius.only(
|
||||||
|
topLeft: Radius.circular(8),
|
||||||
|
topRight: Radius.circular(8),
|
||||||
|
),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Symbols.logout, fill: 1),
|
||||||
|
title: Text('callLeave').tr(),
|
||||||
|
onTap: () {
|
||||||
|
callNotifier.disconnect();
|
||||||
|
GoRouter.of(context).pop();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: const Icon(Symbols.call_end, fill: 1),
|
||||||
|
iconColor: Colors.red,
|
||||||
|
title: Text('callEnd').tr(),
|
||||||
|
onTap: () async {
|
||||||
|
callNotifier.disconnect();
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
await apiClient.delete(
|
||||||
|
'/sphere/chat/realtime/${callNotifier.roomId}',
|
||||||
|
);
|
||||||
|
callNotifier.dispose();
|
||||||
|
if (context.mounted) {
|
||||||
|
GoRouter.of(context).pop();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
Gap(MediaQuery.of(context).padding.bottom),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
backgroundColor: const Color(0xFFE53E3E),
|
backgroundColor: const Color(0xFFE53E3E),
|
||||||
iconColor: Colors.white,
|
iconColor: Colors.white,
|
||||||
),
|
),
|
||||||
@@ -279,7 +323,7 @@ class CallOverlayBar extends HookConsumerWidget {
|
|||||||
child: Card(
|
child: Card(
|
||||||
margin: EdgeInsets.zero,
|
margin: EdgeInsets.zero,
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
@@ -294,17 +338,7 @@ class CallOverlayBar extends HookConsumerWidget {
|
|||||||
height: 40,
|
height: 40,
|
||||||
child:
|
child:
|
||||||
SpeakingRippleAvatar(
|
SpeakingRippleAvatar(
|
||||||
isSpeaking: lastSpeaker.isSpeaking,
|
live: lastSpeaker,
|
||||||
audioLevel:
|
|
||||||
lastSpeaker.remoteParticipant.audioLevel,
|
|
||||||
pictureId:
|
|
||||||
lastSpeaker
|
|
||||||
.participant
|
|
||||||
.profile
|
|
||||||
?.account
|
|
||||||
.profile
|
|
||||||
.picture
|
|
||||||
?.id,
|
|
||||||
size: 36,
|
size: 36,
|
||||||
).center(),
|
).center(),
|
||||||
);
|
);
|
||||||
@@ -314,10 +348,7 @@ class CallOverlayBar extends HookConsumerWidget {
|
|||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text('@${lastSpeaker.participant.identity}').bold(),
|
||||||
lastSpeaker.participant.profile?.account.nick ??
|
|
||||||
'unknown'.tr(),
|
|
||||||
).bold(),
|
|
||||||
Text(
|
Text(
|
||||||
formatDuration(callState.duration),
|
formatDuration(callState.duration),
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
@@ -360,7 +391,10 @@ class CallOverlayBar extends HookConsumerWidget {
|
|||||||
).padding(all: 16),
|
).padding(all: 16),
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed('chatCall', pathParameters: {'id': callNotifier.roomId!});
|
context.pushNamed(
|
||||||
|
'chatCall',
|
||||||
|
pathParameters: {'id': callNotifier.roomId!},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
94
lib/widgets/chat/call_participant_card.dart
Normal file
94
lib/widgets/chat/call_participant_card.dart
Normal file
@@ -0,0 +1,94 @@
|
|||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_popup_card/flutter_popup_card.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/pods/call.dart';
|
||||||
|
import 'package:island/widgets/account/account_nameplate.dart';
|
||||||
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
class CallParticipantCard extends HookConsumerWidget {
|
||||||
|
final CallParticipantLive live;
|
||||||
|
const CallParticipantCard({super.key, required this.live});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final width =
|
||||||
|
math.min(MediaQuery.of(context).size.width - 80, 360).toDouble();
|
||||||
|
return PopupCard(
|
||||||
|
elevation: 8,
|
||||||
|
shape: RoundedRectangleBorder(borderRadius: BorderRadius.circular(12.0)),
|
||||||
|
child: SizedBox(
|
||||||
|
width: width,
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Column(
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.wifi, size: 16),
|
||||||
|
const Gap(8),
|
||||||
|
Text(switch (live.remoteParticipant.connectionQuality) {
|
||||||
|
ConnectionQuality.excellent => 'Excellent',
|
||||||
|
ConnectionQuality.good => 'Good',
|
||||||
|
ConnectionQuality.poor => 'Bad',
|
||||||
|
ConnectionQuality.lost => 'Lost',
|
||||||
|
_ => 'Connecting',
|
||||||
|
}),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20, top: 16),
|
||||||
|
AccountNameplate(
|
||||||
|
name: live.participant.identity,
|
||||||
|
isOutlined: false,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
class CallParticipantGestureDetector extends StatelessWidget {
|
||||||
|
final CallParticipantLive participant;
|
||||||
|
final Widget child;
|
||||||
|
const CallParticipantGestureDetector({
|
||||||
|
super.key,
|
||||||
|
required this.participant,
|
||||||
|
required this.child,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context) {
|
||||||
|
return GestureDetector(
|
||||||
|
child: child,
|
||||||
|
onTapDown: (details) {
|
||||||
|
showCallParticipantCard(
|
||||||
|
context,
|
||||||
|
participant,
|
||||||
|
offset: details.localPosition,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> showCallParticipantCard(
|
||||||
|
BuildContext context,
|
||||||
|
CallParticipantLive participant, {
|
||||||
|
Offset? offset,
|
||||||
|
}) async {
|
||||||
|
await showPopupCard<void>(
|
||||||
|
offset: offset ?? Offset.zero,
|
||||||
|
context: context,
|
||||||
|
builder: (context) => CallParticipantCard(live: participant),
|
||||||
|
alignment: Alignment.center,
|
||||||
|
dimBackground: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
@@ -1,32 +1,33 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/pods/call.dart';
|
import 'package:island/pods/call.dart';
|
||||||
|
import 'package:island/screens/account/profile.dart';
|
||||||
|
import 'package:island/widgets/chat/call_participant_card.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:livekit_client/livekit_client.dart';
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
class SpeakingRippleAvatar extends StatelessWidget {
|
class SpeakingRippleAvatar extends HookConsumerWidget {
|
||||||
final bool isSpeaking;
|
final CallParticipantLive live;
|
||||||
final double audioLevel;
|
|
||||||
final String? pictureId;
|
|
||||||
final double size;
|
final double size;
|
||||||
|
|
||||||
const SpeakingRippleAvatar({
|
const SpeakingRippleAvatar({super.key, required this.live, this.size = 96});
|
||||||
super.key,
|
|
||||||
required this.isSpeaking,
|
|
||||||
required this.audioLevel,
|
|
||||||
required this.pictureId,
|
|
||||||
this.size = 96,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final account = ref.watch(accountProvider(live.participant.identity));
|
||||||
|
|
||||||
final avatarRadius = size / 2;
|
final avatarRadius = size / 2;
|
||||||
final clampedLevel = audioLevel.clamp(0.0, 1.0);
|
final clampedLevel = live.remoteParticipant.audioLevel.clamp(0.0, 1.0);
|
||||||
final rippleRadius = avatarRadius + clampedLevel * (size * 0.333);
|
final rippleRadius = avatarRadius + clampedLevel * (size * 0.333);
|
||||||
return TweenAnimationBuilder<double>(
|
return SizedBox(
|
||||||
|
width: size + 8,
|
||||||
|
height: size + 8,
|
||||||
|
child: TweenAnimationBuilder<double>(
|
||||||
tween: Tween<double>(
|
tween: Tween<double>(
|
||||||
begin: avatarRadius,
|
begin: avatarRadius,
|
||||||
end: isSpeaking ? rippleRadius : avatarRadius,
|
end: live.remoteParticipant.isSpeaking ? rippleRadius : avatarRadius,
|
||||||
),
|
),
|
||||||
duration: const Duration(milliseconds: 250),
|
duration: const Duration(milliseconds: 250),
|
||||||
curve: Curves.easeOut,
|
curve: Curves.easeOut,
|
||||||
@@ -34,7 +35,7 @@ class SpeakingRippleAvatar extends StatelessWidget {
|
|||||||
return Stack(
|
return Stack(
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
children: [
|
children: [
|
||||||
if (isSpeaking)
|
if (live.remoteParticipant.isSpeaking)
|
||||||
Container(
|
Container(
|
||||||
width: animatedRadius * 2,
|
width: animatedRadius * 2,
|
||||||
height: animatedRadius * 2,
|
height: animatedRadius * 2,
|
||||||
@@ -48,36 +49,71 @@ class SpeakingRippleAvatar extends StatelessWidget {
|
|||||||
height: size,
|
height: size,
|
||||||
alignment: Alignment.center,
|
alignment: Alignment.center,
|
||||||
decoration: BoxDecoration(shape: BoxShape.circle),
|
decoration: BoxDecoration(shape: BoxShape.circle),
|
||||||
child: ProfilePictureWidget(fileId: pictureId, radius: size / 2),
|
child: account.when(
|
||||||
|
data:
|
||||||
|
(value) => CallParticipantGestureDetector(
|
||||||
|
participant: live,
|
||||||
|
child: ProfilePictureWidget(
|
||||||
|
file: value.profile.picture,
|
||||||
|
radius: size / 2,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
error:
|
||||||
|
(_, _) => CircleAvatar(
|
||||||
|
radius: size / 2,
|
||||||
|
child: const Icon(Symbols.person_remove),
|
||||||
|
),
|
||||||
|
loading:
|
||||||
|
() => CircleAvatar(
|
||||||
|
radius: size / 2,
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (live.remoteParticipant.isMuted)
|
||||||
|
Positioned(
|
||||||
|
bottom: 4,
|
||||||
|
right: 4,
|
||||||
|
child: Container(
|
||||||
|
width: 20,
|
||||||
|
height: 20,
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Colors.red,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(10)),
|
||||||
|
),
|
||||||
|
child: const Icon(
|
||||||
|
Symbols.mic_off,
|
||||||
|
size: 14,
|
||||||
|
fill: 1,
|
||||||
|
).padding(left: 1.5, top: 1.5),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class CallParticipantTile extends StatelessWidget {
|
class CallParticipantTile extends HookConsumerWidget {
|
||||||
final CallParticipantLive live;
|
final CallParticipantLive live;
|
||||||
|
|
||||||
const CallParticipantTile({super.key, required this.live});
|
const CallParticipantTile({super.key, required this.live});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final hasVideo =
|
final hasVideo =
|
||||||
live.hasVideo &&
|
live.hasVideo &&
|
||||||
live.remoteParticipant.trackPublications.values
|
live.remoteParticipant.trackPublications.values
|
||||||
.where((pub) => pub.track != null && pub.kind == TrackType.VIDEO)
|
.where((pub) => pub.track != null && pub.kind == TrackType.VIDEO)
|
||||||
.isNotEmpty;
|
.isNotEmpty;
|
||||||
final audioLevel = live.remoteParticipant.audioLevel;
|
|
||||||
|
|
||||||
if (hasVideo) {
|
if (hasVideo) {
|
||||||
return Stack(
|
return Stack(
|
||||||
fit: StackFit.loose,
|
fit: StackFit.loose,
|
||||||
children: [
|
children: [
|
||||||
Container(
|
AspectRatio(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
|
||||||
child: AspectRatio(
|
|
||||||
aspectRatio: 16 / 9,
|
aspectRatio: 16 / 9,
|
||||||
child: VideoTrackRenderer(
|
child: VideoTrackRenderer(
|
||||||
live.remoteParticipant.trackPublications.values
|
live.remoteParticipant.trackPublications.values
|
||||||
@@ -88,27 +124,31 @@ class CallParticipantTile extends StatelessWidget {
|
|||||||
renderMode: VideoRenderMode.platformView,
|
renderMode: VideoRenderMode.platformView,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
|
||||||
Positioned(
|
Positioned(
|
||||||
left: 8,
|
left: 8,
|
||||||
right: 8,
|
right: 8,
|
||||||
bottom: 8,
|
bottom: 8,
|
||||||
child: Text(
|
child: Text(
|
||||||
live.participant.profile?.account.nick ??
|
'@${live.participant.name}',
|
||||||
'${'unknown'.tr()}\'s video',
|
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
style: const TextStyle(fontSize: 14, color: Colors.white),
|
style: const TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color: Colors.white,
|
||||||
|
shadows: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
offset: Offset(1, 1),
|
||||||
|
spreadRadius: 8,
|
||||||
|
blurRadius: 8,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
} else {
|
} else {
|
||||||
return SpeakingRippleAvatar(
|
return SpeakingRippleAvatar(size: 84, live: live);
|
||||||
isSpeaking: live.isSpeaking,
|
|
||||||
audioLevel: audioLevel,
|
|
||||||
pictureId: live.participant.profile?.account.profile.picture?.id,
|
|
||||||
size: 84,
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,15 +5,19 @@ 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/services.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.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/database/message.dart';
|
import 'package:island/database/message.dart';
|
||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:island/models/embed.dart';
|
import 'package:island/models/embed.dart';
|
||||||
import 'package:island/pods/call.dart';
|
import 'package:island/pods/call.dart';
|
||||||
|
import 'package:island/pods/translate.dart';
|
||||||
import 'package:island/screens/chat/room.dart';
|
import 'package:island/screens/chat/room.dart';
|
||||||
|
import 'package:island/widgets/account/account_name.dart';
|
||||||
import 'package:island/widgets/account/account_pfc.dart';
|
import 'package:island/widgets/account/account_pfc.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/content/alert.native.dart';
|
||||||
import 'package:island/widgets/content/cloud_file_collection.dart';
|
import 'package:island/widgets/content/cloud_file_collection.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/content/embed/link.dart';
|
import 'package:island/widgets/content/embed/link.dart';
|
||||||
@@ -66,6 +70,46 @@ class MessageItem extends HookConsumerWidget {
|
|||||||
|
|
||||||
final isMobile = !kIsWeb && (Platform.isAndroid || Platform.isIOS);
|
final isMobile = !kIsWeb && (Platform.isAndroid || Platform.isIOS);
|
||||||
|
|
||||||
|
final messageLanguage =
|
||||||
|
remoteMessage.content != null
|
||||||
|
? ref.watch(detectStringLanguageProvider(remoteMessage.content!))
|
||||||
|
: null;
|
||||||
|
|
||||||
|
final currentLanguage = context.locale.toString();
|
||||||
|
final translatableLanguage =
|
||||||
|
messageLanguage != null
|
||||||
|
? messageLanguage.substring(0, 2) != currentLanguage.substring(0, 2)
|
||||||
|
: false;
|
||||||
|
|
||||||
|
final translating = useState(false);
|
||||||
|
final translatedText = useState<String?>(null);
|
||||||
|
|
||||||
|
Future<void> translate() async {
|
||||||
|
if (translatedText.value != null) {
|
||||||
|
translatedText.value = null;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (translating.value) return;
|
||||||
|
if (remoteMessage.content == null) return;
|
||||||
|
translating.value = true;
|
||||||
|
try {
|
||||||
|
final text = await ref.watch(
|
||||||
|
translateStringProvider(
|
||||||
|
TranslateQuery(
|
||||||
|
text: remoteMessage.content!,
|
||||||
|
lang: currentLanguage.substring(0, 2),
|
||||||
|
),
|
||||||
|
).future,
|
||||||
|
);
|
||||||
|
translatedText.value = text;
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
} finally {
|
||||||
|
translating.value = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return ContextMenuWidget(
|
return ContextMenuWidget(
|
||||||
menuProvider: (_) {
|
menuProvider: (_) {
|
||||||
if (onAction == null) return Menu(children: []);
|
if (onAction == null) return Menu(children: []);
|
||||||
@@ -102,6 +146,18 @@ class MessageItem extends HookConsumerWidget {
|
|||||||
onAction!.call(MessageItemAction.forward);
|
onAction!.call(MessageItemAction.forward);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
if (translatableLanguage) MenuSeparator(),
|
||||||
|
if (translatableLanguage)
|
||||||
|
MenuAction(
|
||||||
|
title:
|
||||||
|
translatedText.value == null
|
||||||
|
? 'translate'.tr()
|
||||||
|
: translating.value
|
||||||
|
? 'translating'.tr()
|
||||||
|
: 'translated'.tr(),
|
||||||
|
image: MenuImage.icon(Symbols.translate),
|
||||||
|
callback: translate,
|
||||||
|
),
|
||||||
if (isMobile) MenuSeparator(),
|
if (isMobile) MenuSeparator(),
|
||||||
if (isMobile)
|
if (isMobile)
|
||||||
MenuAction(
|
MenuAction(
|
||||||
@@ -166,8 +222,8 @@ class MessageItem extends HookConsumerWidget {
|
|||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
spacing: 5,
|
spacing: 5,
|
||||||
children: [
|
children: [
|
||||||
Text(
|
AccountName(
|
||||||
sender.account.nick,
|
account: sender.account,
|
||||||
style: Theme.of(context).textTheme.bodySmall,
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
),
|
),
|
||||||
Badge(
|
Badge(
|
||||||
@@ -220,14 +276,18 @@ class MessageItem extends HookConsumerWidget {
|
|||||||
isReply: false,
|
isReply: false,
|
||||||
).padding(vertical: 4),
|
).padding(vertical: 4),
|
||||||
if (_MessageItemContent.hasContent(remoteMessage))
|
if (_MessageItemContent.hasContent(remoteMessage))
|
||||||
_MessageItemContent(item: remoteMessage),
|
_MessageItemContent(
|
||||||
|
item: remoteMessage,
|
||||||
|
translatedText: translatedText.value,
|
||||||
|
),
|
||||||
if (remoteMessage.attachments.isNotEmpty)
|
if (remoteMessage.attachments.isNotEmpty)
|
||||||
LayoutBuilder(
|
LayoutBuilder(
|
||||||
builder: (context, constraints) {
|
builder: (context, constraints) {
|
||||||
return CloudFileList(
|
return CloudFileList(
|
||||||
files: remoteMessage.attachments,
|
files: remoteMessage.attachments,
|
||||||
maxWidth: constraints.maxWidth,
|
maxWidth: constraints.maxWidth,
|
||||||
).padding(vertical: 4);
|
padding: EdgeInsets.symmetric(vertical: 4),
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (remoteMessage.meta['embeds'] != null)
|
if (remoteMessage.meta['embeds'] != null)
|
||||||
@@ -480,7 +540,8 @@ class MessageQuoteWidget extends HookConsumerWidget {
|
|||||||
|
|
||||||
class _MessageItemContent extends StatelessWidget {
|
class _MessageItemContent extends StatelessWidget {
|
||||||
final SnChatMessage item;
|
final SnChatMessage item;
|
||||||
const _MessageItemContent({required this.item});
|
final String? translatedText;
|
||||||
|
const _MessageItemContent({required this.item, this.translatedText});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
@@ -493,10 +554,40 @@ class _MessageItemContent extends StatelessWidget {
|
|||||||
);
|
);
|
||||||
case 'text':
|
case 'text':
|
||||||
default:
|
default:
|
||||||
return MarkdownTextContent(
|
return Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
MarkdownTextContent(
|
||||||
content: item.content!,
|
content: item.content!,
|
||||||
isSelectable: true,
|
isSelectable: true,
|
||||||
linesMargin: EdgeInsets.zero,
|
linesMargin: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
if (translatedText?.isNotEmpty ?? false)
|
||||||
|
...([
|
||||||
|
ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(
|
||||||
|
maxWidth: math.min(
|
||||||
|
280,
|
||||||
|
MediaQuery.of(context).size.width * 0.4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Text('translated').tr().fontSize(11).opacity(0.75),
|
||||||
|
const Gap(8),
|
||||||
|
Flexible(child: Divider()),
|
||||||
|
],
|
||||||
|
).padding(vertical: 4),
|
||||||
|
),
|
||||||
|
MarkdownTextContent(
|
||||||
|
content: translatedText!,
|
||||||
|
isSelectable: true,
|
||||||
|
linesMargin: EdgeInsets.zero,
|
||||||
|
),
|
||||||
|
]),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ Future<SnCheckInResult?> checkInResultToday(Ref ref) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class CheckInWidget extends HookConsumerWidget {
|
class CheckInWidget extends HookConsumerWidget {
|
||||||
const CheckInWidget({super.key});
|
final EdgeInsets? margin;
|
||||||
|
const CheckInWidget({super.key, this.margin});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -66,7 +67,8 @@ class CheckInWidget extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return Card(
|
return Card(
|
||||||
margin: EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
margin:
|
||||||
|
margin ?? EdgeInsets.only(left: 16, right: 16, top: 16, bottom: 8),
|
||||||
child: Row(
|
child: Row(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
spacing: 16,
|
spacing: 16,
|
||||||
|
|||||||
@@ -30,7 +30,11 @@ class AttachmentPreview extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
var ratio =
|
var ratio =
|
||||||
(item.isOnCloud ? (item.data.fileMeta?['ratio'] ?? 1) : 1).toDouble();
|
item.isOnCloud
|
||||||
|
? (item.data.fileMeta?['ratio'] is num
|
||||||
|
? item.data.fileMeta!['ratio'].toDouble()
|
||||||
|
: 1.0)
|
||||||
|
: 1.0;
|
||||||
if (ratio == 0) ratio = 1.0;
|
if (ratio == 0) ratio = 1.0;
|
||||||
|
|
||||||
return AspectRatio(
|
return AspectRatio(
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ import 'package:island/pods/network.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';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:path/path.dart' show extension;
|
import 'package:path/path.dart' show extension;
|
||||||
import 'package:path_provider/path_provider.dart';
|
import 'package:path_provider/path_provider.dart';
|
||||||
import 'package:photo_view/photo_view.dart';
|
import 'package:photo_view/photo_view.dart';
|
||||||
@@ -26,13 +27,17 @@ class CloudFileList extends HookConsumerWidget {
|
|||||||
final double maxWidth;
|
final double maxWidth;
|
||||||
final double? minWidth;
|
final double? minWidth;
|
||||||
final bool disableZoomIn;
|
final bool disableZoomIn;
|
||||||
|
final bool disableConstraint;
|
||||||
|
final EdgeInsets? padding;
|
||||||
const CloudFileList({
|
const CloudFileList({
|
||||||
super.key,
|
super.key,
|
||||||
required this.files,
|
required this.files,
|
||||||
this.maxHeight = 360,
|
this.maxHeight = 560,
|
||||||
this.maxWidth = double.infinity,
|
this.maxWidth = double.infinity,
|
||||||
this.minWidth,
|
this.minWidth,
|
||||||
this.disableZoomIn = false,
|
this.disableZoomIn = false,
|
||||||
|
this.disableConstraint = false,
|
||||||
|
this.padding,
|
||||||
});
|
});
|
||||||
|
|
||||||
double calculateAspectRatio() {
|
double calculateAspectRatio() {
|
||||||
@@ -58,15 +63,17 @@ class CloudFileList extends HookConsumerWidget {
|
|||||||
if (files.isEmpty) return const SizedBox.shrink();
|
if (files.isEmpty) return const SizedBox.shrink();
|
||||||
if (files.length == 1) {
|
if (files.length == 1) {
|
||||||
final isImage = files.first.mimeType?.startsWith('image') ?? false;
|
final isImage = files.first.mimeType?.startsWith('image') ?? false;
|
||||||
return ConstrainedBox(
|
return Container(
|
||||||
|
padding: padding,
|
||||||
constraints: BoxConstraints(
|
constraints: BoxConstraints(
|
||||||
maxHeight: maxHeight,
|
maxHeight: disableConstraint ? double.infinity : maxHeight,
|
||||||
minWidth: minWidth ?? 0,
|
minWidth: minWidth ?? 0,
|
||||||
|
maxWidth: files.length == 1 ? maxWidth : double.infinity,
|
||||||
),
|
),
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: calculateAspectRatio(),
|
aspectRatio: calculateAspectRatio(),
|
||||||
child: ClipRRect(
|
child: ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
child: _CloudFileListEntry(
|
child: _CloudFileListEntry(
|
||||||
file: files.first,
|
file: files.first,
|
||||||
heroTag: heroTags.first,
|
heroTag: heroTags.first,
|
||||||
@@ -86,7 +93,7 @@ class CloudFileList extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
).padding(horizontal: 3);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
final allImages =
|
final allImages =
|
||||||
@@ -100,22 +107,37 @@ class CloudFileList extends HookConsumerWidget {
|
|||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: calculateAspectRatio(),
|
aspectRatio: calculateAspectRatio(),
|
||||||
child: CarouselView(
|
child: CarouselView(
|
||||||
|
padding: padding,
|
||||||
|
itemSnapping: true,
|
||||||
itemExtent: math.min(
|
itemExtent: math.min(
|
||||||
MediaQuery.of(context).size.width * 0.85,
|
MediaQuery.of(context).size.width * 0.85,
|
||||||
maxWidth * 0.85,
|
maxWidth * 0.85,
|
||||||
),
|
),
|
||||||
itemSnapping: true,
|
|
||||||
shape: RoundedRectangleBorder(
|
shape: RoundedRectangleBorder(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||||
),
|
),
|
||||||
children: [
|
children: [
|
||||||
for (var i = 0; i < files.length; i++)
|
for (var i = 0; i < files.length; i++)
|
||||||
|
Stack(
|
||||||
|
children: [
|
||||||
_CloudFileListEntry(
|
_CloudFileListEntry(
|
||||||
file: files[i],
|
file: files[i],
|
||||||
heroTag: heroTags[i],
|
heroTag: heroTags[i],
|
||||||
isImage: files[i].mimeType?.startsWith('image') ?? false,
|
isImage: files[i].mimeType?.startsWith('image') ?? false,
|
||||||
disableZoomIn: disableZoomIn,
|
disableZoomIn: disableZoomIn,
|
||||||
fit: BoxFit.cover,
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 12,
|
||||||
|
left: 16,
|
||||||
|
child: Text('${i + 1}/${files.length}')
|
||||||
|
.textColor(Colors.white)
|
||||||
|
.textShadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
offset: Offset(1, 1),
|
||||||
|
blurRadius: 3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
onTap: (i) {
|
onTap: (i) {
|
||||||
@@ -141,17 +163,26 @@ class CloudFileList extends HookConsumerWidget {
|
|||||||
child: ListView.separated(
|
child: ListView.separated(
|
||||||
scrollDirection: Axis.horizontal,
|
scrollDirection: Axis.horizontal,
|
||||||
itemCount: files.length,
|
itemCount: files.length,
|
||||||
padding: EdgeInsets.symmetric(horizontal: 3),
|
padding: padding,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
return ClipRRect(
|
return AspectRatio(
|
||||||
|
aspectRatio:
|
||||||
|
files[index].fileMeta?['ratio'] is num
|
||||||
|
? files[index].fileMeta!['ratio'].toDouble()
|
||||||
|
: 1.0,
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
ClipRRect(
|
||||||
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
borderRadius: const BorderRadius.all(Radius.circular(16)),
|
||||||
child: _CloudFileListEntry(
|
child: _CloudFileListEntry(
|
||||||
file: files[index],
|
file: files[index],
|
||||||
heroTag: heroTags[index],
|
heroTag: heroTags[index],
|
||||||
isImage: files[index].mimeType?.startsWith('image') ?? false,
|
isImage:
|
||||||
|
files[index].mimeType?.startsWith('image') ?? false,
|
||||||
disableZoomIn: disableZoomIn,
|
disableZoomIn: disableZoomIn,
|
||||||
onTap: () {
|
onTap: () {
|
||||||
if (!(files[index].mimeType?.startsWith('image') ?? false)) {
|
if (!(files[index].mimeType?.startsWith('image') ??
|
||||||
|
false)) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (!disableZoomIn) {
|
if (!disableZoomIn) {
|
||||||
@@ -160,10 +191,25 @@ class CloudFileList extends HookConsumerWidget {
|
|||||||
item: files[index],
|
item: files[index],
|
||||||
heroTag: heroTags[index],
|
heroTag: heroTags[index],
|
||||||
),
|
),
|
||||||
|
rootNavigator: true,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 12,
|
||||||
|
left: 16,
|
||||||
|
child: Text('${index + 1}/${files.length}')
|
||||||
|
.textColor(Colors.white)
|
||||||
|
.textShadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
offset: Offset(1, 1),
|
||||||
|
blurRadius: 3,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (_, _) => const Gap(8),
|
separatorBuilder: (_, _) => const Gap(8),
|
||||||
@@ -184,6 +230,8 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
final photoViewController = useMemoized(() => PhotoViewController(), []);
|
final photoViewController = useMemoized(() => PhotoViewController(), []);
|
||||||
final rotation = useState(0);
|
final rotation = useState(0);
|
||||||
|
|
||||||
|
final showOriginal = useState(false);
|
||||||
|
|
||||||
Future<void> saveToGallery() async {
|
Future<void> saveToGallery() async {
|
||||||
try {
|
try {
|
||||||
// Show loading indicator
|
// Show loading indicator
|
||||||
@@ -197,7 +245,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
final filePath = '${tempDir.path}/${item.id}.${extension(item.name)}';
|
final filePath = '${tempDir.path}/${item.id}.${extension(item.name)}';
|
||||||
|
|
||||||
await client.download(
|
await client.download(
|
||||||
'/files/${item.id}',
|
'/drive/files/${item.id}',
|
||||||
filePath,
|
filePath,
|
||||||
queryParameters: {'original': true},
|
queryParameters: {'original': true},
|
||||||
);
|
);
|
||||||
@@ -347,7 +395,7 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
imageProvider: CloudImageWidget.provider(
|
imageProvider: CloudImageWidget.provider(
|
||||||
fileId: item.id,
|
fileId: item.id,
|
||||||
serverUrl: serverUrl,
|
serverUrl: serverUrl,
|
||||||
original: true,
|
original: showOriginal.value,
|
||||||
),
|
),
|
||||||
// Apply rotation transformation
|
// Apply rotation transformation
|
||||||
customSize: MediaQuery.of(context).size,
|
customSize: MediaQuery.of(context).size,
|
||||||
@@ -381,6 +429,23 @@ class CloudFileZoomIn extends HookConsumerWidget {
|
|||||||
saveToGallery();
|
saveToGallery();
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
showOriginal.value = !showOriginal.value;
|
||||||
|
},
|
||||||
|
icon: Icon(
|
||||||
|
showOriginal.value ? Symbols.raw_on : Symbols.raw_off,
|
||||||
|
color: Colors.white,
|
||||||
|
size: 24,
|
||||||
|
shadows: [
|
||||||
|
Shadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
blurRadius: 5.0,
|
||||||
|
offset: Offset(1.0, 1.0),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -488,7 +553,6 @@ class _CloudFileListEntry extends StatelessWidget {
|
|||||||
final bool isImage;
|
final bool isImage;
|
||||||
final bool disableZoomIn;
|
final bool disableZoomIn;
|
||||||
final VoidCallback? onTap;
|
final VoidCallback? onTap;
|
||||||
final BoxFit fit;
|
|
||||||
|
|
||||||
const _CloudFileListEntry({
|
const _CloudFileListEntry({
|
||||||
required this.file,
|
required this.file,
|
||||||
@@ -496,7 +560,6 @@ class _CloudFileListEntry extends StatelessWidget {
|
|||||||
required this.isImage,
|
required this.isImage,
|
||||||
required this.disableZoomIn,
|
required this.disableZoomIn,
|
||||||
this.onTap,
|
this.onTap,
|
||||||
this.fit = BoxFit.contain,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -519,10 +582,10 @@ class _CloudFileListEntry extends StatelessWidget {
|
|||||||
item: file,
|
item: file,
|
||||||
heroTag: heroTag,
|
heroTag: heroTag,
|
||||||
noBlurhash: true,
|
noBlurhash: true,
|
||||||
fit: fit,
|
fit: BoxFit.contain,
|
||||||
)
|
)
|
||||||
else
|
else
|
||||||
CloudFileWidget(item: file, heroTag: heroTag, fit: fit),
|
CloudFileWidget(item: file, heroTag: heroTag, fit: BoxFit.contain),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,11 @@
|
|||||||
import 'package:cached_network_image/cached_network_image.dart';
|
import 'package:cached_network_image/cached_network_image.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_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: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';
|
||||||
|
|
||||||
@@ -30,8 +33,6 @@ class CloudFileWidget extends ConsumerWidget {
|
|||||||
var ratio =
|
var ratio =
|
||||||
item.fileMeta?['ratio'] is num
|
item.fileMeta?['ratio'] is num
|
||||||
? item.fileMeta!['ratio'].toDouble()
|
? item.fileMeta!['ratio'].toDouble()
|
||||||
: item.fileMeta?['ratio'] is String
|
|
||||||
? double.parse(item.fileMeta!['ratio'])
|
|
||||||
: 1.0;
|
: 1.0;
|
||||||
if (ratio == 0) ratio = 1.0;
|
if (ratio == 0) ratio = 1.0;
|
||||||
final content = switch (item.mimeType?.split('/').firstOrNull) {
|
final content = switch (item.mimeType?.split('/').firstOrNull) {
|
||||||
@@ -39,12 +40,15 @@ class CloudFileWidget extends ConsumerWidget {
|
|||||||
aspectRatio: ratio,
|
aspectRatio: ratio,
|
||||||
child: UniversalImage(
|
child: UniversalImage(
|
||||||
uri: uri,
|
uri: uri,
|
||||||
blurHash: noBlurhash ? null : item.fileMeta?['blur'],
|
blurHash:
|
||||||
|
noBlurhash
|
||||||
|
? null
|
||||||
|
: (item.fileMeta is String ? item.fileMeta!['blur'] : null),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
"video" => AspectRatio(
|
"video" => AspectRatio(
|
||||||
aspectRatio: ratio,
|
aspectRatio: ratio,
|
||||||
child: UniversalVideo(uri: uri, aspectRatio: ratio),
|
child: CloudVideoWidget(item: item),
|
||||||
),
|
),
|
||||||
_ => Text('Unable render for ${item.mimeType}'),
|
_ => Text('Unable render for ${item.mimeType}'),
|
||||||
};
|
};
|
||||||
@@ -57,6 +61,119 @@ class CloudFileWidget extends ConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class CloudVideoWidget extends HookConsumerWidget {
|
||||||
|
final SnCloudFile item;
|
||||||
|
const CloudVideoWidget({super.key, required this.item});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final open = useState(false);
|
||||||
|
|
||||||
|
final serverUrl = ref.watch(serverUrlProvider);
|
||||||
|
final uri = '$serverUrl/drive/files/${item.id}';
|
||||||
|
|
||||||
|
var ratio =
|
||||||
|
item.fileMeta?['ratio'] is num
|
||||||
|
? item.fileMeta!['ratio'].toDouble()
|
||||||
|
: 1.0;
|
||||||
|
if (ratio == 0) ratio = 1.0;
|
||||||
|
|
||||||
|
if (open.value) {
|
||||||
|
return UniversalVideo(uri: uri, aspectRatio: ratio, autoplay: true);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GestureDetector(
|
||||||
|
child: Stack(
|
||||||
|
children: [
|
||||||
|
UniversalImage(uri: '$uri?thumbnail=true'),
|
||||||
|
Positioned.fill(
|
||||||
|
child: Center(
|
||||||
|
child: const Icon(
|
||||||
|
Symbols.play_arrow,
|
||||||
|
fill: 1,
|
||||||
|
size: 32,
|
||||||
|
shadows: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
offset: Offset(1, 1),
|
||||||
|
spreadRadius: 8,
|
||||||
|
blurRadius: 8,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
bottom: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
child: Column(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Row(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
if (item.fileMeta?['duration'] != null)
|
||||||
|
Text(
|
||||||
|
Duration(
|
||||||
|
milliseconds:
|
||||||
|
((item.fileMeta?['duration'] as num) * 1000)
|
||||||
|
.toInt(),
|
||||||
|
).formatDuration(),
|
||||||
|
style: TextStyle(
|
||||||
|
shadows: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
offset: Offset(1, 1),
|
||||||
|
spreadRadius: 8,
|
||||||
|
blurRadius: 8,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (item.fileMeta?['bit_rate'] != null)
|
||||||
|
Text(
|
||||||
|
'${int.parse(item.fileMeta?['bit_rate'] as String) ~/ 1000} Kbps',
|
||||||
|
style: TextStyle(
|
||||||
|
shadows: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
offset: Offset(1, 1),
|
||||||
|
spreadRadius: 8,
|
||||||
|
blurRadius: 8,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
item.name,
|
||||||
|
style: TextStyle(
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
shadows: [
|
||||||
|
BoxShadow(
|
||||||
|
color: Colors.black54,
|
||||||
|
offset: Offset(1, 1),
|
||||||
|
spreadRadius: 8,
|
||||||
|
blurRadius: 8,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
).padding(horizontal: 16, bottom: 12),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
open.value = true;
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class CloudImageWidget extends ConsumerWidget {
|
class CloudImageWidget extends ConsumerWidget {
|
||||||
final String? fileId;
|
final String? fileId;
|
||||||
final SnCloudFile? file;
|
final SnCloudFile? file;
|
||||||
@@ -91,7 +208,10 @@ class CloudImageWidget extends ConsumerWidget {
|
|||||||
required String serverUrl,
|
required String serverUrl,
|
||||||
bool original = false,
|
bool original = false,
|
||||||
}) {
|
}) {
|
||||||
final uri = '$serverUrl/drive/files/$fileId?original=$original';
|
final uri =
|
||||||
|
original
|
||||||
|
? '$serverUrl/drive/files/$fileId?original=true'
|
||||||
|
: '$serverUrl/drive/files/$fileId';
|
||||||
return CachedNetworkImageProvider(uri);
|
return CachedNetworkImageProvider(uri);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,10 +11,12 @@ import 'package:media_kit_video/media_kit_video.dart';
|
|||||||
class UniversalVideo extends ConsumerStatefulWidget {
|
class UniversalVideo extends ConsumerStatefulWidget {
|
||||||
final String uri;
|
final String uri;
|
||||||
final double aspectRatio;
|
final double aspectRatio;
|
||||||
|
final bool autoplay;
|
||||||
const UniversalVideo({
|
const UniversalVideo({
|
||||||
super.key,
|
super.key,
|
||||||
required this.uri,
|
required this.uri,
|
||||||
this.aspectRatio = 16 / 9,
|
this.aspectRatio = 16 / 9,
|
||||||
|
this.autoplay = false,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -47,7 +49,7 @@ class _UniversalVideoState extends ConsumerState<UniversalVideo> {
|
|||||||
log('[MediaPlayer] Hit cache: $url');
|
log('[MediaPlayer] Hit cache: $url');
|
||||||
}
|
}
|
||||||
|
|
||||||
_player!.open(Media(uri), play: false);
|
_player!.open(Media(uri), play: widget.autoplay);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'package:dio/dio.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
@@ -13,7 +14,10 @@ import 'package:island/pods/network.dart';
|
|||||||
import 'package:island/services/file.dart';
|
import 'package:island/services/file.dart';
|
||||||
import 'package:island/services/compose_storage_db.dart';
|
import 'package:island/services/compose_storage_db.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:pasteboard/pasteboard.dart';
|
import 'package:pasteboard/pasteboard.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:developer';
|
import 'dart:developer';
|
||||||
|
|
||||||
@@ -60,6 +64,9 @@ class ComposeState {
|
|||||||
_autoSaveTimer?.cancel();
|
_autoSaveTimer?.cancel();
|
||||||
_autoSaveTimer = null;
|
_autoSaveTimer = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool get isEmpty =>
|
||||||
|
attachments.value.isEmpty && contentController.text.isEmpty;
|
||||||
}
|
}
|
||||||
|
|
||||||
class ComposeLogic {
|
class ComposeLogic {
|
||||||
@@ -392,6 +399,95 @@ class ComposeLogic {
|
|||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static Future<void> linkAttachment(
|
||||||
|
WidgetRef ref,
|
||||||
|
ComposeState state,
|
||||||
|
BuildContext context,
|
||||||
|
) async {
|
||||||
|
final TextEditingController idController = TextEditingController();
|
||||||
|
String? errorMessage;
|
||||||
|
|
||||||
|
await showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (BuildContext dialogContext) {
|
||||||
|
return StatefulBuilder(
|
||||||
|
builder: (context, setState) {
|
||||||
|
return SheetScaffold(
|
||||||
|
titleText: 'linkAttachment'.tr(),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
TextField(
|
||||||
|
controller: idController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'fileId'.tr(),
|
||||||
|
helperText: 'fileIdHint'.tr(),
|
||||||
|
helperMaxLines: 3,
|
||||||
|
errorText: errorMessage,
|
||||||
|
border: OutlineInputBorder(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(16),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: TextButton.icon(
|
||||||
|
icon: const Icon(Symbols.add),
|
||||||
|
label: Text('add'.tr()),
|
||||||
|
onPressed: () async {
|
||||||
|
final fileId = idController.text.trim();
|
||||||
|
if (fileId.isEmpty) {
|
||||||
|
setState(() {
|
||||||
|
errorMessage = 'fileIdCannotBeEmpty'.tr();
|
||||||
|
});
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
final client = ref.read(apiClientProvider);
|
||||||
|
final response = await client.get(
|
||||||
|
'/drive/files/$fileId/info',
|
||||||
|
);
|
||||||
|
final SnCloudFile cloudFile = SnCloudFile.fromJson(
|
||||||
|
response.data,
|
||||||
|
);
|
||||||
|
|
||||||
|
state.attachments.value = [
|
||||||
|
...state.attachments.value,
|
||||||
|
UniversalFile(
|
||||||
|
data: cloudFile,
|
||||||
|
type: switch (cloudFile.mimeType
|
||||||
|
?.split('/')
|
||||||
|
.firstOrNull) {
|
||||||
|
'image' => UniversalFileType.image,
|
||||||
|
'video' => UniversalFileType.video,
|
||||||
|
'audio' => UniversalFileType.audio,
|
||||||
|
_ => UniversalFileType.file,
|
||||||
|
},
|
||||||
|
),
|
||||||
|
];
|
||||||
|
if (context.mounted) {
|
||||||
|
Navigator.of(dialogContext).pop();
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
setState(() {
|
||||||
|
errorMessage = 'failedToFetchFile'.tr(
|
||||||
|
args: [e.toString()],
|
||||||
|
);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24, vertical: 24),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
static Future<void> uploadAttachment(
|
static Future<void> uploadAttachment(
|
||||||
WidgetRef ref,
|
WidgetRef ref,
|
||||||
ComposeState state,
|
ComposeState state,
|
||||||
|
|||||||
107
lib/widgets/post/compose_toolbar.dart
Normal file
107
lib/widgets/post/compose_toolbar.dart
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/post.dart';
|
||||||
|
import 'package:island/services/compose_storage_db.dart';
|
||||||
|
import 'package:island/widgets/post/compose_shared.dart';
|
||||||
|
import 'package:island/widgets/post/draft_manager.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
class ComposeToolbar extends HookConsumerWidget {
|
||||||
|
final ComposeState state;
|
||||||
|
final SnPost? originalPost;
|
||||||
|
|
||||||
|
const ComposeToolbar({super.key, required this.state, this.originalPost});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
void pickPhotoMedia() {
|
||||||
|
ComposeLogic.pickPhotoMedia(ref, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void pickVideoMedia() {
|
||||||
|
ComposeLogic.pickVideoMedia(ref, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void linkAttachment() {
|
||||||
|
ComposeLogic.linkAttachment(ref, state, context);
|
||||||
|
}
|
||||||
|
|
||||||
|
void saveDraft() {
|
||||||
|
ComposeLogic.saveDraft(ref, state);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showDraftManager() {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder:
|
||||||
|
(context) => DraftManagerSheet(
|
||||||
|
onDraftSelected: (draftId) {
|
||||||
|
final draft = ref.read(composeStorageNotifierProvider)[draftId];
|
||||||
|
if (draft != null) {
|
||||||
|
state.titleController.text = draft.title ?? '';
|
||||||
|
state.descriptionController.text = draft.description ?? '';
|
||||||
|
state.contentController.text = draft.content ?? '';
|
||||||
|
state.visibility.value = draft.visibility;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
|
||||||
|
return Material(
|
||||||
|
elevation: 4,
|
||||||
|
child: Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: const BoxConstraints(maxWidth: 560),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
onPressed: pickPhotoMedia,
|
||||||
|
tooltip: 'addPhoto'.tr(),
|
||||||
|
icon: const Icon(Symbols.add_a_photo),
|
||||||
|
color: colorScheme.primary,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: pickVideoMedia,
|
||||||
|
tooltip: 'addVideo'.tr(),
|
||||||
|
icon: const Icon(Symbols.videocam),
|
||||||
|
color: colorScheme.primary,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: linkAttachment,
|
||||||
|
icon: const Icon(Symbols.attach_file),
|
||||||
|
tooltip: 'linkAttachment'.tr(),
|
||||||
|
color: colorScheme.primary,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
if (originalPost == null && state.isEmpty)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.draft),
|
||||||
|
color: colorScheme.primary,
|
||||||
|
onPressed: showDraftManager,
|
||||||
|
tooltip: 'drafts'.tr(),
|
||||||
|
)
|
||||||
|
else if (originalPost == null)
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.save),
|
||||||
|
color: colorScheme.primary,
|
||||||
|
onPressed: saveDraft,
|
||||||
|
onLongPress: showDraftManager,
|
||||||
|
tooltip: 'saveDraft'.tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(
|
||||||
|
bottom: MediaQuery.of(context).padding.bottom + 16,
|
||||||
|
horizontal: 16,
|
||||||
|
top: 8,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
152
lib/widgets/post/post_item.g.dart
Normal file
152
lib/widgets/post/post_item.g.dart
Normal file
@@ -0,0 +1,152 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'post_item.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$postFeaturedReplyHash() => r'3f0ac0d51ad21f8754a63dd94109eb8ac4812293';
|
||||||
|
|
||||||
|
/// Copied from Dart SDK
|
||||||
|
class _SystemHash {
|
||||||
|
_SystemHash._();
|
||||||
|
|
||||||
|
static int combine(int hash, int value) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + value);
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||||
|
return hash ^ (hash >> 6);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int finish(int hash) {
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||||
|
// ignore: parameter_assignments
|
||||||
|
hash = hash ^ (hash >> 11);
|
||||||
|
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [postFeaturedReply].
|
||||||
|
@ProviderFor(postFeaturedReply)
|
||||||
|
const postFeaturedReplyProvider = PostFeaturedReplyFamily();
|
||||||
|
|
||||||
|
/// See also [postFeaturedReply].
|
||||||
|
class PostFeaturedReplyFamily extends Family<AsyncValue<SnPost?>> {
|
||||||
|
/// See also [postFeaturedReply].
|
||||||
|
const PostFeaturedReplyFamily();
|
||||||
|
|
||||||
|
/// See also [postFeaturedReply].
|
||||||
|
PostFeaturedReplyProvider call(String id) {
|
||||||
|
return PostFeaturedReplyProvider(id);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PostFeaturedReplyProvider getProviderOverride(
|
||||||
|
covariant PostFeaturedReplyProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.id);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||||
|
|
||||||
|
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||||
|
_allTransitiveDependencies;
|
||||||
|
|
||||||
|
@override
|
||||||
|
String? get name => r'postFeaturedReplyProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [postFeaturedReply].
|
||||||
|
class PostFeaturedReplyProvider extends AutoDisposeFutureProvider<SnPost?> {
|
||||||
|
/// See also [postFeaturedReply].
|
||||||
|
PostFeaturedReplyProvider(String id)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => postFeaturedReply(ref as PostFeaturedReplyRef, id),
|
||||||
|
from: postFeaturedReplyProvider,
|
||||||
|
name: r'postFeaturedReplyProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$postFeaturedReplyHash,
|
||||||
|
dependencies: PostFeaturedReplyFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
PostFeaturedReplyFamily._allTransitiveDependencies,
|
||||||
|
id: id,
|
||||||
|
);
|
||||||
|
|
||||||
|
PostFeaturedReplyProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.id,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String id;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<SnPost?> Function(PostFeaturedReplyRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: PostFeaturedReplyProvider._internal(
|
||||||
|
(ref) => create(ref as PostFeaturedReplyRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
id: id,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<SnPost?> createElement() {
|
||||||
|
return _PostFeaturedReplyProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is PostFeaturedReplyProvider && other.id == id;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, id.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin PostFeaturedReplyRef on AutoDisposeFutureProviderRef<SnPost?> {
|
||||||
|
/// The parameter `id` of this provider.
|
||||||
|
String get id;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostFeaturedReplyProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<SnPost?>
|
||||||
|
with PostFeaturedReplyRef {
|
||||||
|
_PostFeaturedReplyProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get id => (origin as PostFeaturedReplyProvider).id;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
@@ -45,7 +45,9 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
title: 'edit'.tr(),
|
title: 'edit'.tr(),
|
||||||
image: MenuImage.icon(Symbols.edit),
|
image: MenuImage.icon(Symbols.edit),
|
||||||
callback: () {
|
callback: () {
|
||||||
context.pushNamed('postEdit', pathParameters: {'id': item.id}).then((value) {
|
context
|
||||||
|
.pushNamed('postEdit', pathParameters: {'id': item.id})
|
||||||
|
.then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
onRefresh?.call();
|
onRefresh?.call();
|
||||||
}
|
}
|
||||||
@@ -80,7 +82,10 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
image: MenuImage.icon(Symbols.link),
|
image: MenuImage.icon(Symbols.link),
|
||||||
callback: () {
|
callback: () {
|
||||||
// Copy post link to clipboard
|
// Copy post link to clipboard
|
||||||
context.pushNamed('postDetail', pathParameters: {'id': item.id});
|
context.pushNamed(
|
||||||
|
'postDetail',
|
||||||
|
pathParameters: {'id': item.id},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -88,8 +93,6 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
child: Material(
|
child: Material(
|
||||||
color: backgroundColor ?? Theme.of(context).colorScheme.surface,
|
color: backgroundColor ?? Theme.of(context).colorScheme.surface,
|
||||||
borderRadius: BorderRadius.circular(12),
|
|
||||||
elevation: 1,
|
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
borderRadius: BorderRadius.circular(12),
|
borderRadius: BorderRadius.circular(12),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -197,8 +200,8 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
CloudFileList(
|
CloudFileList(
|
||||||
files: item.attachments,
|
files: item.attachments,
|
||||||
maxWidth: MediaQuery.of(context).size.width * 0.85,
|
maxWidth: MediaQuery.of(context).size.width * 0.85,
|
||||||
minWidth: MediaQuery.of(context).size.width * 0.9,
|
padding: EdgeInsets.only(top: 8),
|
||||||
).padding(top: 8),
|
),
|
||||||
|
|
||||||
// Reference post indicator
|
// Reference post indicator
|
||||||
if (item.repliedPost != null || item.forwardedPost != null)
|
if (item.repliedPost != null || item.forwardedPost != null)
|
||||||
@@ -211,7 +214,7 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
size: 16,
|
size: 16,
|
||||||
color: Theme.of(context).colorScheme.secondary,
|
color: Theme.of(context).colorScheme.secondary,
|
||||||
),
|
),
|
||||||
const SizedBox(width: 4),
|
const Gap(4),
|
||||||
Text(
|
Text(
|
||||||
item.repliedPost != null
|
item.repliedPost != null
|
||||||
? 'repliedTo'.tr()
|
? 'repliedTo'.tr()
|
||||||
@@ -364,6 +367,7 @@ class PostItemCreator extends HookConsumerWidget {
|
|||||||
PostReactionList(
|
PostReactionList(
|
||||||
parentId: item.id,
|
parentId: item.id,
|
||||||
reactions: item.reactionsCount,
|
reactions: item.reactionsCount,
|
||||||
|
reactionsMade: item.reactionsMade,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
const Gap(16),
|
const Gap(16),
|
||||||
|
|||||||
@@ -94,9 +94,7 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
|
|
||||||
final post = data.items[index];
|
final post = data.items[index];
|
||||||
|
|
||||||
return Column(
|
return _buildPostItem(post);
|
||||||
children: [_buildPostItem(post), const Divider(height: 1)],
|
|
||||||
);
|
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -105,16 +103,24 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
Widget _buildPostItem(SnPost post) {
|
Widget _buildPostItem(SnPost post) {
|
||||||
switch (itemType) {
|
switch (itemType) {
|
||||||
case PostItemType.creator:
|
case PostItemType.creator:
|
||||||
return PostItemCreator(
|
return Column(
|
||||||
|
children: [
|
||||||
|
PostItemCreator(
|
||||||
item: post,
|
item: post,
|
||||||
backgroundColor: backgroundColor,
|
backgroundColor: backgroundColor,
|
||||||
padding: padding,
|
padding: padding,
|
||||||
isOpenable: isOpenable,
|
isOpenable: isOpenable,
|
||||||
onRefresh: onRefresh,
|
onRefresh: onRefresh,
|
||||||
onUpdate: onUpdate,
|
onUpdate: onUpdate,
|
||||||
|
),
|
||||||
|
const Divider(),
|
||||||
|
],
|
||||||
);
|
);
|
||||||
case PostItemType.regular:
|
case PostItemType.regular:
|
||||||
return PostItem(item: post);
|
return Card(
|
||||||
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
|
child: PostActionableItem(item: post, borderRadius: 8),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,6 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
|
||||||
import 'package:island/widgets/post/post_item.dart';
|
import 'package:island/widgets/post/post_item.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';
|
||||||
@@ -56,17 +55,17 @@ class PostRepliesNotifier extends _$PostRepliesNotifier
|
|||||||
|
|
||||||
class PostRepliesList extends HookConsumerWidget {
|
class PostRepliesList extends HookConsumerWidget {
|
||||||
final String postId;
|
final String postId;
|
||||||
final Color? backgroundColor;
|
final double? maxWidth;
|
||||||
|
final VoidCallback? onOpen;
|
||||||
const PostRepliesList({
|
const PostRepliesList({
|
||||||
super.key,
|
super.key,
|
||||||
required this.postId,
|
required this.postId,
|
||||||
this.backgroundColor,
|
this.maxWidth,
|
||||||
|
this.onOpen,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final isWide = isWideScreen(context);
|
|
||||||
|
|
||||||
return PagingHelperSliverView(
|
return PagingHelperSliverView(
|
||||||
provider: postRepliesNotifierProvider(postId),
|
provider: postRepliesNotifierProvider(postId),
|
||||||
futureRefreshable: postRepliesNotifierProvider(postId).future,
|
futureRefreshable: postRepliesNotifierProvider(postId).future,
|
||||||
@@ -93,16 +92,24 @@ class PostRepliesList extends HookConsumerWidget {
|
|||||||
return endItemView;
|
return endItemView;
|
||||||
}
|
}
|
||||||
|
|
||||||
return Column(
|
final contentWidget = Card(
|
||||||
children: [
|
margin: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
||||||
PostItem(
|
child: PostActionableItem(
|
||||||
|
borderRadius: 8,
|
||||||
item: data.items[index],
|
item: data.items[index],
|
||||||
backgroundColor:
|
isShowReference: false,
|
||||||
backgroundColor ?? (isWide ? Colors.transparent : null),
|
isEmbedOpenable: true,
|
||||||
showReferencePost: false,
|
onOpen: onOpen,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
if (maxWidth == null) return contentWidget;
|
||||||
|
|
||||||
|
return Center(
|
||||||
|
child: ConstrainedBox(
|
||||||
|
constraints: BoxConstraints(maxWidth: maxWidth!),
|
||||||
|
child: contentWidget,
|
||||||
),
|
),
|
||||||
const Divider(height: 1),
|
|
||||||
],
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -27,7 +27,9 @@ class PostRepliesSheet extends HookConsumerWidget {
|
|||||||
slivers: [
|
slivers: [
|
||||||
PostRepliesList(
|
PostRepliesList(
|
||||||
postId: post.id.toString(),
|
postId: post.id.toString(),
|
||||||
backgroundColor: Colors.transparent,
|
onOpen: () {
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@@ -27,9 +27,13 @@ class PublisherCard extends ConsumerWidget {
|
|||||||
|
|
||||||
Widget card = Card(
|
Widget card = Card(
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed('publisherProfile', pathParameters: {'name': publisher.name});
|
context.pushNamed(
|
||||||
|
'publisherProfile',
|
||||||
|
pathParameters: {'name': publisher.name},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: 16 / 7,
|
aspectRatio: 16 / 7,
|
||||||
|
|||||||
@@ -29,9 +29,13 @@ class RealmCard extends ConsumerWidget {
|
|||||||
|
|
||||||
Widget card = Card(
|
Widget card = Card(
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () {
|
onTap: () {
|
||||||
context.pushNamed('realmDetail', pathParameters: {'slug': realm.slug});
|
context.pushNamed(
|
||||||
|
'realmDetail',
|
||||||
|
pathParameters: {'slug': realm.slug},
|
||||||
|
);
|
||||||
},
|
},
|
||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: 16 / 7,
|
aspectRatio: 16 / 7,
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ class WebArticleCard extends StatelessWidget {
|
|||||||
return ConstrainedBox(
|
return ConstrainedBox(
|
||||||
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
|
constraints: BoxConstraints(maxWidth: maxWidth ?? double.infinity),
|
||||||
child: Card(
|
child: Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
clipBehavior: Clip.antiAlias,
|
clipBehavior: Clip.antiAlias,
|
||||||
child: InkWell(
|
child: InkWell(
|
||||||
onTap: () => _onTap(context),
|
onTap: () => _onTap(context),
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
#include <flutter_udid/flutter_udid_plugin.h>
|
#include <flutter_udid/flutter_udid_plugin.h>
|
||||||
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
#include <flutter_webrtc/flutter_web_r_t_c_plugin.h>
|
||||||
#include <irondash_engine_context/irondash_engine_context_plugin.h>
|
#include <irondash_engine_context/irondash_engine_context_plugin.h>
|
||||||
|
#include <livekit_client/live_kit_plugin.h>
|
||||||
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
#include <media_kit_libs_linux/media_kit_libs_linux_plugin.h>
|
||||||
#include <media_kit_video/media_kit_video_plugin.h>
|
#include <media_kit_video/media_kit_video_plugin.h>
|
||||||
#include <pasteboard/pasteboard_plugin.h>
|
#include <pasteboard/pasteboard_plugin.h>
|
||||||
@@ -48,6 +49,9 @@ void fl_register_plugins(FlPluginRegistry* registry) {
|
|||||||
g_autoptr(FlPluginRegistrar) irondash_engine_context_registrar =
|
g_autoptr(FlPluginRegistrar) irondash_engine_context_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "IrondashEngineContextPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "IrondashEngineContextPlugin");
|
||||||
irondash_engine_context_plugin_register_with_registrar(irondash_engine_context_registrar);
|
irondash_engine_context_plugin_register_with_registrar(irondash_engine_context_registrar);
|
||||||
|
g_autoptr(FlPluginRegistrar) livekit_client_registrar =
|
||||||
|
fl_plugin_registry_get_registrar_for_plugin(registry, "LiveKitPlugin");
|
||||||
|
live_kit_plugin_register_with_registrar(livekit_client_registrar);
|
||||||
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
g_autoptr(FlPluginRegistrar) media_kit_libs_linux_registrar =
|
||||||
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
fl_plugin_registry_get_registrar_for_plugin(registry, "MediaKitLibsLinuxPlugin");
|
||||||
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
media_kit_libs_linux_plugin_register_with_registrar(media_kit_libs_linux_registrar);
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ list(APPEND FLUTTER_PLUGIN_LIST
|
|||||||
flutter_udid
|
flutter_udid
|
||||||
flutter_webrtc
|
flutter_webrtc
|
||||||
irondash_engine_context
|
irondash_engine_context
|
||||||
|
livekit_client
|
||||||
media_kit_libs_linux
|
media_kit_libs_linux
|
||||||
media_kit_video
|
media_kit_video
|
||||||
pasteboard
|
pasteboard
|
||||||
|
|||||||
@@ -11,34 +11,34 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- file_selector_macos (0.0.1):
|
- file_selector_macos (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- Firebase/CoreOnly (11.15.0):
|
- Firebase/CoreOnly (12.0.0):
|
||||||
- FirebaseCore (~> 11.15.0)
|
- FirebaseCore (~> 12.0.0)
|
||||||
- Firebase/Messaging (11.15.0):
|
- Firebase/Messaging (12.0.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 11.15.0)
|
- FirebaseMessaging (~> 12.0.0)
|
||||||
- firebase_core (3.15.1):
|
- firebase_core (4.0.0):
|
||||||
- Firebase/CoreOnly (~> 11.15.0)
|
- Firebase/CoreOnly (~> 12.0.0)
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- firebase_messaging (15.2.9):
|
- firebase_messaging (16.0.0):
|
||||||
- Firebase/CoreOnly (~> 11.15.0)
|
- Firebase/CoreOnly (~> 12.0.0)
|
||||||
- Firebase/Messaging (~> 11.15.0)
|
- Firebase/Messaging (~> 12.0.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- FirebaseCore (11.15.0):
|
- FirebaseCore (12.0.0):
|
||||||
- FirebaseCoreInternal (~> 11.15.0)
|
- FirebaseCoreInternal (~> 12.0.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- FirebaseCoreInternal (11.15.0):
|
- FirebaseCoreInternal (12.0.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- FirebaseInstallations (11.15.0):
|
- FirebaseInstallations (12.0.0):
|
||||||
- FirebaseCore (~> 11.15.0)
|
- FirebaseCore (~> 12.0.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (11.15.0):
|
- FirebaseMessaging (12.0.0):
|
||||||
- FirebaseCore (~> 11.15.0)
|
- FirebaseCore (~> 12.0.0)
|
||||||
- FirebaseInstallations (~> 11.0)
|
- FirebaseInstallations (~> 12.0.0)
|
||||||
- GoogleDataTransport (~> 10.0)
|
- 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)
|
||||||
@@ -56,9 +56,9 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- flutter_webrtc (0.14.0):
|
- flutter_webrtc (1.0.0):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (= 125.6422.07)
|
- WebRTC-SDK (= 137.7151.02)
|
||||||
- FlutterMacOS (1.0.0)
|
- FlutterMacOS (1.0.0)
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
@@ -92,10 +92,10 @@ PODS:
|
|||||||
- GoogleUtilities/Privacy
|
- GoogleUtilities/Privacy
|
||||||
- irondash_engine_context (0.0.1):
|
- irondash_engine_context (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- livekit_client (2.4.9):
|
- livekit_client (2.5.0):
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (= 125.6422.07)
|
- WebRTC-SDK (= 137.7151.02)
|
||||||
- local_auth_darwin (0.0.1):
|
- local_auth_darwin (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -130,28 +130,31 @@ PODS:
|
|||||||
- sqflite_darwin (0.0.4):
|
- sqflite_darwin (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (3.50.1):
|
- sqlite3 (3.50.3):
|
||||||
- sqlite3/common (= 3.50.1)
|
- sqlite3/common (= 3.50.3)
|
||||||
- sqlite3/common (3.50.1)
|
- sqlite3/common (3.50.3)
|
||||||
- sqlite3/dbstatvtab (3.50.1):
|
- sqlite3/dbstatvtab (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/fts5 (3.50.1):
|
- sqlite3/fts5 (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/math (3.50.1):
|
- sqlite3/math (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/perf-threadsafe (3.50.1):
|
- sqlite3/perf-threadsafe (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/rtree (3.50.1):
|
- sqlite3/rtree (3.50.3):
|
||||||
|
- sqlite3/common
|
||||||
|
- sqlite3/session (3.50.3):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3_flutter_libs (0.0.1):
|
- sqlite3_flutter_libs (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (~> 3.50.1)
|
- sqlite3 (~> 3.50.3)
|
||||||
- sqlite3/dbstatvtab
|
- sqlite3/dbstatvtab
|
||||||
- sqlite3/fts5
|
- sqlite3/fts5
|
||||||
- sqlite3/math
|
- sqlite3/math
|
||||||
- sqlite3/perf-threadsafe
|
- sqlite3/perf-threadsafe
|
||||||
- sqlite3/rtree
|
- sqlite3/rtree
|
||||||
|
- sqlite3/session
|
||||||
- super_native_extensions (0.0.1):
|
- super_native_extensions (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- url_launcher_macos (0.0.1):
|
- url_launcher_macos (0.0.1):
|
||||||
@@ -160,7 +163,7 @@ PODS:
|
|||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- WebRTC-SDK (125.6422.07)
|
- WebRTC-SDK (137.7151.02)
|
||||||
|
|
||||||
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`)
|
||||||
@@ -291,25 +294,25 @@ SPEC CHECKSUMS:
|
|||||||
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
|
device_info_plus: 4fb280989f669696856f8b129e4a5e3cd6c48f76
|
||||||
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
file_picker: 7584aae6fa07a041af2b36a2655122d42f578c1a
|
||||||
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
|
file_selector_macos: 6280b52b459ae6c590af5d78fc35c7267a3c4b31
|
||||||
Firebase: d99ac19b909cd2c548339c2241ecd0d1599ab02e
|
Firebase: 800d487043c0557d9faed71477a38d9aafb08a41
|
||||||
firebase_core: 8dc569d17b3a9fc3ee5ebc21b322411b4a796833
|
firebase_core: eeea10f64026b68cd0bc3dee079ab4717e22909e
|
||||||
firebase_messaging: adaf7fc22897a7aa49410d15f8a595bef2dbca2d
|
firebase_messaging: 5eefcd5bde556bfacdd9968e11c52f39032dfbe5
|
||||||
FirebaseCore: efb3893e5b94f32b86e331e3bd6dadf18b66568e
|
FirebaseCore: 055f4ab117d5964158c833f3d5e7ec6d91648d4a
|
||||||
FirebaseCoreInternal: 9afa45b1159304c963da48addb78275ef701c6b4
|
FirebaseCoreInternal: dedc28e569a4be85f38f3d6af1070a2e12018d55
|
||||||
FirebaseInstallations: 317270fec08a5d418fdbc8429282238cab3ac843
|
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
||||||
FirebaseMessaging: 3b26e2cee503815e01c3701236b020aa9b576f09
|
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
||||||
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: a7eeb54859e672228c28f4b48b1fb61561976ea3
|
flutter_webrtc: 0d70bd8782c19bde286dc52f766eebbea26de201
|
||||||
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
FlutterMacOS: 8f6f14fa908a6fb3fba0cd85dbd81ec4b251fb24
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba
|
irondash_engine_context: 893c7d96d20ce361d7e996f39d360c4c2f9869ba
|
||||||
livekit_client: c9d9f41996f5cf22b9ba0e8483e6af4ca5094059
|
livekit_client: 0b0515e03858b86a7c14cc7fd6f772331f6ee84c
|
||||||
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
|
||||||
@@ -325,13 +328,13 @@ SPEC CHECKSUMS:
|
|||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
sign_in_with_apple: 6673c03c9e3643f6c8d33601943fbfa9ae99f94e
|
sign_in_with_apple: 6673c03c9e3643f6c8d33601943fbfa9ae99f94e
|
||||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||||
sqlite3: 1d85290c3321153511f6e900ede7a1608718bbd5
|
sqlite3: 83105acd294c9137c026e2da1931c30b4588ab81
|
||||||
sqlite3_flutter_libs: e7fc8c9ea2200ff3271f08f127842131746b70e2
|
sqlite3_flutter_libs: 616267f2fca40e9c6af8c5d82324e05667040b6e
|
||||||
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
||||||
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
||||||
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
||||||
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497
|
wakelock_plus: 21ddc249ac4b8d018838dbdabd65c5976c308497
|
||||||
WebRTC-SDK: dff00a3892bc570b6014e046297782084071657e
|
WebRTC-SDK: d20de357dcbf7c9696b124b39f3ff62125107e4b
|
||||||
|
|
||||||
PODFILE CHECKSUM: 346bfb2deb41d4a6ebd6f6799f92188bde2d246f
|
PODFILE CHECKSUM: 346bfb2deb41d4a6ebd6f6799f92188bde2d246f
|
||||||
|
|
||||||
|
|||||||
240
pubspec.lock
240
pubspec.lock
@@ -5,34 +5,34 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _fe_analyzer_shared
|
name: _fe_analyzer_shared
|
||||||
sha256: e55636ed79578b9abca5fecf9437947798f5ef7456308b5cb85720b793eac92f
|
sha256: da0d9209ca76bde579f2da330aeb9df62b6319c834fa7baae052021b0462401f
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "82.0.0"
|
version: "85.0.0"
|
||||||
_flutterfire_internals:
|
_flutterfire_internals:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: _flutterfire_internals
|
name: _flutterfire_internals
|
||||||
sha256: a5788040810bd84400bc209913fbc40f388cded7cdf95ee2f5d2bff7e38d5241
|
sha256: bb84ee51e527053dd8e25ecc9f97a6abfdc19130fb4d883e4e8585e23e7e6dd8
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.58"
|
version: "1.3.60"
|
||||||
analyzer:
|
analyzer:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer
|
name: analyzer
|
||||||
sha256: "904ae5bb474d32c38fb9482e2d925d5454cda04ddd0e55d2e6826bc72f6ba8c0"
|
sha256: f4ad0fea5f102201015c9aae9d93bc02f75dd9491529a8c21f88d17a8523d44c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "7.4.5"
|
version: "7.6.0"
|
||||||
analyzer_plugin:
|
analyzer_plugin:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: analyzer_plugin
|
name: analyzer_plugin
|
||||||
sha256: ee188b6df6c85f1441497c7171c84f1392affadc0384f71089cb10a3bc508cef
|
sha256: a5ab7590c27b779f3d4de67f31c4109dbe13dd7339f86461a6f2a8ab2594d8ce
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.13.1"
|
version: "0.13.4"
|
||||||
animations:
|
animations:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -85,10 +85,10 @@ packages:
|
|||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: auto_route_generator
|
name: auto_route_generator
|
||||||
sha256: "2a5b5bf9c55d4a2098931037dac90921a4663808aed494bb4f134d82d46cb8ec"
|
sha256: "9e3846fcbeacba5c362557328dd8c8fbc953b6a0cbc3395365e8d8f92eea29c4"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.2.3"
|
version: "10.1.0"
|
||||||
avatar_stack:
|
avatar_stack:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -205,10 +205,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: built_value
|
name: built_value
|
||||||
sha256: "082001b5c3dc495d4a42f1d5789990505df20d8547d42507c29050af6933ee27"
|
sha256: "0b1b12a0a549605e5f04476031cd0bc91ead1d7c8e830773a18ee54179b3cb62"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.10.1"
|
version: "8.11.0"
|
||||||
cached_network_image:
|
cached_network_image:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -281,14 +281,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.1.0"
|
version: "0.1.0"
|
||||||
cli_config:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: cli_config
|
|
||||||
sha256: ac20a183a07002b700f0c25e61b7ee46b23c309d76ab7b7640a028f18e4d99ec
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.2.0"
|
|
||||||
cli_util:
|
cli_util:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -345,14 +337,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.2"
|
version: "3.1.2"
|
||||||
coverage:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: coverage
|
|
||||||
sha256: "5da775aa218eaf2151c721b16c01c7676fbfdd99cebba2bf64e8b807a28ff94d"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.15.0"
|
|
||||||
croppy:
|
croppy:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -397,18 +381,18 @@ packages:
|
|||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: custom_lint
|
name: custom_lint
|
||||||
sha256: "409c485fd14f544af1da965d5a0d160ee57cd58b63eeaa7280a4f28cf5bda7f1"
|
sha256: "9656925637516c5cf0f5da018b33df94025af2088fe09c8ae2ca54c53f2d9a84"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.5"
|
version: "0.7.6"
|
||||||
custom_lint_builder:
|
custom_lint_builder:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: custom_lint_builder
|
name: custom_lint_builder
|
||||||
sha256: "107e0a43606138015777590ee8ce32f26ba7415c25b722ff0908a6f5d7a4c228"
|
sha256: "6cdc8e87e51baaaba9c43e283ed8d28e59a0c4732279df62f66f7b5984655414"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.5"
|
version: "0.7.6"
|
||||||
custom_lint_core:
|
custom_lint_core:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -421,26 +405,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: custom_lint_visitor
|
name: custom_lint_visitor
|
||||||
sha256: cba5b6d7a6217312472bf4468cdf68c949488aed7ffb0eab792cd0b6c435054d
|
sha256: "4a86a0d8415a91fbb8298d6ef03e9034dc8e323a599ddc4120a0e36c433983a2"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.0+7.4.5"
|
version: "1.0.0+7.7.0"
|
||||||
dart_style:
|
dart_style:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dart_style
|
name: dart_style
|
||||||
sha256: "5b236382b47ee411741447c1f1e111459c941ea1b3f2b540dde54c210a3662af"
|
sha256: "8a0e5fba27e8ee025d2ffb4ee820b4e6e2cf5e4246a6b1a477eb66866947e0bb"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.1.0"
|
version: "3.1.1"
|
||||||
dart_webrtc:
|
dart_webrtc:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: dart_webrtc
|
name: dart_webrtc
|
||||||
sha256: "5b76fd85ac95d6f5dee3e7d7de8d4b51bfbec1dc73804647c6aebb52d6297116"
|
sha256: a2ae542cdadc21359022adedc26138fa3487cc3b3547c24ff4f556681869e28c
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.3+hotfix.2"
|
version: "1.5.3+hotfix.4"
|
||||||
dbus:
|
dbus:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -493,26 +477,26 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: drift
|
name: drift
|
||||||
sha256: e60c715f045dd33624fc533efb0075e057debec9f39e83843e518f488a0e21fb
|
sha256: "6aaea757f53bb035e8a3baedf3d1d53a79d6549a6c13d84f7546509da9372c7c"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.27.0"
|
version: "2.28.1"
|
||||||
drift_dev:
|
drift_dev:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
name: drift_dev
|
name: drift_dev
|
||||||
sha256: "7ad88b8982e753eadcdbc0ea7c7d30500598af733601428b5c9d264baf5106d6"
|
sha256: "68c138e884527d2bd61df2ade276c3a144df84d1adeb0ab8f3196b5afe021bd4"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.27.0"
|
version: "2.28.0"
|
||||||
drift_flutter:
|
drift_flutter:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: drift_flutter
|
name: drift_flutter
|
||||||
sha256: "0cadbf3b8733409a6cf61d18ba2e94e149df81df7de26f48ae0695b48fd71922"
|
sha256: ccfb42bc942e59f81500b16228df59cf8eb40d2fbd96637ff677df923350af7b
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.2.4"
|
version: "0.2.5"
|
||||||
dropdown_button2:
|
dropdown_button2:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -525,10 +509,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: easy_localization
|
name: easy_localization
|
||||||
sha256: "0f5239c7b8ab06c66440cfb0e9aa4b4640429c6668d5a42fe389c5de42220b12"
|
sha256: "2ccdf9db8fe4d9c5a75c122e6275674508fd0f0d49c827354967b8afcc56bbed"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.7+1"
|
version: "3.0.8"
|
||||||
easy_logger:
|
easy_logger:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -629,10 +613,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_core
|
name: firebase_core
|
||||||
sha256: c6e8a6bf883d8ddd0dec39be90872daca65beaa6f4cff0051ed3b16c56b82e9f
|
sha256: "6b343e6f7b72a4f32d7ce8df8c9a28d8f54b4ac20d7c6500f3e8b3969afca457"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.15.1"
|
version: "4.0.0"
|
||||||
firebase_core_platform_interface:
|
firebase_core_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -645,34 +629,34 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_core_web
|
name: firebase_core_web
|
||||||
sha256: "0ed0dc292e8f9ac50992e2394e9d336a0275b6ae400d64163fdf0a8a8b556c37"
|
sha256: "5d28b14dd32282fb7ce2b22b897362453755b6b8541d491127dc72b755bb7b16"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.24.1"
|
version: "3.0.0"
|
||||||
firebase_messaging:
|
firebase_messaging:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging
|
name: firebase_messaging
|
||||||
sha256: "0f3363f97672eb9f65609fa00ed2f62cc8ec93e7e2d4def99726f9165d3d8a73"
|
sha256: "10272b553a49c13a6cedfd00121047157521f82a5d3f2a1706b9dd28342cc482"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "15.2.9"
|
version: "16.0.0"
|
||||||
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: "7a05ef119a14c5f6a9440d1e0223bcba20c8daf555450e119c4c477bf2c3baa9"
|
sha256: b846a305feb3f74ee3f0aace447f65a4696bc6550bc828ecf5a84a1b77473d16
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.6.9"
|
version: "4.7.0"
|
||||||
firebase_messaging_web:
|
firebase_messaging_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: firebase_messaging_web
|
name: firebase_messaging_web
|
||||||
sha256: a4547f76da2a905190f899eb4d0150e1d0fd52206fce469d9f05ae15bb68b2c5
|
sha256: "28714749880f7242c5fb3b1ee6c66b41f61453f02ae348b43c82957df80b87ae"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.10.9"
|
version: "4.0.0"
|
||||||
fixnum:
|
fixnum:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -846,6 +830,14 @@ 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:
|
||||||
@@ -1033,10 +1025,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: flutter_webrtc
|
name: flutter_webrtc
|
||||||
sha256: "792aa1e5838a719f29ae52c0773dbb5dd781fc33b1bf87c321b274e55ab51ad1"
|
sha256: "69095ba39b83da3de48286dfc0769aa8e9f10491f70058dc8d8ecc960ef7a260"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.14.2"
|
version: "1.0.0"
|
||||||
font_awesome_flutter:
|
font_awesome_flutter:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1073,10 +1065,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: gal
|
name: gal
|
||||||
sha256: "2771519c8b29f784d5e27f4efc2667667eef51c6c47cccaa0435a8fe8aa208e4"
|
sha256: "969598f986789127fd407a750413249e1352116d4c2be66e81837ffeeaafdfee"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.3.1"
|
version: "2.3.2"
|
||||||
gap:
|
gap:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1201,10 +1193,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image_picker_android
|
name: image_picker_android
|
||||||
sha256: "317a5d961cec5b34e777b9252393f2afbd23084aa6e60fcf601dcf6341b9ebeb"
|
sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12+23"
|
version: "0.8.12+24"
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1333,14 +1325,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.1"
|
version: "3.0.1"
|
||||||
lean_builder:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: lean_builder
|
|
||||||
sha256: dca2165cfe681c69ae903a0880cab90ee93d730777605a0f44c9dd08cec7e1b9
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.1.0-alpha.13"
|
|
||||||
lint:
|
lint:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1361,10 +1345,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: livekit_client
|
name: livekit_client
|
||||||
sha256: "5d182f40cc9aafce60a9acf936bad8bc69010b5cbf0a949f6f27dc4390f2fcce"
|
sha256: b3db2d8afa8d1dbe4fd8dfc965fc9d661cb51a8d864ad199919575ce919a40fb
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.9"
|
version: "2.5.0+hotfix.1"
|
||||||
local_auth:
|
local_auth:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1377,10 +1361,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: local_auth_android
|
name: local_auth_android
|
||||||
sha256: "63ad7ca6396290626dc0cb34725a939e4cfe965d80d36112f08d49cf13a8136e"
|
sha256: "82b2bdeee2199a510d3b7716121e96a6609da86693bb0863edd8566355406b79"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.49"
|
version: "1.0.50"
|
||||||
local_auth_darwin:
|
local_auth_darwin:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1405,6 +1389,14 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.11"
|
version: "1.0.11"
|
||||||
|
logger:
|
||||||
|
dependency: transitive
|
||||||
|
description:
|
||||||
|
name: logger
|
||||||
|
sha256: "7ad7215c15420a102ec687bb320a7312afd449bac63bfb1c60d9787c27b9767f"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "1.4.0"
|
||||||
logging:
|
logging:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1457,10 +1449,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: material_symbols_icons
|
name: material_symbols_icons
|
||||||
sha256: "7c50901b39d1ad645ee25d920aed008061e1fd541a897b4ebf2c01d966dbf16b"
|
sha256: ef20d86fb34c2b59eb7553c4d795bb8a7ec8c890c53ffd3148c64f7adc46ae50
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.2815.1"
|
version: "4.2858.1"
|
||||||
media_kit:
|
media_kit:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1581,14 +1573,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.0"
|
version: "0.5.0"
|
||||||
node_preamble:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: node_preamble
|
|
||||||
sha256: "6e7eac89047ab8a8d26cf16127b5ed26de65209847630400f9aefd7cd5c730db"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.0.2"
|
|
||||||
octo_image:
|
octo_image:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1793,10 +1777,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: protobuf
|
name: protobuf
|
||||||
sha256: "579fe5557eae58e3adca2e999e38f02441d8aa908703854a9e0a0f47fa857731"
|
sha256: "6153efcc92a06910918f3db8231fd2cf828ac81e50ebd87adc8f8a8cb3caff0e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "4.1.0"
|
version: "4.1.1"
|
||||||
provider:
|
provider:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2101,22 +2085,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.2"
|
version: "1.4.2"
|
||||||
shelf_packages_handler:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_packages_handler
|
|
||||||
sha256: "89f967eca29607c933ba9571d838be31d67f53f6e4ee15147d5dc2934fee1b1e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "3.0.2"
|
|
||||||
shelf_static:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: shelf_static
|
|
||||||
sha256: c87c3875f91262785dade62d135760c2c69cb217ac759485334c5857ad89f6e3
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.1.3"
|
|
||||||
shelf_web_socket:
|
shelf_web_socket:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2178,22 +2146,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.3.6"
|
version: "1.3.6"
|
||||||
source_map_stack_trace:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_map_stack_trace
|
|
||||||
sha256: c0713a43e323c3302c2abe2a1cc89aa057a387101ebd280371d6a6c9fa68516b
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "2.1.2"
|
|
||||||
source_maps:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: source_maps
|
|
||||||
sha256: "190222579a448b03896e0ca6eca5998fa810fda630c1d65e2f78b3f638f54812"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.10.13"
|
|
||||||
source_span:
|
source_span:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2230,10 +2182,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqflite_common
|
name: sqflite_common
|
||||||
sha256: "84731e8bfd8303a3389903e01fb2141b6e59b5973cacbb0929021df08dddbe8b"
|
sha256: "6ef422a4525ecc601db6c0a2233ff448c731307906e92cabc9ba292afaae16a6"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.5.5"
|
version: "2.5.6"
|
||||||
sqflite_darwin:
|
sqflite_darwin:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2254,26 +2206,26 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqlite3
|
name: sqlite3
|
||||||
sha256: c0503c69b44d5714e6abbf4c1f51a3c3cc42b75ce785f44404765e4635481d38
|
sha256: dd806fff004a0aeb01e208b858dbc649bc72104670d425a81a6dd17698535f6e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.7.6"
|
version: "2.8.0"
|
||||||
sqlite3_flutter_libs:
|
sqlite3_flutter_libs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqlite3_flutter_libs
|
name: sqlite3_flutter_libs
|
||||||
sha256: e07232b998755fe795655c56d1f5426e0190c9c435e1752d39e7b1cd33699c71
|
sha256: fd996da5515a73aacd0a04ae7063db5fe8df42670d974df4c3ee538c652eef2e
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.34"
|
version: "0.5.38"
|
||||||
sqlparser:
|
sqlparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqlparser
|
name: sqlparser
|
||||||
sha256: "27dd0a9f0c02e22ac0eb42a23df9ea079ce69b52bb4a3b478d64e0ef34a263ee"
|
sha256: "7c859c803cf7e9a84d6db918bac824545045692bbe94a6386bd3a45132235d09"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.41.0"
|
version: "0.41.1"
|
||||||
stack_trace:
|
stack_trace:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2370,14 +2322,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.2.2"
|
version: "1.2.2"
|
||||||
test:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test
|
|
||||||
sha256: "301b213cd241ca982e9ba50266bd3f5bd1ea33f1455554c5abb85d1be0e2d87e"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.25.15"
|
|
||||||
test_api:
|
test_api:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2386,14 +2330,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.7.4"
|
version: "0.7.4"
|
||||||
test_core:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: test_core
|
|
||||||
sha256: "84d17c3486c8dfdbe5e12a50c8ae176d15e2a771b96909a9442b40173649ccaa"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "0.6.8"
|
|
||||||
textfield_tags:
|
textfield_tags:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -2480,10 +2416,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: url_launcher
|
name: url_launcher
|
||||||
sha256: "9d06212b1362abc2f0f0d78e6f09f726608c74e3b9462e8368bb03314aa8d603"
|
sha256: f6a7e5c4835bb4e3026a04793a4199ca2d14c739ec378fdfe23fc8075d0439f8
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.1"
|
version: "6.3.2"
|
||||||
url_launcher_android:
|
url_launcher_android:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2660,14 +2596,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "3.0.3"
|
version: "3.0.3"
|
||||||
webkit_inspection_protocol:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: webkit_inspection_protocol
|
|
||||||
sha256: "87d3f2333bb240704cd3f1c6b5b7acd8a10e7f0bc28c28dcf14e782014f4a572"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.1"
|
|
||||||
webrtc_interface:
|
webrtc_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2708,14 +2636,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.5.0"
|
version: "6.5.0"
|
||||||
xxh3:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: xxh3
|
|
||||||
sha256: "399a0438f5d426785723c99da6b16e136f4953fb1e9db0bf270bd41dd4619916"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "1.2.0"
|
|
||||||
yaml:
|
yaml:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
|||||||
53
pubspec.yaml
53
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.1.0+114
|
version: 3.1.0+116
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
@@ -46,65 +46,65 @@ dependencies:
|
|||||||
path_provider: ^2.1.5
|
path_provider: ^2.1.5
|
||||||
dio: ^5.8.0+1
|
dio: ^5.8.0+1
|
||||||
very_good_infinite_list: ^0.9.0
|
very_good_infinite_list: ^0.9.0
|
||||||
freezed_annotation: ^3.0.0
|
freezed_annotation: ^3.1.0
|
||||||
json_annotation: ^4.9.0
|
json_annotation: ^4.9.0
|
||||||
flutter_markdown_latex: ^0.3.4
|
flutter_markdown_latex: ^0.3.4
|
||||||
markdown: ^7.3.0
|
markdown: ^7.3.0
|
||||||
flutter_highlight: ^0.7.0
|
flutter_highlight: ^0.7.0
|
||||||
uuid: ^4.5.1
|
uuid: ^4.5.1
|
||||||
url_launcher: ^6.3.1
|
url_launcher: ^6.3.2
|
||||||
google_fonts: ^6.2.1
|
google_fonts: ^6.2.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
|
||||||
flutter_blurhash: ^0.9.0
|
flutter_blurhash: ^0.9.1
|
||||||
media_kit: ^1.2.0
|
media_kit: ^1.2.0
|
||||||
media_kit_video: ^1.3.0
|
media_kit_video: ^1.3.0
|
||||||
media_kit_libs_video: ^1.0.6
|
media_kit_libs_video: ^1.0.6
|
||||||
flutter_cache_manager: ^3.4.1
|
flutter_cache_manager: ^3.4.1
|
||||||
flutter_platform_alert: ^0.8.0
|
flutter_platform_alert: ^0.8.0
|
||||||
email_validator: ^3.0.0
|
email_validator: ^3.0.0
|
||||||
easy_localization: ^3.0.7+1
|
easy_localization: ^3.0.8
|
||||||
flutter_inappwebview: ^6.1.5
|
flutter_inappwebview: ^6.1.5
|
||||||
animations: ^2.0.11
|
animations: ^2.0.11
|
||||||
package_info_plus: ^8.3.0
|
package_info_plus: ^8.3.0
|
||||||
device_info_plus: ^11.4.0
|
device_info_plus: ^11.5.0
|
||||||
tus_client_dart:
|
tus_client_dart:
|
||||||
git: https://github.com/LittleSheep2Code/tus_client.git
|
git: https://github.com/LittleSheep2Code/tus_client.git
|
||||||
cross_file: ^0.3.4+2
|
cross_file: ^0.3.4+2
|
||||||
image_picker: ^1.1.2
|
image_picker: ^1.1.2
|
||||||
file_picker: ^10.1.7
|
file_picker: ^10.2.0
|
||||||
riverpod_annotation: ^2.6.1
|
riverpod_annotation: ^2.6.1
|
||||||
image_picker_platform_interface: ^2.10.1
|
image_picker_platform_interface: ^2.10.1
|
||||||
image_picker_android: ^0.8.12+23
|
image_picker_android: ^0.8.12+24
|
||||||
super_context_menu: ^0.9.0-dev.6
|
super_context_menu: ^0.9.1
|
||||||
modal_bottom_sheet: ^3.0.0
|
modal_bottom_sheet: ^3.0.0
|
||||||
firebase_messaging: ^15.2.5
|
firebase_messaging: ^16.0.0
|
||||||
flutter_udid: ^4.0.0
|
flutter_udid: ^4.0.0
|
||||||
firebase_core: ^3.13.0
|
firebase_core: ^4.0.0
|
||||||
web_socket_channel: ^3.0.3
|
web_socket_channel: ^3.0.3
|
||||||
material_symbols_icons: ^4.2815.0
|
material_symbols_icons: ^4.2858.1
|
||||||
drift: ^2.26.0
|
drift: ^2.28.1
|
||||||
drift_flutter: ^0.2.4
|
drift_flutter: ^0.2.5
|
||||||
path: ^1.9.1
|
path: ^1.9.1
|
||||||
collection: ^1.19.1
|
collection: ^1.19.1
|
||||||
markdown_editor_plus: ^0.2.15
|
markdown_editor_plus: ^0.2.15
|
||||||
croppy: ^1.3.6
|
croppy: ^1.3.6
|
||||||
table_calendar: ^3.1.3
|
table_calendar: ^3.2.0
|
||||||
relative_time: ^5.0.0
|
relative_time: ^5.0.0
|
||||||
dropdown_button2: ^2.3.9
|
dropdown_button2: ^2.3.9
|
||||||
riverpod_paging_utils: ^0.8.0
|
riverpod_paging_utils: ^0.8.1
|
||||||
crypto: ^3.0.6
|
crypto: ^3.0.6
|
||||||
avatar_stack: ^3.0.0
|
avatar_stack: ^3.0.0
|
||||||
markdown_widget: ^2.3.2+8
|
markdown_widget: ^2.3.2+8
|
||||||
visibility_detector: ^0.4.0+2
|
visibility_detector: ^0.4.0+2
|
||||||
flutter_native_splash: ^2.4.6
|
flutter_native_splash: ^2.4.6
|
||||||
photo_view: ^0.15.0
|
photo_view: ^0.15.0
|
||||||
gal: ^2.3.1
|
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: ^0.14.1
|
flutter_webrtc: ^1.0.0
|
||||||
livekit_client: ^2.4.7
|
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.0.0
|
record: ^6.0.0
|
||||||
@@ -116,7 +116,7 @@ dependencies:
|
|||||||
flutter_timezone: ^4.1.1
|
flutter_timezone: ^4.1.1
|
||||||
fl_chart: ^1.0.0
|
fl_chart: ^1.0.0
|
||||||
sign_in_with_apple: ^7.0.1
|
sign_in_with_apple: ^7.0.1
|
||||||
flutter_svg: ^2.1.0
|
flutter_svg: ^2.2.0
|
||||||
native_exif: ^0.6.2
|
native_exif: ^0.6.2
|
||||||
local_auth: ^2.3.0
|
local_auth: ^2.3.0
|
||||||
flutter_secure_storage: ^9.2.4
|
flutter_secure_storage: ^9.2.4
|
||||||
@@ -131,6 +131,7 @@ 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
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -142,15 +143,15 @@ dev_dependencies:
|
|||||||
# package. See that file for information about deactivating specific lint
|
# package. See that file for information about deactivating specific lint
|
||||||
# rules and activating additional ones.
|
# rules and activating additional ones.
|
||||||
flutter_lints: ^6.0.0
|
flutter_lints: ^6.0.0
|
||||||
auto_route_generator: ^10.0.1
|
auto_route_generator: ^10.1.0
|
||||||
build_runner: ^2.4.15
|
build_runner: ^2.5.4
|
||||||
freezed: ^3.0.6
|
freezed: ^3.1.0
|
||||||
json_serializable: ^6.9.5
|
json_serializable: ^6.9.5
|
||||||
riverpod_generator: ^2.6.5
|
riverpod_generator: ^2.6.5
|
||||||
custom_lint: ^0.7.5
|
custom_lint: ^0.7.6
|
||||||
riverpod_lint: ^2.6.5
|
riverpod_lint: ^2.6.5
|
||||||
drift_dev: ^2.26.0
|
drift_dev: ^2.28.0
|
||||||
flutter_launcher_icons: ^0.14.3
|
flutter_launcher_icons: ^0.14.4
|
||||||
|
|
||||||
# For information on the generic Dart part of this file, see the
|
# For information on the generic Dart part of this file, see the
|
||||||
# following page: https://dart.dev/tools/pub/pubspec
|
# following page: https://dart.dev/tools/pub/pubspec
|
||||||
|
|||||||
Reference in New Issue
Block a user