Compare commits
35 Commits
e2e103fa67
...
3.1.0+122
Author | SHA1 | Date | |
---|---|---|---|
8e0c0c6054 | |||
f3d1183076 | |||
a9f7f0cce0 | |||
f2943f8411 | |||
808e7dcffa | |||
9bed4fa6fb | |||
e6255a340b | |||
78bf319fb7 | |||
36a966d582 | |||
f72b268d36 | |||
44ef31034e | |||
229dc2186f | |||
a2f9a1efb4 | |||
|
823e3c5de6 | ||
|
faac7bac35 | ||
1fac1bfe02 | |||
9394b1d9c8 | |||
43dd13bac4 | |||
65bc372103 | |||
6558854a7a | |||
892035ab27 | |||
87ae8d2ff4 | |||
15c2dbaa0d | |||
6b3338b885 | |||
bb00b1bc6a | |||
5e1a15ada2 | |||
9bdf8ba346 | |||
204c087f29 | |||
1def3e1895 | |||
550c74e544 | |||
a39565f012 | |||
aa9755e6a7 | |||
b25e8d661a | |||
4b253ac3ec | |||
5d1b875d3c |
@@ -12,7 +12,12 @@
|
|||||||
"package_name": "dev.solsynth.solian"
|
"package_name": "dev.solsynth.solian"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"oauth_client": [],
|
"oauth_client": [
|
||||||
|
{
|
||||||
|
"client_id": "961776991058-963m1qin2vtp8fv693b5fdrab5hmpl89.apps.googleusercontent.com",
|
||||||
|
"client_type": 3
|
||||||
|
}
|
||||||
|
],
|
||||||
"api_key": [
|
"api_key": [
|
||||||
{
|
{
|
||||||
"current_key": "AIzaSyDvFNudXYs29uDtcCv6pFR8h5tXBs90FYk"
|
"current_key": "AIzaSyDvFNudXYs29uDtcCv6pFR8h5tXBs90FYk"
|
||||||
@@ -20,7 +25,20 @@
|
|||||||
],
|
],
|
||||||
"services": {
|
"services": {
|
||||||
"appinvite_service": {
|
"appinvite_service": {
|
||||||
"other_platform_oauth_client": []
|
"other_platform_oauth_client": [
|
||||||
|
{
|
||||||
|
"client_id": "961776991058-963m1qin2vtp8fv693b5fdrab5hmpl89.apps.googleusercontent.com",
|
||||||
|
"client_type": 3
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"client_id": "961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com",
|
||||||
|
"client_type": 2,
|
||||||
|
"ios_info": {
|
||||||
|
"bundle_id": "dev.solsynth.solian",
|
||||||
|
"app_store_id": "6499032345"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
BIN
android/app/src/main/res/drawable/ic_notification.png
Executable file
BIN
android/app/src/main/res/drawable/ic_notification.png
Executable file
Binary file not shown.
After Width: | Height: | Size: 70 KiB |
@@ -706,6 +706,7 @@
|
|||||||
"copyToClipboardTooltip": "Copy to clipboard",
|
"copyToClipboardTooltip": "Copy to clipboard",
|
||||||
"postForwardingTo": "Forwarding to",
|
"postForwardingTo": "Forwarding to",
|
||||||
"postReplyingTo": "Replying to",
|
"postReplyingTo": "Replying to",
|
||||||
|
"postReplyPlaceholder": "Post your reply",
|
||||||
"postEditing": "You are editing an existing post",
|
"postEditing": "You are editing an existing post",
|
||||||
"postArticle": "Article",
|
"postArticle": "Article",
|
||||||
"aboutDeviceName": "Device Name",
|
"aboutDeviceName": "Device Name",
|
||||||
@@ -782,5 +783,11 @@
|
|||||||
"postCategoryStudy": "Study",
|
"postCategoryStudy": "Study",
|
||||||
"postCategoryGaming": "Gaming",
|
"postCategoryGaming": "Gaming",
|
||||||
"postCategoryProgramming": "Programming",
|
"postCategoryProgramming": "Programming",
|
||||||
"postCategoryMusic": "Music"
|
"postCategoryMusic": "Music",
|
||||||
|
"links": "Links",
|
||||||
|
"addLink": "Add link",
|
||||||
|
"linkKey": "Link Name",
|
||||||
|
"linkValue": "URL",
|
||||||
|
"debugOptions": "Debug Options",
|
||||||
|
"joinedAt": "Joined at {}"
|
||||||
}
|
}
|
||||||
|
@@ -120,6 +120,7 @@
|
|||||||
"other": "{}个附件"
|
"other": "{}个附件"
|
||||||
},
|
},
|
||||||
"edited": "已编辑",
|
"edited": "已编辑",
|
||||||
|
"editedAt": "编辑于 {}",
|
||||||
"addVideo": "添加视频",
|
"addVideo": "添加视频",
|
||||||
"addPhoto": "添加照片",
|
"addPhoto": "添加照片",
|
||||||
"addFile": "添加文件",
|
"addFile": "添加文件",
|
||||||
|
@@ -1 +1 @@
|
|||||||
{"flutter":{"platforms":{"android":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:android:a8d3f7995b0b8e86f4188b","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:ios:727229d368cc47e1f4188b","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"macos":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:ios:727229d368cc47e1f4188b","uploadDebugSymbols":false,"fileOutput":"macos/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"solian-0x001","configurations":{"android":"1:961776991058:android:a8d3f7995b0b8e86f4188b","ios":"1:961776991058:ios:727229d368cc47e1f4188b","macos":"1:961776991058:ios:727229d368cc47e1f4188b","web":"1:961776991058:web:b91d12f2892a5609f4188b","windows":"1:961776991058:web:3a912c0eb14028e5f4188b"}}}}}}
|
{"flutter":{"platforms":{"android":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:android:a8d3f7995b0b8e86f4188b","fileOutput":"android/app/google-services.json"}},"ios":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:ios:727229d368cc47e1f4188b","uploadDebugSymbols":false,"fileOutput":"ios/Runner/GoogleService-Info.plist"}},"macos":{"default":{"projectId":"solian-0x001","appId":"1:961776991058:ios:727229d368cc47e1f4188b","uploadDebugSymbols":false,"fileOutput":"macos/Runner/GoogleService-Info.plist"}},"dart":{"lib/firebase_options.dart":{"projectId":"solian-0x001","configurations":{"android":"1:961776991058:android:a8d3f7995b0b8e86f4188b","ios":"1:961776991058:ios:727229d368cc47e1f4188b","macos":"1:961776991058:ios:727229d368cc47e1f4188b","web":"1:961776991058:web:3a912c0eb14028e5f4188b","windows":"1:961776991058:web:3a912c0eb14028e5f4188b"}}}}}}
|
@@ -73,6 +73,8 @@ PODS:
|
|||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- Flutter (1.0.0)
|
- Flutter (1.0.0)
|
||||||
|
- flutter_app_update (0.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_inappwebview_ios (0.0.1):
|
- flutter_inappwebview_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_inappwebview_ios/Core (= 0.0.1)
|
- flutter_inappwebview_ios/Core (= 0.0.1)
|
||||||
@@ -178,25 +180,25 @@ PODS:
|
|||||||
- sqflite_darwin (0.0.4):
|
- sqflite_darwin (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (3.50.3):
|
- sqlite3 (3.50.4):
|
||||||
- sqlite3/common (= 3.50.3)
|
- sqlite3/common (= 3.50.4)
|
||||||
- sqlite3/common (3.50.3)
|
- sqlite3/common (3.50.4)
|
||||||
- sqlite3/dbstatvtab (3.50.3):
|
- sqlite3/dbstatvtab (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/fts5 (3.50.3):
|
- sqlite3/fts5 (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/math (3.50.3):
|
- sqlite3/math (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/perf-threadsafe (3.50.3):
|
- sqlite3/perf-threadsafe (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/rtree (3.50.3):
|
- sqlite3/rtree (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/session (3.50.3):
|
- sqlite3/session (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3_flutter_libs (0.0.1):
|
- sqlite3_flutter_libs (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (~> 3.50.3)
|
- sqlite3 (~> 3.50.4)
|
||||||
- sqlite3/dbstatvtab
|
- sqlite3/dbstatvtab
|
||||||
- sqlite3/fts5
|
- sqlite3/fts5
|
||||||
- sqlite3/math
|
- sqlite3/math
|
||||||
@@ -223,6 +225,7 @@ DEPENDENCIES:
|
|||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||||
- Flutter (from `Flutter`)
|
- Flutter (from `Flutter`)
|
||||||
|
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
||||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
@@ -293,6 +296,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||||
Flutter:
|
Flutter:
|
||||||
:path: Flutter
|
:path: Flutter
|
||||||
|
flutter_app_update:
|
||||||
|
:path: ".symlinks/plugins/flutter_app_update/ios"
|
||||||
flutter_inappwebview_ios:
|
flutter_inappwebview_ios:
|
||||||
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||||
flutter_keyboard_visibility:
|
flutter_keyboard_visibility:
|
||||||
@@ -372,6 +377,7 @@ SPEC CHECKSUMS:
|
|||||||
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
||||||
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||||
|
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
@@ -406,8 +412,8 @@ 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: 83105acd294c9137c026e2da1931c30b4588ab81
|
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
|
||||||
sqlite3_flutter_libs: 616267f2fca40e9c6af8c5d82324e05667040b6e
|
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
|
||||||
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||||
|
@@ -2,6 +2,12 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CLIENT_ID</key>
|
||||||
|
<string>961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com</string>
|
||||||
|
<key>REVERSED_CLIENT_ID</key>
|
||||||
|
<string>com.googleusercontent.apps.961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig</string>
|
||||||
|
<key>ANDROID_CLIENT_ID</key>
|
||||||
|
<string>961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com</string>
|
||||||
<key>API_KEY</key>
|
<key>API_KEY</key>
|
||||||
<string>AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8</string>
|
<string>AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8</string>
|
||||||
<key>GCM_SENDER_ID</key>
|
<key>GCM_SENDER_ID</key>
|
||||||
|
@@ -34,7 +34,7 @@ class NotifyDelegate: UIResponder, UNUserNotificationCenterDelegate {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let serverUrl = UserDefaults.standard.getServerUrl()
|
let serverUrl = UserDefaults.standard.getServerUrl()
|
||||||
let url = "\(serverUrl)/chat/\(metadata["room_id"] ?? "")/messages"
|
let url = "\(serverUrl)/sphere/chat/\(metadata["room_id"] ?? "")/messages"
|
||||||
|
|
||||||
let parameters: [String: Any?] = [
|
let parameters: [String: Any?] = [
|
||||||
"content": textResponse.userText,
|
"content": textResponse.userText,
|
||||||
|
@@ -8,7 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
func getAttachmentUrl(for identifier: String) -> String {
|
func getAttachmentUrl(for identifier: String) -> String {
|
||||||
let serverBaseUrl = "https://nt.solian.app"
|
let serverBaseUrl = "https://api.solian.app"
|
||||||
|
|
||||||
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/files/\(identifier)"
|
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/drive/files/\(identifier)"
|
||||||
}
|
}
|
||||||
|
@@ -29,10 +29,7 @@ class DefaultFirebaseOptions {
|
|||||||
case TargetPlatform.windows:
|
case TargetPlatform.windows:
|
||||||
return windows;
|
return windows;
|
||||||
case TargetPlatform.linux:
|
case TargetPlatform.linux:
|
||||||
throw UnsupportedError(
|
return windows;
|
||||||
'DefaultFirebaseOptions have not been configured for linux - '
|
|
||||||
'you can reconfigure this by running the FlutterFire CLI again.',
|
|
||||||
);
|
|
||||||
default:
|
default:
|
||||||
throw UnsupportedError(
|
throw UnsupportedError(
|
||||||
'DefaultFirebaseOptions are not supported for this platform.',
|
'DefaultFirebaseOptions are not supported for this platform.',
|
||||||
@@ -41,13 +38,13 @@ class DefaultFirebaseOptions {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static const FirebaseOptions web = FirebaseOptions(
|
static const FirebaseOptions web = FirebaseOptions(
|
||||||
apiKey: 'AIzaSyBKfIQpTouj5rXnlzkEieSlbAzepm4mgJE',
|
apiKey: 'AIzaSyCfgOdlcr7h8x8j0WKx_S2wXnGkOopq320',
|
||||||
appId: '1:961776991058:web:b91d12f2892a5609f4188b',
|
appId: '1:961776991058:web:3a912c0eb14028e5f4188b',
|
||||||
messagingSenderId: '961776991058',
|
messagingSenderId: '961776991058',
|
||||||
projectId: 'solian-0x001',
|
projectId: 'solian-0x001',
|
||||||
authDomain: 'solian-0x001.firebaseapp.com',
|
authDomain: 'solian-0x001.firebaseapp.com',
|
||||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||||
measurementId: 'G-XY3HHKG0PE',
|
measurementId: 'G-JD1YEG9D6F',
|
||||||
);
|
);
|
||||||
|
|
||||||
static const FirebaseOptions android = FirebaseOptions(
|
static const FirebaseOptions android = FirebaseOptions(
|
||||||
@@ -64,6 +61,10 @@ class DefaultFirebaseOptions {
|
|||||||
messagingSenderId: '961776991058',
|
messagingSenderId: '961776991058',
|
||||||
projectId: 'solian-0x001',
|
projectId: 'solian-0x001',
|
||||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||||
|
androidClientId:
|
||||||
|
'961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com',
|
||||||
|
iosClientId:
|
||||||
|
'961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com',
|
||||||
iosBundleId: 'dev.solsynth.solian',
|
iosBundleId: 'dev.solsynth.solian',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -73,6 +74,10 @@ class DefaultFirebaseOptions {
|
|||||||
messagingSenderId: '961776991058',
|
messagingSenderId: '961776991058',
|
||||||
projectId: 'solian-0x001',
|
projectId: 'solian-0x001',
|
||||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||||
|
androidClientId:
|
||||||
|
'961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com',
|
||||||
|
iosClientId:
|
||||||
|
'961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com',
|
||||||
iosBundleId: 'dev.solsynth.solian',
|
iosBundleId: 'dev.solsynth.solian',
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -85,5 +90,4 @@ class DefaultFirebaseOptions {
|
|||||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||||
measurementId: 'G-JD1YEG9D6F',
|
measurementId: 'G-JD1YEG9D6F',
|
||||||
);
|
);
|
||||||
|
}
|
||||||
}
|
|
||||||
|
@@ -30,7 +30,6 @@ import 'package:image_picker_platform_interface/image_picker_platform_interface.
|
|||||||
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;
|
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
||||||
import 'package:island/services/update_service.dart';
|
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
@@ -54,10 +53,16 @@ void main() async {
|
|||||||
try {
|
try {
|
||||||
await langdetect.initLangDetect();
|
await langdetect.initLangDetect();
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
await Firebase.initializeApp(
|
|
||||||
options: DefaultFirebaseOptions.currentPlatform,
|
if (kIsWeb || !Platform.isLinux) {
|
||||||
);
|
await Firebase.initializeApp(
|
||||||
FirebaseMessaging.onBackgroundMessage(_firebaseMessagingBackgroundHandler);
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
|
);
|
||||||
|
FirebaseMessaging.onBackgroundMessage(
|
||||||
|
_firebaseMessagingBackgroundHandler,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
log("[SplashScreen] Firebase is ready!");
|
log("[SplashScreen] Firebase is ready!");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
@@ -138,15 +143,6 @@ void main() async {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
// Schedule update check shortly after startup, when a context is available.
|
|
||||||
// Uses the global overlay key to obtain a BuildContext safely.
|
|
||||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
|
||||||
final ctx = globalOverlay.currentContext;
|
|
||||||
if (ctx != null) {
|
|
||||||
UpdateService().checkForUpdates(ctx);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Router will be provided through Riverpod
|
// Router will be provided through Riverpod
|
||||||
@@ -175,6 +171,9 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
|
if (!kIsWeb && Platform.isLinux) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
const channel = MethodChannel('dev.solsynth.solian/notifications');
|
const channel = MethodChannel('dev.solsynth.solian/notifications');
|
||||||
|
|
||||||
Future<void> handleInitialLink() async {
|
Future<void> handleInitialLink() async {
|
||||||
|
@@ -1,14 +1,26 @@
|
|||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:island/models/publisher.dart';
|
||||||
|
|
||||||
part 'developer.freezed.dart';
|
part 'developer.freezed.dart';
|
||||||
part 'developer.g.dart';
|
part 'developer.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnDeveloper with _$SnDeveloper {
|
||||||
|
const factory SnDeveloper({
|
||||||
|
required String id,
|
||||||
|
required String publisherId,
|
||||||
|
SnPublisher? publisher,
|
||||||
|
}) = _SnDeveloper;
|
||||||
|
|
||||||
|
factory SnDeveloper.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnDeveloperFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class DeveloperStats with _$DeveloperStats {
|
sealed class DeveloperStats with _$DeveloperStats {
|
||||||
const factory DeveloperStats({
|
const factory DeveloperStats({@Default(0) int totalCustomApps}) =
|
||||||
@Default(0) int totalCustomApps,
|
_DeveloperStats;
|
||||||
}) = _DeveloperStats;
|
|
||||||
|
|
||||||
factory DeveloperStats.fromJson(Map<String, dynamic> json) =>
|
factory DeveloperStats.fromJson(Map<String, dynamic> json) =>
|
||||||
_$DeveloperStatsFromJson(json);
|
_$DeveloperStatsFromJson(json);
|
||||||
}
|
}
|
||||||
|
@@ -12,6 +12,293 @@ part of 'developer.dart';
|
|||||||
// dart format off
|
// dart format off
|
||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnDeveloper {
|
||||||
|
|
||||||
|
String get id; String get publisherId; SnPublisher? get publisher;
|
||||||
|
/// Create a copy of SnDeveloper
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnDeveloperCopyWith<SnDeveloper> get copyWith => _$SnDeveloperCopyWithImpl<SnDeveloper>(this as SnDeveloper, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnDeveloper to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnDeveloper&&(identical(other.id, id) || other.id == id)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisher, publisher) || other.publisher == publisher));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,publisherId,publisher);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnDeveloper(id: $id, publisherId: $publisherId, publisher: $publisher)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnDeveloperCopyWith<$Res> {
|
||||||
|
factory $SnDeveloperCopyWith(SnDeveloper value, $Res Function(SnDeveloper) _then) = _$SnDeveloperCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String publisherId, SnPublisher? publisher
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$SnPublisherCopyWith<$Res>? get publisher;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnDeveloperCopyWithImpl<$Res>
|
||||||
|
implements $SnDeveloperCopyWith<$Res> {
|
||||||
|
_$SnDeveloperCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnDeveloper _self;
|
||||||
|
final $Res Function(SnDeveloper) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnDeveloper
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? publisherId = null,Object? publisher = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,publisher: freezed == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnPublisher?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
/// Create a copy of SnDeveloper
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPublisherCopyWith<$Res>? get publisher {
|
||||||
|
if (_self.publisher == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPublisherCopyWith<$Res>(_self.publisher!, (value) {
|
||||||
|
return _then(_self.copyWith(publisher: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [SnDeveloper].
|
||||||
|
extension SnDeveloperPatterns on SnDeveloper {
|
||||||
|
/// 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( _SnDeveloper value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnDeveloper() 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( _SnDeveloper value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnDeveloper():
|
||||||
|
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( _SnDeveloper value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnDeveloper() 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 id, String publisherId, SnPublisher? publisher)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnDeveloper() when $default != null:
|
||||||
|
return $default(_that.id,_that.publisherId,_that.publisher);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 id, String publisherId, SnPublisher? publisher) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnDeveloper():
|
||||||
|
return $default(_that.id,_that.publisherId,_that.publisher);}
|
||||||
|
}
|
||||||
|
/// 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 id, String publisherId, SnPublisher? publisher)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnDeveloper() when $default != null:
|
||||||
|
return $default(_that.id,_that.publisherId,_that.publisher);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnDeveloper implements SnDeveloper {
|
||||||
|
const _SnDeveloper({required this.id, required this.publisherId, this.publisher});
|
||||||
|
factory _SnDeveloper.fromJson(Map<String, dynamic> json) => _$SnDeveloperFromJson(json);
|
||||||
|
|
||||||
|
@override final String id;
|
||||||
|
@override final String publisherId;
|
||||||
|
@override final SnPublisher? publisher;
|
||||||
|
|
||||||
|
/// Create a copy of SnDeveloper
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnDeveloperCopyWith<_SnDeveloper> get copyWith => __$SnDeveloperCopyWithImpl<_SnDeveloper>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnDeveloperToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnDeveloper&&(identical(other.id, id) || other.id == id)&&(identical(other.publisherId, publisherId) || other.publisherId == publisherId)&&(identical(other.publisher, publisher) || other.publisher == publisher));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,publisherId,publisher);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnDeveloper(id: $id, publisherId: $publisherId, publisher: $publisher)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnDeveloperCopyWith<$Res> implements $SnDeveloperCopyWith<$Res> {
|
||||||
|
factory _$SnDeveloperCopyWith(_SnDeveloper value, $Res Function(_SnDeveloper) _then) = __$SnDeveloperCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String publisherId, SnPublisher? publisher
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $SnPublisherCopyWith<$Res>? get publisher;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnDeveloperCopyWithImpl<$Res>
|
||||||
|
implements _$SnDeveloperCopyWith<$Res> {
|
||||||
|
__$SnDeveloperCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnDeveloper _self;
|
||||||
|
final $Res Function(_SnDeveloper) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnDeveloper
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? publisherId = null,Object? publisher = freezed,}) {
|
||||||
|
return _then(_SnDeveloper(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,publisherId: null == publisherId ? _self.publisherId : publisherId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,publisher: freezed == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnPublisher?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SnDeveloper
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnPublisherCopyWith<$Res>? get publisher {
|
||||||
|
if (_self.publisher == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnPublisherCopyWith<$Res>(_self.publisher!, (value) {
|
||||||
|
return _then(_self.copyWith(publisher: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$DeveloperStats {
|
mixin _$DeveloperStats {
|
||||||
|
|
||||||
|
@@ -6,6 +6,22 @@ part of 'developer.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
_SnDeveloper _$SnDeveloperFromJson(Map<String, dynamic> json) => _SnDeveloper(
|
||||||
|
id: json['id'] as String,
|
||||||
|
publisherId: json['publisher_id'] as String,
|
||||||
|
publisher:
|
||||||
|
json['publisher'] == null
|
||||||
|
? null
|
||||||
|
: SnPublisher.fromJson(json['publisher'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnDeveloperToJson(_SnDeveloper instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'publisher_id': instance.publisherId,
|
||||||
|
'publisher': instance.publisher?.toJson(),
|
||||||
|
};
|
||||||
|
|
||||||
_DeveloperStats _$DeveloperStatsFromJson(Map<String, dynamic> json) =>
|
_DeveloperStats _$DeveloperStatsFromJson(Map<String, dynamic> json) =>
|
||||||
_DeveloperStats(
|
_DeveloperStats(
|
||||||
totalCustomApps: (json['total_custom_apps'] as num?)?.toInt() ?? 0,
|
totalCustomApps: (json['total_custom_apps'] as num?)?.toInt() ?? 0,
|
||||||
|
@@ -36,8 +36,8 @@ sealed class SnPost with _$SnPost {
|
|||||||
@Default({}) Map<String, int> reactionsCount,
|
@Default({}) Map<String, int> reactionsCount,
|
||||||
@Default({}) Map<String, bool> reactionsMade,
|
@Default({}) Map<String, bool> reactionsMade,
|
||||||
@Default([]) List<dynamic> reactions,
|
@Default([]) List<dynamic> reactions,
|
||||||
@Default([]) List<PostTag> tags,
|
@Default([]) List<SnPostTag> tags,
|
||||||
@Default([]) List<PostCategory> categories,
|
@Default([]) List<SnPostCategory> categories,
|
||||||
@Default([]) List<dynamic> collections,
|
@Default([]) List<dynamic> collections,
|
||||||
@Default(null) DateTime? createdAt,
|
@Default(null) DateTime? createdAt,
|
||||||
@Default(null) DateTime? updatedAt,
|
@Default(null) DateTime? updatedAt,
|
||||||
|
@@ -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; 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;
|
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<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
|
||||||
/// Create a copy of SnPost
|
/// Create a copy of SnPost
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -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, Map<String, bool> reactionsMade, 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<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -94,8 +94,8 @@ as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : r
|
|||||||
as Map<String, int>,reactionsMade: null == reactionsMade ? _self.reactionsMade : reactionsMade // 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 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<SnPostTag>,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<SnPostCategory>,collections: null == collections ? _self.collections : collections // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,updatedAt: freezed == 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
|
||||||
@@ -227,7 +227,7 @@ 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, 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;
|
@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<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPost() when $default != null:
|
case _SnPost() when $default != null:
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.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 $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 _:
|
||||||
@@ -248,7 +248,7 @@ 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, 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;
|
@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<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPost():
|
case _SnPost():
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.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);}
|
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);}
|
||||||
@@ -265,7 +265,7 @@ 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, 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;
|
@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<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnPost() when $default != null:
|
case _SnPost() when $default != null:
|
||||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.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 $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 _:
|
||||||
@@ -280,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 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;
|
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<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
||||||
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -341,15 +341,15 @@ class _SnPost implements SnPost {
|
|||||||
return EqualUnmodifiableListView(_reactions);
|
return EqualUnmodifiableListView(_reactions);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<PostTag> _tags;
|
final List<SnPostTag> _tags;
|
||||||
@override@JsonKey() List<PostTag> get tags {
|
@override@JsonKey() List<SnPostTag> get tags {
|
||||||
if (_tags is EqualUnmodifiableListView) return _tags;
|
if (_tags is EqualUnmodifiableListView) return _tags;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_tags);
|
return EqualUnmodifiableListView(_tags);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<PostCategory> _categories;
|
final List<SnPostCategory> _categories;
|
||||||
@override@JsonKey() List<PostCategory> get categories {
|
@override@JsonKey() List<SnPostCategory> get categories {
|
||||||
if (_categories is EqualUnmodifiableListView) return _categories;
|
if (_categories is EqualUnmodifiableListView) return _categories;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_categories);
|
return EqualUnmodifiableListView(_categories);
|
||||||
@@ -400,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, Map<String, bool> reactionsMade, 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<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -446,8 +446,8 @@ as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount :
|
|||||||
as Map<String, int>,reactionsMade: null == reactionsMade ? _self._reactionsMade : reactionsMade // 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 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<SnPostTag>,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<SnPostCategory>,collections: null == collections ? _self._collections : collections // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,createdAt: freezed == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,updatedAt: freezed == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,updatedAt: freezed == 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
|
||||||
|
@@ -62,12 +62,12 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
|||||||
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>?)
|
||||||
?.map((e) => PostTag.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnPostTag.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
categories:
|
categories:
|
||||||
(json['categories'] as List<dynamic>?)
|
(json['categories'] as List<dynamic>?)
|
||||||
?.map((e) => PostCategory.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnPostCategory.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
collections: json['collections'] as List<dynamic>? ?? const [],
|
collections: json['collections'] as List<dynamic>? ?? const [],
|
||||||
|
@@ -1,19 +1,30 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
|
import 'package:island/services/text.dart';
|
||||||
|
|
||||||
part 'post_category.freezed.dart';
|
part 'post_category.freezed.dart';
|
||||||
part 'post_category.g.dart';
|
part 'post_category.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class PostCategory with _$PostCategory {
|
sealed class SnPostCategory with _$SnPostCategory {
|
||||||
const factory PostCategory({
|
const SnPostCategory._();
|
||||||
|
|
||||||
|
const factory SnPostCategory({
|
||||||
required String id,
|
required String id,
|
||||||
required String slug,
|
required String slug,
|
||||||
String? name,
|
String? name,
|
||||||
@Default([]) List<SnPost> posts,
|
@Default([]) List<SnPost> posts,
|
||||||
}) = _PostCategory;
|
}) = _SnPostCategory;
|
||||||
|
|
||||||
factory PostCategory.fromJson(Map<String, dynamic> json) =>
|
factory SnPostCategory.fromJson(Map<String, dynamic> json) =>
|
||||||
_$PostCategoryFromJson(json);
|
_$SnPostCategoryFromJson(json);
|
||||||
|
|
||||||
|
String get categoryDisplayTitle {
|
||||||
|
final capitalizedSlug = slug.capitalizeEachWord();
|
||||||
|
if ('postCategory$capitalizedSlug'.trExists()) {
|
||||||
|
return 'postCategory$capitalizedSlug'.tr();
|
||||||
|
}
|
||||||
|
return name ?? slug;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@@ -13,22 +13,22 @@ part of 'post_category.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$PostCategory {
|
mixin _$SnPostCategory {
|
||||||
|
|
||||||
String get id; String get slug; String? get name; List<SnPost> get posts;
|
String get id; String get slug; String? get name; List<SnPost> get posts;
|
||||||
/// Create a copy of PostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// 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)
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
$PostCategoryCopyWith<PostCategory> get copyWith => _$PostCategoryCopyWithImpl<PostCategory>(this as PostCategory, _$identity);
|
$SnPostCategoryCopyWith<SnPostCategory> get copyWith => _$SnPostCategoryCopyWithImpl<SnPostCategory>(this as SnPostCategory, _$identity);
|
||||||
|
|
||||||
/// Serializes this PostCategory to a JSON map.
|
/// Serializes this SnPostCategory to a JSON map.
|
||||||
Map<String, dynamic> toJson();
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is PostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -37,15 +37,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract mixin class $PostCategoryCopyWith<$Res> {
|
abstract mixin class $SnPostCategoryCopyWith<$Res> {
|
||||||
factory $PostCategoryCopyWith(PostCategory value, $Res Function(PostCategory) _then) = _$PostCategoryCopyWithImpl;
|
factory $SnPostCategoryCopyWith(SnPostCategory value, $Res Function(SnPostCategory) _then) = _$SnPostCategoryCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts
|
||||||
@@ -56,14 +56,14 @@ $Res call({
|
|||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class _$PostCategoryCopyWithImpl<$Res>
|
class _$SnPostCategoryCopyWithImpl<$Res>
|
||||||
implements $PostCategoryCopyWith<$Res> {
|
implements $SnPostCategoryCopyWith<$Res> {
|
||||||
_$PostCategoryCopyWithImpl(this._self, this._then);
|
_$SnPostCategoryCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
final PostCategory _self;
|
final SnPostCategory _self;
|
||||||
final $Res Function(PostCategory) _then;
|
final $Res Function(SnPostCategory) _then;
|
||||||
|
|
||||||
/// Create a copy of PostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// 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? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
@@ -78,8 +78,8 @@ as List<SnPost>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Adds pattern-matching-related methods to [PostCategory].
|
/// Adds pattern-matching-related methods to [SnPostCategory].
|
||||||
extension PostCategoryPatterns on PostCategory {
|
extension SnPostCategoryPatterns on SnPostCategory {
|
||||||
/// A variant of `map` that fallback to returning `orElse`.
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
///
|
///
|
||||||
/// It is equivalent to doing:
|
/// It is equivalent to doing:
|
||||||
@@ -92,10 +92,10 @@ extension PostCategoryPatterns on PostCategory {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _PostCategory value)? $default,{required TResult orElse(),}){
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SnPostCategory value)? $default,{required TResult orElse(),}){
|
||||||
final _that = this;
|
final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostCategory() when $default != null:
|
case _SnPostCategory() when $default != null:
|
||||||
return $default(_that);case _:
|
return $default(_that);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
@@ -114,10 +114,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _PostCategory value) $default,){
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SnPostCategory value) $default,){
|
||||||
final _that = this;
|
final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostCategory():
|
case _SnPostCategory():
|
||||||
return $default(_that);}
|
return $default(_that);}
|
||||||
}
|
}
|
||||||
/// A variant of `map` that fallback to returning `null`.
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
@@ -132,10 +132,10 @@ return $default(_that);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _PostCategory value)? $default,){
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SnPostCategory value)? $default,){
|
||||||
final _that = this;
|
final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostCategory() when $default != null:
|
case _SnPostCategory() when $default != null:
|
||||||
return $default(_that);case _:
|
return $default(_that);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ return $default(_that);case _:
|
|||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostCategory() when $default != null:
|
case _SnPostCategory() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostCategory():
|
case _SnPostCategory():
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
@@ -193,7 +193,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
|||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostCategory() when $default != null:
|
case _SnPostCategory() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -205,9 +205,9 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _PostCategory implements PostCategory {
|
class _SnPostCategory extends SnPostCategory {
|
||||||
const _PostCategory({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts;
|
const _SnPostCategory({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts,super._();
|
||||||
factory _PostCategory.fromJson(Map<String, dynamic> json) => _$PostCategoryFromJson(json);
|
factory _SnPostCategory.fromJson(Map<String, dynamic> json) => _$SnPostCategoryFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@override final String slug;
|
@override final String slug;
|
||||||
@@ -220,20 +220,20 @@ class _PostCategory implements PostCategory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a copy of PostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$PostCategoryCopyWith<_PostCategory> get copyWith => __$PostCategoryCopyWithImpl<_PostCategory>(this, _$identity);
|
_$SnPostCategoryCopyWith<_SnPostCategory> get copyWith => __$SnPostCategoryCopyWithImpl<_SnPostCategory>(this, _$identity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return _$PostCategoryToJson(this, );
|
return _$SnPostCategoryToJson(this, );
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -242,15 +242,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract mixin class _$PostCategoryCopyWith<$Res> implements $PostCategoryCopyWith<$Res> {
|
abstract mixin class _$SnPostCategoryCopyWith<$Res> implements $SnPostCategoryCopyWith<$Res> {
|
||||||
factory _$PostCategoryCopyWith(_PostCategory value, $Res Function(_PostCategory) _then) = __$PostCategoryCopyWithImpl;
|
factory _$SnPostCategoryCopyWith(_SnPostCategory value, $Res Function(_SnPostCategory) _then) = __$SnPostCategoryCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts
|
||||||
@@ -261,17 +261,17 @@ $Res call({
|
|||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class __$PostCategoryCopyWithImpl<$Res>
|
class __$SnPostCategoryCopyWithImpl<$Res>
|
||||||
implements _$PostCategoryCopyWith<$Res> {
|
implements _$SnPostCategoryCopyWith<$Res> {
|
||||||
__$PostCategoryCopyWithImpl(this._self, this._then);
|
__$SnPostCategoryCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
final _PostCategory _self;
|
final _SnPostCategory _self;
|
||||||
final $Res Function(_PostCategory) _then;
|
final $Res Function(_SnPostCategory) _then;
|
||||||
|
|
||||||
/// Create a copy of PostCategory
|
/// Create a copy of SnPostCategory
|
||||||
/// 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? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||||
return _then(_PostCategory(
|
return _then(_SnPostCategory(
|
||||||
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,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
|
@@ -6,8 +6,8 @@ part of 'post_category.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
_PostCategory _$PostCategoryFromJson(Map<String, dynamic> json) =>
|
_SnPostCategory _$SnPostCategoryFromJson(Map<String, dynamic> json) =>
|
||||||
_PostCategory(
|
_SnPostCategory(
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
slug: json['slug'] as String,
|
slug: json['slug'] as String,
|
||||||
name: json['name'] as String?,
|
name: json['name'] as String?,
|
||||||
@@ -18,7 +18,7 @@ _PostCategory _$PostCategoryFromJson(Map<String, dynamic> json) =>
|
|||||||
const [],
|
const [],
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$PostCategoryToJson(_PostCategory instance) =>
|
Map<String, dynamic> _$SnPostCategoryToJson(_SnPostCategory instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'slug': instance.slug,
|
'slug': instance.slug,
|
||||||
|
@@ -1,4 +1,3 @@
|
|||||||
|
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
|
|
||||||
@@ -6,14 +5,14 @@ part 'post_tag.freezed.dart';
|
|||||||
part 'post_tag.g.dart';
|
part 'post_tag.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class PostTag with _$PostTag {
|
sealed class SnPostTag with _$SnPostTag {
|
||||||
const factory PostTag({
|
const factory SnPostTag({
|
||||||
required String id,
|
required String id,
|
||||||
required String slug,
|
required String slug,
|
||||||
String? name,
|
String? name,
|
||||||
@Default([]) List<SnPost> posts,
|
@Default([]) List<SnPost> posts,
|
||||||
}) = _PostTag;
|
}) = _SnPostTag;
|
||||||
|
|
||||||
factory PostTag.fromJson(Map<String, dynamic> json) =>
|
factory SnPostTag.fromJson(Map<String, dynamic> json) =>
|
||||||
_$PostTagFromJson(json);
|
_$SnPostTagFromJson(json);
|
||||||
}
|
}
|
||||||
|
@@ -13,22 +13,22 @@ part of 'post_tag.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$PostTag {
|
mixin _$SnPostTag {
|
||||||
|
|
||||||
String get id; String get slug; String? get name; List<SnPost> get posts;
|
String get id; String get slug; String? get name; List<SnPost> get posts;
|
||||||
/// Create a copy of PostTag
|
/// Create a copy of SnPostTag
|
||||||
/// 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)
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
$PostTagCopyWith<PostTag> get copyWith => _$PostTagCopyWithImpl<PostTag>(this as PostTag, _$identity);
|
$SnPostTagCopyWith<SnPostTag> get copyWith => _$SnPostTagCopyWithImpl<SnPostTag>(this as SnPostTag, _$identity);
|
||||||
|
|
||||||
/// Serializes this PostTag to a JSON map.
|
/// Serializes this SnPostTag to a JSON map.
|
||||||
Map<String, dynamic> toJson();
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is PostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -37,15 +37,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract mixin class $PostTagCopyWith<$Res> {
|
abstract mixin class $SnPostTagCopyWith<$Res> {
|
||||||
factory $PostTagCopyWith(PostTag value, $Res Function(PostTag) _then) = _$PostTagCopyWithImpl;
|
factory $SnPostTagCopyWith(SnPostTag value, $Res Function(SnPostTag) _then) = _$SnPostTagCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts
|
||||||
@@ -56,14 +56,14 @@ $Res call({
|
|||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class _$PostTagCopyWithImpl<$Res>
|
class _$SnPostTagCopyWithImpl<$Res>
|
||||||
implements $PostTagCopyWith<$Res> {
|
implements $SnPostTagCopyWith<$Res> {
|
||||||
_$PostTagCopyWithImpl(this._self, this._then);
|
_$SnPostTagCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
final PostTag _self;
|
final SnPostTag _self;
|
||||||
final $Res Function(PostTag) _then;
|
final $Res Function(SnPostTag) _then;
|
||||||
|
|
||||||
/// Create a copy of PostTag
|
/// Create a copy of SnPostTag
|
||||||
/// 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? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
@@ -78,8 +78,8 @@ as List<SnPost>,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Adds pattern-matching-related methods to [PostTag].
|
/// Adds pattern-matching-related methods to [SnPostTag].
|
||||||
extension PostTagPatterns on PostTag {
|
extension SnPostTagPatterns on SnPostTag {
|
||||||
/// A variant of `map` that fallback to returning `orElse`.
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
///
|
///
|
||||||
/// It is equivalent to doing:
|
/// It is equivalent to doing:
|
||||||
@@ -92,10 +92,10 @@ extension PostTagPatterns on PostTag {
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _PostTag value)? $default,{required TResult orElse(),}){
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SnPostTag value)? $default,{required TResult orElse(),}){
|
||||||
final _that = this;
|
final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostTag() when $default != null:
|
case _SnPostTag() when $default != null:
|
||||||
return $default(_that);case _:
|
return $default(_that);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
@@ -114,10 +114,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _PostTag value) $default,){
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SnPostTag value) $default,){
|
||||||
final _that = this;
|
final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostTag():
|
case _SnPostTag():
|
||||||
return $default(_that);}
|
return $default(_that);}
|
||||||
}
|
}
|
||||||
/// A variant of `map` that fallback to returning `null`.
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
@@ -132,10 +132,10 @@ return $default(_that);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _PostTag value)? $default,){
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SnPostTag value)? $default,){
|
||||||
final _that = this;
|
final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostTag() when $default != null:
|
case _SnPostTag() when $default != null:
|
||||||
return $default(_that);case _:
|
return $default(_that);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -155,7 +155,7 @@ return $default(_that);case _:
|
|||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostTag() when $default != null:
|
case _SnPostTag() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
@@ -176,7 +176,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostTag():
|
case _SnPostTag():
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
@@ -193,7 +193,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
|||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _PostTag() when $default != null:
|
case _SnPostTag() when $default != null:
|
||||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
@@ -205,9 +205,9 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _PostTag implements PostTag {
|
class _SnPostTag implements SnPostTag {
|
||||||
const _PostTag({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts;
|
const _SnPostTag({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts;
|
||||||
factory _PostTag.fromJson(Map<String, dynamic> json) => _$PostTagFromJson(json);
|
factory _SnPostTag.fromJson(Map<String, dynamic> json) => _$SnPostTagFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@override final String slug;
|
@override final String slug;
|
||||||
@@ -220,20 +220,20 @@ class _PostTag implements PostTag {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a copy of PostTag
|
/// Create a copy of SnPostTag
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$PostTagCopyWith<_PostTag> get copyWith => __$PostTagCopyWithImpl<_PostTag>(this, _$identity);
|
_$SnPostTagCopyWith<_SnPostTag> get copyWith => __$SnPostTagCopyWithImpl<_SnPostTag>(this, _$identity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return _$PostTagToJson(this, );
|
return _$SnPostTagToJson(this, );
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _PostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -242,15 +242,15 @@ int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEqu
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'PostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract mixin class _$PostTagCopyWith<$Res> implements $PostTagCopyWith<$Res> {
|
abstract mixin class _$SnPostTagCopyWith<$Res> implements $SnPostTagCopyWith<$Res> {
|
||||||
factory _$PostTagCopyWith(_PostTag value, $Res Function(_PostTag) _then) = __$PostTagCopyWithImpl;
|
factory _$SnPostTagCopyWith(_SnPostTag value, $Res Function(_SnPostTag) _then) = __$SnPostTagCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String? name, List<SnPost> posts
|
String id, String slug, String? name, List<SnPost> posts
|
||||||
@@ -261,17 +261,17 @@ $Res call({
|
|||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class __$PostTagCopyWithImpl<$Res>
|
class __$SnPostTagCopyWithImpl<$Res>
|
||||||
implements _$PostTagCopyWith<$Res> {
|
implements _$SnPostTagCopyWith<$Res> {
|
||||||
__$PostTagCopyWithImpl(this._self, this._then);
|
__$SnPostTagCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
final _PostTag _self;
|
final _SnPostTag _self;
|
||||||
final $Res Function(_PostTag) _then;
|
final $Res Function(_SnPostTag) _then;
|
||||||
|
|
||||||
/// Create a copy of PostTag
|
/// Create a copy of SnPostTag
|
||||||
/// 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? slug = null,Object? name = freezed,Object? posts = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||||
return _then(_PostTag(
|
return _then(_SnPostTag(
|
||||||
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,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
|
@@ -6,7 +6,7 @@ part of 'post_tag.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
_PostTag _$PostTagFromJson(Map<String, dynamic> json) => _PostTag(
|
_SnPostTag _$SnPostTagFromJson(Map<String, dynamic> json) => _SnPostTag(
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
slug: json['slug'] as String,
|
slug: json['slug'] as String,
|
||||||
name: json['name'] as String?,
|
name: json['name'] as String?,
|
||||||
@@ -17,9 +17,10 @@ _PostTag _$PostTagFromJson(Map<String, dynamic> json) => _PostTag(
|
|||||||
const [],
|
const [],
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$PostTagToJson(_PostTag instance) => <String, dynamic>{
|
Map<String, dynamic> _$SnPostTagToJson(_SnPostTag instance) =>
|
||||||
'id': instance.id,
|
<String, dynamic>{
|
||||||
'slug': instance.slug,
|
'id': instance.id,
|
||||||
'name': instance.name,
|
'slug': instance.slug,
|
||||||
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
'name': instance.name,
|
||||||
};
|
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
|
@@ -25,6 +25,32 @@ sealed class SnAccount with _$SnAccount {
|
|||||||
_$SnAccountFromJson(json);
|
_$SnAccountFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class ProfileLink with _$ProfileLink {
|
||||||
|
const factory ProfileLink({required String name, required String url}) =
|
||||||
|
_ProfileLink;
|
||||||
|
|
||||||
|
factory ProfileLink.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$ProfileLinkFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ProfileLinkConverter
|
||||||
|
implements JsonConverter<List<ProfileLink>, dynamic> {
|
||||||
|
const ProfileLinkConverter();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<ProfileLink> fromJson(dynamic json) {
|
||||||
|
return json is List<dynamic>
|
||||||
|
? json.map((e) => ProfileLink.fromJson(e)).cast<ProfileLink>().toList()
|
||||||
|
: <ProfileLink>[];
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<dynamic> toJson(List<ProfileLink> object) {
|
||||||
|
return object.map((e) => e.toJson()).toList();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class SnAccountProfile with _$SnAccountProfile {
|
sealed class SnAccountProfile with _$SnAccountProfile {
|
||||||
const factory SnAccountProfile({
|
const factory SnAccountProfile({
|
||||||
@@ -38,6 +64,7 @@ sealed class SnAccountProfile with _$SnAccountProfile {
|
|||||||
@Default('') String location,
|
@Default('') String location,
|
||||||
@Default('') String timeZone,
|
@Default('') String timeZone,
|
||||||
DateTime? birthday,
|
DateTime? birthday,
|
||||||
|
@ProfileLinkConverter() @Default([]) List<ProfileLink> links,
|
||||||
DateTime? lastSeenAt,
|
DateTime? lastSeenAt,
|
||||||
SnAccountBadge? activeBadge,
|
SnAccountBadge? activeBadge,
|
||||||
required int experience,
|
required int experience,
|
||||||
|
@@ -347,10 +347,270 @@ $SnWalletSubscriptionRefCopyWith<$Res>? get perkSubscription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$ProfileLink {
|
||||||
|
|
||||||
|
String get name; String get url;
|
||||||
|
/// Create a copy of ProfileLink
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$ProfileLinkCopyWith<ProfileLink> get copyWith => _$ProfileLinkCopyWithImpl<ProfileLink>(this as ProfileLink, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this ProfileLink to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is ProfileLink&&(identical(other.name, name) || other.name == name)&&(identical(other.url, url) || other.url == url));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,name,url);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfileLink(name: $name, url: $url)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $ProfileLinkCopyWith<$Res> {
|
||||||
|
factory $ProfileLinkCopyWith(ProfileLink value, $Res Function(ProfileLink) _then) = _$ProfileLinkCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String name, String url
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$ProfileLinkCopyWithImpl<$Res>
|
||||||
|
implements $ProfileLinkCopyWith<$Res> {
|
||||||
|
_$ProfileLinkCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final ProfileLink _self;
|
||||||
|
final $Res Function(ProfileLink) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProfileLink
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? name = null,Object? url = null,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [ProfileLink].
|
||||||
|
extension ProfileLinkPatterns on ProfileLink {
|
||||||
|
/// 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( _ProfileLink value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _ProfileLink() 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( _ProfileLink value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _ProfileLink():
|
||||||
|
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( _ProfileLink value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _ProfileLink() 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 name, String url)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _ProfileLink() when $default != null:
|
||||||
|
return $default(_that.name,_that.url);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 name, String url) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _ProfileLink():
|
||||||
|
return $default(_that.name,_that.url);}
|
||||||
|
}
|
||||||
|
/// 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 name, String url)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _ProfileLink() when $default != null:
|
||||||
|
return $default(_that.name,_that.url);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _ProfileLink implements ProfileLink {
|
||||||
|
const _ProfileLink({required this.name, required this.url});
|
||||||
|
factory _ProfileLink.fromJson(Map<String, dynamic> json) => _$ProfileLinkFromJson(json);
|
||||||
|
|
||||||
|
@override final String name;
|
||||||
|
@override final String url;
|
||||||
|
|
||||||
|
/// Create a copy of ProfileLink
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$ProfileLinkCopyWith<_ProfileLink> get copyWith => __$ProfileLinkCopyWithImpl<_ProfileLink>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$ProfileLinkToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ProfileLink&&(identical(other.name, name) || other.name == name)&&(identical(other.url, url) || other.url == url));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,name,url);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'ProfileLink(name: $name, url: $url)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$ProfileLinkCopyWith<$Res> implements $ProfileLinkCopyWith<$Res> {
|
||||||
|
factory _$ProfileLinkCopyWith(_ProfileLink value, $Res Function(_ProfileLink) _then) = __$ProfileLinkCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String name, String url
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$ProfileLinkCopyWithImpl<$Res>
|
||||||
|
implements _$ProfileLinkCopyWith<$Res> {
|
||||||
|
__$ProfileLinkCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _ProfileLink _self;
|
||||||
|
final $Res Function(_ProfileLink) _then;
|
||||||
|
|
||||||
|
/// Create a copy of ProfileLink
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? name = null,Object? url = null,}) {
|
||||||
|
return _then(_ProfileLink(
|
||||||
|
name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAccountProfile {
|
mixin _$SnAccountProfile {
|
||||||
|
|
||||||
String get id; String get firstName; String get middleName; String get lastName; String get bio; String get gender; String get pronouns; String get location; String get timeZone; DateTime? get birthday; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String get firstName; String get middleName; String get lastName; String get bio; String get gender; String get pronouns; String get location; String get timeZone; DateTime? get birthday;@ProfileLinkConverter() List<ProfileLink> get links; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get 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)
|
||||||
@@ -363,16 +623,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.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other.links, links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.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,createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(links),lastSeenAt,activeBadge,experience,level,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, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -383,7 +643,7 @@ abstract mixin class $SnAccountProfileCopyWith<$Res> {
|
|||||||
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -400,7 +660,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? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? 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
|
||||||
@@ -412,7 +672,8 @@ as String,pronouns: null == pronouns ? _self.pronouns : pronouns // ignore: cast
|
|||||||
as String,location: null == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
as String,location: null == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
as String,timeZone: null == timeZone ? _self.timeZone : timeZone // ignore: cast_nullable_to_non_nullable
|
as String,timeZone: null == timeZone ? _self.timeZone : timeZone // ignore: cast_nullable_to_non_nullable
|
||||||
as String,birthday: freezed == birthday ? _self.birthday : birthday // ignore: cast_nullable_to_non_nullable
|
as String,birthday: freezed == birthday ? _self.birthday : birthday // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : lastSeenAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,links: null == links ? _self.links : links // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<ProfileLink>,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : lastSeenAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -553,10 +814,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, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double 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.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -574,10 +835,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, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double 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.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.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`
|
||||||
///
|
///
|
||||||
@@ -591,10 +852,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, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double 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.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -606,7 +867,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.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, @ProfileLinkConverter() final List<ProfileLink> links = const [], this.lastSeenAt, this.activeBadge, required this.experience, required this.level, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.createdAt, required this.updatedAt, required this.deletedAt}): _links = links;
|
||||||
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;
|
||||||
@@ -619,6 +880,13 @@ class _SnAccountProfile implements SnAccountProfile {
|
|||||||
@override@JsonKey() final String location;
|
@override@JsonKey() final String location;
|
||||||
@override@JsonKey() final String timeZone;
|
@override@JsonKey() final String timeZone;
|
||||||
@override final DateTime? birthday;
|
@override final DateTime? birthday;
|
||||||
|
final List<ProfileLink> _links;
|
||||||
|
@override@JsonKey()@ProfileLinkConverter() List<ProfileLink> get links {
|
||||||
|
if (_links is EqualUnmodifiableListView) return _links;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_links);
|
||||||
|
}
|
||||||
|
|
||||||
@override final DateTime? lastSeenAt;
|
@override final DateTime? lastSeenAt;
|
||||||
@override final SnAccountBadge? activeBadge;
|
@override final SnAccountBadge? activeBadge;
|
||||||
@override final int experience;
|
@override final int experience;
|
||||||
@@ -644,16 +912,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.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other._links, _links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.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,createdAt,updatedAt,deletedAt]);
|
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(_links),lastSeenAt,activeBadge,experience,level,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, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -664,7 +932,7 @@ abstract mixin class _$SnAccountProfileCopyWith<$Res> implements $SnAccountProfi
|
|||||||
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -681,7 +949,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? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? 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
|
||||||
@@ -693,7 +961,8 @@ as String,pronouns: null == pronouns ? _self.pronouns : pronouns // ignore: cast
|
|||||||
as String,location: null == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
as String,location: null == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
as String,timeZone: null == timeZone ? _self.timeZone : timeZone // ignore: cast_nullable_to_non_nullable
|
as String,timeZone: null == timeZone ? _self.timeZone : timeZone // ignore: cast_nullable_to_non_nullable
|
||||||
as String,birthday: freezed == birthday ? _self.birthday : birthday // ignore: cast_nullable_to_non_nullable
|
as String,birthday: freezed == birthday ? _self.birthday : birthday // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : lastSeenAt // ignore: cast_nullable_to_non_nullable
|
as DateTime?,links: null == links ? _self._links : links // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<ProfileLink>,lastSeenAt: freezed == lastSeenAt ? _self.lastSeenAt : lastSeenAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
as DateTime?,activeBadge: freezed == activeBadge ? _self.activeBadge : activeBadge // ignore: cast_nullable_to_non_nullable
|
||||||
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
as SnAccountBadge?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||||
|
@@ -47,6 +47,12 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
|||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_ProfileLink _$ProfileLinkFromJson(Map<String, dynamic> json) =>
|
||||||
|
_ProfileLink(name: json['name'] as String, url: json['url'] as String);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$ProfileLinkToJson(_ProfileLink instance) =>
|
||||||
|
<String, dynamic>{'name': instance.name, 'url': instance.url};
|
||||||
|
|
||||||
_SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
_SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
||||||
_SnAccountProfile(
|
_SnAccountProfile(
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
@@ -62,6 +68,10 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
|||||||
json['birthday'] == null
|
json['birthday'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['birthday'] as String),
|
: DateTime.parse(json['birthday'] as String),
|
||||||
|
links:
|
||||||
|
json['links'] == null
|
||||||
|
? const []
|
||||||
|
: const ProfileLinkConverter().fromJson(json['links']),
|
||||||
lastSeenAt:
|
lastSeenAt:
|
||||||
json['last_seen_at'] == null
|
json['last_seen_at'] == null
|
||||||
? null
|
? null
|
||||||
@@ -111,6 +121,7 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
|||||||
'location': instance.location,
|
'location': instance.location,
|
||||||
'time_zone': instance.timeZone,
|
'time_zone': instance.timeZone,
|
||||||
'birthday': instance.birthday?.toIso8601String(),
|
'birthday': instance.birthday?.toIso8601String(),
|
||||||
|
'links': const ProfileLinkConverter().toJson(instance.links),
|
||||||
'last_seen_at': instance.lastSeenAt?.toIso8601String(),
|
'last_seen_at': instance.lastSeenAt?.toIso8601String(),
|
||||||
'active_badge': instance.activeBadge?.toJson(),
|
'active_badge': instance.activeBadge?.toJson(),
|
||||||
'experience': instance.experience,
|
'experience': instance.experience,
|
||||||
|
@@ -7,6 +7,7 @@ import 'package:island/screens/developers/edit_app.dart';
|
|||||||
import 'package:island/screens/developers/new_app.dart';
|
import 'package:island/screens/developers/new_app.dart';
|
||||||
import 'package:island/screens/developers/hub.dart';
|
import 'package:island/screens/developers/hub.dart';
|
||||||
import 'package:island/screens/discovery/articles.dart';
|
import 'package:island/screens/discovery/articles.dart';
|
||||||
|
import 'package:island/screens/posts/post_category_detail.dart';
|
||||||
import 'package:island/screens/posts/post_search.dart';
|
import 'package:island/screens/posts/post_search.dart';
|
||||||
import 'package:island/widgets/app_wrapper.dart';
|
import 'package:island/widgets/app_wrapper.dart';
|
||||||
import 'package:island/screens/tabs.dart';
|
import 'package:island/screens/tabs.dart';
|
||||||
@@ -322,15 +323,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
builder: (context, state) => const AboutScreen(),
|
builder: (context, state) => const AboutScreen(),
|
||||||
),
|
),
|
||||||
|
|
||||||
GoRoute(
|
|
||||||
name: 'reportDetail',
|
|
||||||
path: '/safety/reports/me/:id',
|
|
||||||
builder: (context, state) {
|
|
||||||
final id = state.pathParameters['id']!;
|
|
||||||
return AbuseReportDetailScreen(reportId: id);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
|
|
||||||
// Main tabs with TabsScreen shell
|
// Main tabs with TabsScreen shell
|
||||||
ShellRoute(
|
ShellRoute(
|
||||||
navigatorKey: _tabsShellKey,
|
navigatorKey: _tabsShellKey,
|
||||||
@@ -357,6 +349,25 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
return PostDetailScreen(id: id);
|
return PostDetailScreen(id: id);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
name: 'postCategoryDetail',
|
||||||
|
path: '/posts/categories/:slug',
|
||||||
|
builder: (context, state) {
|
||||||
|
final slug = state.pathParameters['slug']!;
|
||||||
|
return PostCategoryDetailScreen(slug: slug, isCategory: true);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
GoRoute(
|
||||||
|
name: 'postTagDetail',
|
||||||
|
path: '/posts/tags/:slug',
|
||||||
|
builder: (context, state) {
|
||||||
|
final slug = state.pathParameters['slug']!;
|
||||||
|
return PostCategoryDetailScreen(
|
||||||
|
slug: slug,
|
||||||
|
isCategory: false,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
GoRoute(
|
GoRoute(
|
||||||
name: 'publisherProfile',
|
name: 'publisherProfile',
|
||||||
path: '/publishers/:name',
|
path: '/publishers/:name',
|
||||||
@@ -505,6 +516,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
|||||||
path: '/safety/reports/me',
|
path: '/safety/reports/me',
|
||||||
builder: (context, state) => const AbuseReportListScreen(),
|
builder: (context, state) => const AbuseReportListScreen(),
|
||||||
),
|
),
|
||||||
|
GoRoute(
|
||||||
|
name: 'reportDetail',
|
||||||
|
path: '/safety/reports/me/:id',
|
||||||
|
builder: (context, state) {
|
||||||
|
final id = state.pathParameters['id']!;
|
||||||
|
return AbuseReportDetailScreen(reportId: id);
|
||||||
|
},
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|
||||||
|
@@ -7,12 +7,12 @@ import 'package:flutter/services.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/services/udid.native.dart';
|
import 'package:island/services/udid.native.dart';
|
||||||
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:island/services/update_service.dart';
|
import 'package:island/services/update_service.dart';
|
||||||
import 'package:island/widgets/content/sheet.dart';
|
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
@@ -102,235 +102,226 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
|
|||||||
? const Center(child: CircularProgressIndicator())
|
? const Center(child: CircularProgressIndicator())
|
||||||
: _errorMessage != null
|
: _errorMessage != null
|
||||||
? Center(child: Text(_errorMessage!))
|
? Center(child: Text(_errorMessage!))
|
||||||
: SingleChildScrollView(
|
: Center(
|
||||||
child: Column(
|
child: ConstrainedBox(
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
constraints: const BoxConstraints(maxWidth: 540),
|
||||||
children: [
|
child: SingleChildScrollView(
|
||||||
const SizedBox(height: 24),
|
child: Column(
|
||||||
// App Icon and Name
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
CircleAvatar(
|
|
||||||
radius: 50,
|
|
||||||
backgroundColor: theme.colorScheme.primary.withOpacity(
|
|
||||||
0.1,
|
|
||||||
),
|
|
||||||
child: Image.asset(
|
|
||||||
'assets/icons/icon.png',
|
|
||||||
width: 56,
|
|
||||||
height: 56,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Text(
|
|
||||||
_packageInfo.appName,
|
|
||||||
style: theme.textTheme.headlineSmall?.copyWith(
|
|
||||||
fontWeight: FontWeight.bold,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Text(
|
|
||||||
'aboutScreenVersionInfo'.tr(
|
|
||||||
args: [_packageInfo.version, _packageInfo.buildNumber],
|
|
||||||
),
|
|
||||||
style: theme.textTheme.bodyMedium?.copyWith(
|
|
||||||
color: theme.textTheme.bodySmall?.color,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const SizedBox(height: 32),
|
|
||||||
|
|
||||||
// App Info Card
|
|
||||||
_buildSection(
|
|
||||||
context,
|
|
||||||
title: 'aboutScreenAppInfoSectionTitle'.tr(),
|
|
||||||
children: [
|
children: [
|
||||||
_buildInfoItem(
|
const SizedBox(height: 24),
|
||||||
context,
|
// App Icon and Name
|
||||||
icon: Symbols.info,
|
CircleAvatar(
|
||||||
label: 'aboutScreenPackageNameLabel'.tr(),
|
radius: 50,
|
||||||
value: _packageInfo.packageName,
|
backgroundColor: theme.colorScheme.primary
|
||||||
),
|
.withOpacity(0.1),
|
||||||
_buildInfoItem(
|
child: Image.asset(
|
||||||
context,
|
'assets/icons/icon.png',
|
||||||
icon: Symbols.update,
|
width: 56,
|
||||||
label: 'aboutScreenVersionLabel'.tr(),
|
height: 56,
|
||||||
value: _packageInfo.version,
|
|
||||||
),
|
|
||||||
_buildInfoItem(
|
|
||||||
context,
|
|
||||||
icon: Symbols.build,
|
|
||||||
label: 'aboutScreenBuildNumberLabel'.tr(),
|
|
||||||
value: _packageInfo.buildNumber,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
if (_deviceInfo != null) const SizedBox(height: 16),
|
|
||||||
|
|
||||||
if (_deviceInfo != null)
|
|
||||||
_buildSection(
|
|
||||||
context,
|
|
||||||
title: 'Device Information',
|
|
||||||
children: [
|
|
||||||
_buildInfoItem(
|
|
||||||
context,
|
|
||||||
icon: Symbols.label,
|
|
||||||
label: 'aboutDeviceName'.tr(),
|
|
||||||
value: _deviceInfo?.data['name'],
|
|
||||||
),
|
),
|
||||||
_buildInfoItem(
|
),
|
||||||
context,
|
const SizedBox(height: 16),
|
||||||
icon: Symbols.fingerprint,
|
Text(
|
||||||
label: 'aboutDeviceIdentifier'.tr(),
|
_packageInfo.appName,
|
||||||
value: _deviceUdid ?? 'N/A',
|
style: theme.textTheme.headlineSmall?.copyWith(
|
||||||
copyable: true,
|
fontWeight: FontWeight.bold,
|
||||||
),
|
),
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Links Card
|
|
||||||
_buildSection(
|
|
||||||
context,
|
|
||||||
title: 'aboutScreenLinksSectionTitle'.tr(),
|
|
||||||
children: [
|
|
||||||
_buildListTile(
|
|
||||||
context,
|
|
||||||
icon: Symbols.system_update,
|
|
||||||
title: 'Check for updates',
|
|
||||||
onTap: () async {
|
|
||||||
// Fetch latest release and show the unified sheet
|
|
||||||
final svc = UpdateService();
|
|
||||||
// Reuse service fetch + compare to decide content
|
|
||||||
final release = await svc.fetchLatestRelease();
|
|
||||||
if (release != null) {
|
|
||||||
await svc.showUpdateSheet(context, release);
|
|
||||||
} else {
|
|
||||||
// Fallback: show a simple sheet indicating no info
|
|
||||||
// Use your SheetScaffold for consistent styling
|
|
||||||
// Show a minimal message
|
|
||||||
// ignore: use_build_context_synchronously
|
|
||||||
showModalBottomSheet(
|
|
||||||
context: context,
|
|
||||||
isScrollControlled: true,
|
|
||||||
useSafeArea: true,
|
|
||||||
showDragHandle: true,
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(context).colorScheme.surface,
|
|
||||||
builder:
|
|
||||||
(_) => const SheetScaffold(
|
|
||||||
titleText: 'Update',
|
|
||||||
child: Center(
|
|
||||||
child: Padding(
|
|
||||||
padding: EdgeInsets.all(24),
|
|
||||||
child: Text(
|
|
||||||
'Unable to fetch release info at this time.',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
_buildListTile(
|
Text(
|
||||||
context,
|
'aboutScreenVersionInfo'.tr(
|
||||||
icon: Symbols.privacy_tip,
|
args: [
|
||||||
title: 'aboutScreenPrivacyPolicyTitle'.tr(),
|
_packageInfo.version,
|
||||||
onTap:
|
_packageInfo.buildNumber,
|
||||||
() => _launchURL(
|
],
|
||||||
'https://solsynth.dev/terms/privacy-policy',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_buildListTile(
|
|
||||||
context,
|
|
||||||
icon: Symbols.description,
|
|
||||||
title: 'aboutScreenTermsOfServiceTitle'.tr(),
|
|
||||||
onTap:
|
|
||||||
() => _launchURL(
|
|
||||||
'https://solsynth.dev/terms/user-agreement',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
_buildListTile(
|
|
||||||
context,
|
|
||||||
icon: Symbols.code,
|
|
||||||
title: 'aboutScreenOpenSourceLicensesTitle'.tr(),
|
|
||||||
onTap: () {
|
|
||||||
showLicensePage(
|
|
||||||
context: context,
|
|
||||||
applicationName: _packageInfo.appName,
|
|
||||||
applicationVersion:
|
|
||||||
'Version ${_packageInfo.version}',
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
|
|
||||||
// Developer Info
|
|
||||||
_buildSection(
|
|
||||||
context,
|
|
||||||
title: 'aboutScreenDeveloperSectionTitle'.tr(),
|
|
||||||
children: [
|
|
||||||
_buildListTile(
|
|
||||||
context,
|
|
||||||
icon: Symbols.email,
|
|
||||||
title: 'aboutScreenContactUsTitle'.tr(),
|
|
||||||
subtitle: 'lily@solsynth.dev',
|
|
||||||
onTap: () => _launchURL('mailto:lily@solsynth.dev'),
|
|
||||||
),
|
|
||||||
_buildListTile(
|
|
||||||
context,
|
|
||||||
icon: Symbols.copyright,
|
|
||||||
title: 'aboutScreenLicenseTitle'.tr(),
|
|
||||||
subtitle: 'aboutScreenLicenseContent'.tr(
|
|
||||||
args: [DateTime.now().year.toString()],
|
|
||||||
),
|
),
|
||||||
onTap:
|
style: theme.textTheme.bodyMedium?.copyWith(
|
||||||
() => _launchURL(
|
color: theme.textTheme.bodySmall?.color,
|
||||||
'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt',
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (kIsWeb || !(Platform.isMacOS || Platform.isIOS))
|
|
||||||
_buildListTile(
|
|
||||||
context,
|
|
||||||
icon: Symbols.favorite,
|
|
||||||
title: 'donate'.tr(),
|
|
||||||
subtitle: 'donateDescription'.tr(),
|
|
||||||
onTap: () {
|
|
||||||
launchUrlString(
|
|
||||||
'https://afdian.com/@littlesheep',
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
],
|
),
|
||||||
),
|
const SizedBox(height: 32),
|
||||||
|
|
||||||
const SizedBox(height: 32),
|
// App Info Card
|
||||||
|
_buildSection(
|
||||||
// Copyright
|
context,
|
||||||
Padding(
|
title: 'aboutScreenAppInfoSectionTitle'.tr(),
|
||||||
padding: const EdgeInsets.all(16.0),
|
children: [
|
||||||
child: Column(
|
_buildInfoItem(
|
||||||
children: [
|
context,
|
||||||
Text(
|
icon: Symbols.info,
|
||||||
'aboutScreenCopyright'.tr(
|
label: 'aboutScreenPackageNameLabel'.tr(),
|
||||||
args: [DateTime.now().year.toString()],
|
value: _packageInfo.packageName,
|
||||||
),
|
),
|
||||||
style: theme.textTheme.bodySmall,
|
_buildInfoItem(
|
||||||
textAlign: TextAlign.center,
|
context,
|
||||||
),
|
icon: Symbols.update,
|
||||||
const Gap(1),
|
label: 'aboutScreenVersionLabel'.tr(),
|
||||||
Text(
|
value: _packageInfo.version,
|
||||||
'aboutScreenMadeWith'.tr(),
|
),
|
||||||
textAlign: TextAlign.center,
|
_buildInfoItem(
|
||||||
).fontSize(10).opacity(0.8),
|
context,
|
||||||
],
|
icon: Symbols.build,
|
||||||
),
|
label: 'aboutScreenBuildNumberLabel'.tr(),
|
||||||
),
|
value: _packageInfo.buildNumber,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
Gap(MediaQuery.of(context).padding.bottom + 16),
|
if (_deviceInfo != null) const SizedBox(height: 16),
|
||||||
],
|
|
||||||
|
if (_deviceInfo != null)
|
||||||
|
_buildSection(
|
||||||
|
context,
|
||||||
|
title: 'Device Information',
|
||||||
|
children: [
|
||||||
|
_buildInfoItem(
|
||||||
|
context,
|
||||||
|
icon: Symbols.label,
|
||||||
|
label: 'aboutDeviceName'.tr(),
|
||||||
|
value: _deviceInfo?.data['name'],
|
||||||
|
),
|
||||||
|
_buildInfoItem(
|
||||||
|
context,
|
||||||
|
icon: Symbols.fingerprint,
|
||||||
|
label: 'aboutDeviceIdentifier'.tr(),
|
||||||
|
value: _deviceUdid ?? 'N/A',
|
||||||
|
copyable: true,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Links Card
|
||||||
|
_buildSection(
|
||||||
|
context,
|
||||||
|
title: 'aboutScreenLinksSectionTitle'.tr(),
|
||||||
|
children: [
|
||||||
|
_buildListTile(
|
||||||
|
context,
|
||||||
|
icon: Symbols.system_update,
|
||||||
|
title: 'Check for updates',
|
||||||
|
onTap: () async {
|
||||||
|
// Fetch latest release and show the unified sheet
|
||||||
|
final svc = UpdateService();
|
||||||
|
// Reuse service fetch + compare to decide content
|
||||||
|
showLoadingModal(context);
|
||||||
|
final release = await svc.fetchLatestRelease();
|
||||||
|
if (!context.mounted) return;
|
||||||
|
hideLoadingModal(context);
|
||||||
|
if (release != null) {
|
||||||
|
await svc.showUpdateSheet(context, release);
|
||||||
|
} else {
|
||||||
|
showInfoAlert(
|
||||||
|
'Currently cannot get update from the GitHub.',
|
||||||
|
'Unable to check for updates',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
_buildListTile(
|
||||||
|
context,
|
||||||
|
icon: Symbols.privacy_tip,
|
||||||
|
title: 'aboutScreenPrivacyPolicyTitle'.tr(),
|
||||||
|
onTap:
|
||||||
|
() => _launchURL(
|
||||||
|
'https://solsynth.dev/terms/privacy-policy',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildListTile(
|
||||||
|
context,
|
||||||
|
icon: Symbols.description,
|
||||||
|
title: 'aboutScreenTermsOfServiceTitle'.tr(),
|
||||||
|
onTap:
|
||||||
|
() => _launchURL(
|
||||||
|
'https://solsynth.dev/terms/user-agreement',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_buildListTile(
|
||||||
|
context,
|
||||||
|
icon: Symbols.code,
|
||||||
|
title: 'aboutScreenOpenSourceLicensesTitle'.tr(),
|
||||||
|
onTap: () {
|
||||||
|
showLicensePage(
|
||||||
|
context: context,
|
||||||
|
applicationName: _packageInfo.appName,
|
||||||
|
applicationVersion:
|
||||||
|
'Version ${_packageInfo.version}',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
|
||||||
|
// Developer Info
|
||||||
|
_buildSection(
|
||||||
|
context,
|
||||||
|
title: 'aboutScreenDeveloperSectionTitle'.tr(),
|
||||||
|
children: [
|
||||||
|
_buildListTile(
|
||||||
|
context,
|
||||||
|
icon: Symbols.email,
|
||||||
|
title: 'aboutScreenContactUsTitle'.tr(),
|
||||||
|
subtitle: 'lily@solsynth.dev',
|
||||||
|
onTap:
|
||||||
|
() => _launchURL('mailto:lily@solsynth.dev'),
|
||||||
|
),
|
||||||
|
_buildListTile(
|
||||||
|
context,
|
||||||
|
icon: Symbols.copyright,
|
||||||
|
title: 'aboutScreenLicenseTitle'.tr(),
|
||||||
|
subtitle: 'aboutScreenLicenseContent'.tr(
|
||||||
|
args: [DateTime.now().year.toString()],
|
||||||
|
),
|
||||||
|
onTap:
|
||||||
|
() => _launchURL(
|
||||||
|
'https://github.com/Solsynth/Solian/blob/v3/LICENSE.txt',
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (kIsWeb || !(Platform.isMacOS || Platform.isIOS))
|
||||||
|
_buildListTile(
|
||||||
|
context,
|
||||||
|
icon: Symbols.favorite,
|
||||||
|
title: 'donate'.tr(),
|
||||||
|
subtitle: 'donateDescription'.tr(),
|
||||||
|
onTap: () {
|
||||||
|
launchUrlString(
|
||||||
|
'https://afdian.com/@littlesheep',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
|
||||||
|
const SizedBox(height: 32),
|
||||||
|
|
||||||
|
// Copyright
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16.0),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'aboutScreenCopyright'.tr(
|
||||||
|
args: [DateTime.now().year.toString()],
|
||||||
|
),
|
||||||
|
style: theme.textTheme.bodySmall,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
),
|
||||||
|
const Gap(1),
|
||||||
|
Text(
|
||||||
|
'aboutScreenMadeWith'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
).fontSize(10).opacity(0.8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
|
||||||
|
Gap(MediaQuery.of(context).padding.bottom + 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
@@ -1,12 +1,8 @@
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:flutter/services.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/message.dart';
|
|
||||||
import 'package:island/pods/network.dart';
|
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/screens/notification.dart';
|
import 'package:island/screens/notification.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
@@ -15,6 +11,7 @@ import 'package:island/widgets/account/status.dart';
|
|||||||
import 'package:island/widgets/account/leveling_progress.dart';
|
import 'package:island/widgets/account/leveling_progress.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:island/widgets/debug_sheet.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';
|
||||||
|
|
||||||
@@ -276,30 +273,6 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
context.pushNamed('accountSettings');
|
context.pushNamed('accountSettings');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (kDebugMode) const Divider(height: 1).padding(vertical: 8),
|
|
||||||
if (kDebugMode)
|
|
||||||
ListTile(
|
|
||||||
minTileHeight: 48,
|
|
||||||
leading: const Icon(Symbols.copy_all),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
title: Text('Copy access token'),
|
|
||||||
onTap: () async {
|
|
||||||
final tk = ref.watch(tokenProvider);
|
|
||||||
Clipboard.setData(ClipboardData(text: tk!.token));
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (kDebugMode)
|
|
||||||
ListTile(
|
|
||||||
minTileHeight: 48,
|
|
||||||
leading: const Icon(Symbols.delete),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
|
||||||
title: Text('Reset database'),
|
|
||||||
onTap: () async {
|
|
||||||
resetDatabase(ref);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Divider(height: 1).padding(vertical: 8),
|
const Divider(height: 1).padding(vertical: 8),
|
||||||
ListTile(
|
ListTile(
|
||||||
minTileHeight: 48,
|
minTileHeight: 48,
|
||||||
@@ -311,6 +284,19 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
context.pushNamed('about');
|
context.pushNamed('about');
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
minTileHeight: 48,
|
||||||
|
leading: const Icon(Symbols.bug_report),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
title: Text('debugOptions').tr(),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
builder: (context) => DebugSheet(),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
ListTile(
|
ListTile(
|
||||||
minTileHeight: 48,
|
minTileHeight: 48,
|
||||||
leading: const Icon(Symbols.logout),
|
leading: const Icon(Symbols.logout),
|
||||||
|
@@ -3,9 +3,11 @@ import 'package:dropdown_button2/dropdown_button2.dart';
|
|||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
|
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/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
@@ -94,6 +96,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
final usernameController = useTextEditingController(text: user.value!.name);
|
final usernameController = useTextEditingController(text: user.value!.name);
|
||||||
final nicknameController = useTextEditingController(text: user.value!.nick);
|
final nicknameController = useTextEditingController(text: user.value!.nick);
|
||||||
final language = useState(user.value!.language);
|
final language = useState(user.value!.language);
|
||||||
|
final links = useState<List<ProfileLink>>(user.value!.profile.links);
|
||||||
|
|
||||||
void updateBasicInfo() async {
|
void updateBasicInfo() async {
|
||||||
if (!formKeyBasicInfo.currentState!.validate()) return;
|
if (!formKeyBasicInfo.currentState!.validate()) return;
|
||||||
@@ -165,6 +168,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
'location': locationController.text,
|
'location': locationController.text,
|
||||||
'time_zone': timeZoneController.text,
|
'time_zone': timeZoneController.text,
|
||||||
'birthday': birthday.value?.toUtc().toIso8601String(),
|
'birthday': birthday.value?.toUtc().toIso8601String(),
|
||||||
|
'links': links.value,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||||
@@ -558,6 +562,73 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
Text('links').tr().bold().fontSize(18).padding(top: 16),
|
||||||
|
Column(
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
for (var i = 0; i < links.value.length; i++)
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
initialValue: links.value[i].name,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'linkKey'.tr(),
|
||||||
|
isDense: true,
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
links.value[i] = links.value[i].copyWith(
|
||||||
|
name: value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onTapOutside:
|
||||||
|
(_) =>
|
||||||
|
FocusManager.instance.primaryFocus
|
||||||
|
?.unfocus(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
Expanded(
|
||||||
|
child: TextFormField(
|
||||||
|
initialValue: links.value[i].url,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'linkValue'.tr(),
|
||||||
|
isDense: true,
|
||||||
|
),
|
||||||
|
onChanged: (value) {
|
||||||
|
links.value[i] = links.value[i].copyWith(
|
||||||
|
url: value,
|
||||||
|
);
|
||||||
|
},
|
||||||
|
onTapOutside:
|
||||||
|
(_) =>
|
||||||
|
FocusManager.instance.primaryFocus
|
||||||
|
?.unfocus(),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.delete),
|
||||||
|
onPressed: () {
|
||||||
|
links.value = List.from(links.value)
|
||||||
|
..removeAt(i);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Align(
|
||||||
|
alignment: Alignment.centerRight,
|
||||||
|
child: FilledButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
links.value = List.from(links.value)
|
||||||
|
..add(ProfileLink(name: '', url: ''));
|
||||||
|
},
|
||||||
|
label: Text('addLink').tr(),
|
||||||
|
icon: const Icon(Symbols.add),
|
||||||
|
).padding(top: 8),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
Align(
|
Align(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
child: TextButton.icon(
|
child: TextButton.icon(
|
||||||
|
@@ -1,5 +1,6 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
@@ -13,6 +14,7 @@ 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/responsive.dart';
|
||||||
|
import 'package:island/services/text.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';
|
||||||
@@ -30,6 +32,7 @@ import 'package:palette_generator/palette_generator.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:share_plus/share_plus.dart';
|
import 'package:share_plus/share_plus.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
part 'profile.g.dart';
|
part 'profile.g.dart';
|
||||||
|
|
||||||
@@ -194,6 +197,15 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
List<Widget> buildSubcolumn(SnAccount data) {
|
List<Widget> buildSubcolumn(SnAccount data) {
|
||||||
return [
|
return [
|
||||||
|
Row(
|
||||||
|
spacing: 6,
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.join, size: 17, fill: 1),
|
||||||
|
Text(
|
||||||
|
'joinedAt'.tr(args: [data.createdAt.formatCustom('yyyy-MM-dd')]),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
if (data.profile.birthday != null)
|
if (data.profile.birthday != null)
|
||||||
Row(
|
Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
@@ -320,7 +332,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
spacing: 2,
|
spacing: 2,
|
||||||
children: buildSubcolumn(data),
|
children: buildSubcolumn(data),
|
||||||
),
|
),
|
||||||
if (data.profile.timeZone.isNotEmpty)
|
if (data.profile.timeZone.isNotEmpty && !kIsWeb)
|
||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -350,6 +362,32 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
).padding(horizontal: 24, vertical: 16),
|
).padding(horizontal: 24, vertical: 16),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Widget accountProfileLinks(SnAccount data) => Card(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('links').tr().bold().padding(horizontal: 24, top: 12, bottom: 4),
|
||||||
|
for (final link in data.profile.links)
|
||||||
|
ListTile(
|
||||||
|
title: Text(link.name.capitalizeEachWord()),
|
||||||
|
subtitle: Text(link.url),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: const BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
onTap: () {
|
||||||
|
if (!link.url.startsWith('http') && !link.url.contains('://')) {
|
||||||
|
launchUrlString('https://${link.url}');
|
||||||
|
} else {
|
||||||
|
launchUrlString(link.url);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
Widget accountAction(SnAccount data) => Card(
|
Widget accountAction(SnAccount data) => Card(
|
||||||
child: Column(
|
child: Column(
|
||||||
children: [
|
children: [
|
||||||
@@ -452,7 +490,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(horizontal: 16, vertical: 8),
|
).padding(horizontal: 16, vertical: 12),
|
||||||
);
|
);
|
||||||
|
|
||||||
return account.when(
|
return account.when(
|
||||||
@@ -509,9 +547,11 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
SliverToBoxAdapter(child: accountBasicInfo(data)),
|
SliverToBoxAdapter(child: accountBasicInfo(data)),
|
||||||
if (data.badges.isNotEmpty)
|
if (data.badges.isNotEmpty)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: BadgeList(
|
child: Card(
|
||||||
badges: data.badges,
|
child: BadgeList(
|
||||||
).padding(horizontal: 24, bottom: 24),
|
badges: data.badges,
|
||||||
|
).padding(horizontal: 26, vertical: 20),
|
||||||
|
).padding(left: 2, right: 4),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -521,9 +561,10 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
level: data.profile.level,
|
level: data.profile.level,
|
||||||
experience: data.profile.experience,
|
experience: data.profile.experience,
|
||||||
progress: data.profile.levelingProgress,
|
progress: data.profile.levelingProgress,
|
||||||
),
|
).padding(left: 2, right: 4),
|
||||||
if (data.profile.verification != null)
|
if (data.profile.verification != null)
|
||||||
Card(
|
Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
child: VerificationStatusCard(
|
child: VerificationStatusCard(
|
||||||
mark: data.profile.verification!,
|
mark: data.profile.verification!,
|
||||||
),
|
),
|
||||||
@@ -534,6 +575,10 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: accountProfileBio(data).padding(top: 4),
|
child: accountProfileBio(data).padding(top: 4),
|
||||||
),
|
),
|
||||||
|
if (data.profile.links.isNotEmpty)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: accountProfileLinks(data),
|
||||||
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: accountProfileDetail(data),
|
child: accountProfileDetail(data),
|
||||||
),
|
),
|
||||||
@@ -604,9 +649,11 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
SliverToBoxAdapter(child: accountBasicInfo(data)),
|
SliverToBoxAdapter(child: accountBasicInfo(data)),
|
||||||
if (data.badges.isNotEmpty)
|
if (data.badges.isNotEmpty)
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: BadgeList(
|
child: Card(
|
||||||
badges: data.badges,
|
child: BadgeList(
|
||||||
).padding(horizontal: 24, bottom: 24),
|
badges: data.badges,
|
||||||
|
).padding(horizontal: 26, vertical: 20),
|
||||||
|
).padding(horizontal: 4),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -628,6 +675,12 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: accountProfileBio(data).padding(horizontal: 4),
|
child: accountProfileBio(data).padding(horizontal: 4),
|
||||||
),
|
),
|
||||||
|
if (data.profile.links.isNotEmpty)
|
||||||
|
SliverToBoxAdapter(
|
||||||
|
child: accountProfileLinks(
|
||||||
|
data,
|
||||||
|
).padding(horizontal: 4),
|
||||||
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: accountProfileDetail(
|
child: accountProfileDetail(
|
||||||
data,
|
data,
|
||||||
|
@@ -339,7 +339,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
await apiClient.post(
|
await apiClient.post(
|
||||||
'/chat/${chatRoom.value!.id}/members/me',
|
'/sphere/chat/${chatRoom.value!.id}/members/me',
|
||||||
);
|
);
|
||||||
ref.invalidate(chatroomIdentityProvider(id));
|
ref.invalidate(chatroomIdentityProvider(id));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -929,7 +929,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
if (attachment.isOnCloud) {
|
if (attachment.isOnCloud) {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
await client.delete(
|
await client.delete(
|
||||||
'/files/${attachment.data.id}',
|
'/drive/files/${attachment.data.id}',
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
final clone = List.of(attachments.value);
|
final clone = List.of(attachments.value);
|
||||||
|
@@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/poll.dart';
|
import 'package:island/models/poll.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/poll/poll_feedback.dart';
|
import 'package:island/widgets/poll/poll_feedback.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
@@ -70,7 +71,7 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return Scaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('Polls')),
|
appBar: AppBar(title: const Text('Polls')),
|
||||||
floatingActionButton: FloatingActionButton(
|
floatingActionButton: FloatingActionButton(
|
||||||
onPressed: () => _createPoll(context),
|
onPressed: () => _createPoll(context),
|
||||||
|
@@ -58,7 +58,7 @@ class StickerPackDetailScreen extends HookConsumerWidget {
|
|||||||
try {
|
try {
|
||||||
showLoadingModal(context);
|
showLoadingModal(context);
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
await apiClient.delete('/stickers/$id/content/${sticker.id}');
|
await apiClient.delete('/sphere/stickers/$id/content/${sticker.id}');
|
||||||
ref.invalidate(stickerPackContentProvider(id));
|
ref.invalidate(stickerPackContentProvider(id));
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
@@ -297,7 +297,7 @@ class _StickerPackActionMenu extends HookConsumerWidget {
|
|||||||
).then((confirm) {
|
).then((confirm) {
|
||||||
if (confirm) {
|
if (confirm) {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
client.delete('/stickers/$packId');
|
client.delete('/sphere/stickers/$packId');
|
||||||
ref.invalidate(stickerPacksNotifierProvider);
|
ref.invalidate(stickerPacksNotifierProvider);
|
||||||
if (context.mounted) context.pop(true);
|
if (context.mounted) context.pop(true);
|
||||||
}
|
}
|
||||||
@@ -325,7 +325,7 @@ Future<SnSticker?> stickerPackSticker(
|
|||||||
if (query == null) return null;
|
if (query == null) return null;
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
final resp = await apiClient.get(
|
final resp = await apiClient.get(
|
||||||
'/stickers/${query.packId}/content/${query.id}',
|
'/sphere/stickers/${query.packId}/content/${query.id}',
|
||||||
);
|
);
|
||||||
if (resp.data == null) return null;
|
if (resp.data == null) return null;
|
||||||
return SnSticker.fromJson(resp.data);
|
return SnSticker.fromJson(resp.data);
|
||||||
@@ -379,8 +379,8 @@ class EditStickersScreen extends HookConsumerWidget {
|
|||||||
try {
|
try {
|
||||||
final resp = await apiClient.request(
|
final resp = await apiClient.request(
|
||||||
id == null
|
id == null
|
||||||
? '/stickers/$packId/content'
|
? '/sphere/stickers/$packId/content'
|
||||||
: '/stickers/$packId/content/$id',
|
: '/sphere/stickers/$packId/content/$id',
|
||||||
data: {'slug': slugController.text, 'image_id': imageController.text},
|
data: {'slug': slugController.text, 'image_id': imageController.text},
|
||||||
options: Options(method: id == null ? 'POST' : 'PATCH'),
|
options: Options(method: id == null ? 'POST' : 'PATCH'),
|
||||||
);
|
);
|
||||||
|
@@ -151,7 +151,7 @@ class _StickerPackContentProviderElement
|
|||||||
}
|
}
|
||||||
|
|
||||||
String _$stickerPackStickerHash() =>
|
String _$stickerPackStickerHash() =>
|
||||||
r'36f524c047e632236d5597aaaa8678ed86599602';
|
r'5c553666b3a63530bdebae4b7cd52f303c5ab3a0';
|
||||||
|
|
||||||
/// See also [stickerPackSticker].
|
/// See also [stickerPackSticker].
|
||||||
@ProviderFor(stickerPackSticker)
|
@ProviderFor(stickerPackSticker)
|
||||||
|
@@ -114,10 +114,11 @@ class WebFeedEditScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
return feedAsync.when(
|
return feedAsync.when(
|
||||||
loading:
|
loading:
|
||||||
() =>
|
() => const AppScaffold(
|
||||||
const Scaffold(body: Center(child: CircularProgressIndicator())),
|
body: Center(child: CircularProgressIndicator()),
|
||||||
|
),
|
||||||
error:
|
error:
|
||||||
(error, stack) => Scaffold(
|
(error, stack) => AppScaffold(
|
||||||
appBar: AppBar(title: const Text('Error')),
|
appBar: AppBar(title: const Text('Error')),
|
||||||
body: Center(child: Text('Error: $error')),
|
body: Center(child: Text('Error: $error')),
|
||||||
),
|
),
|
||||||
|
@@ -30,12 +30,12 @@ Future<DeveloperStats?> developerStats(Ref ref, String? uname) async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<List<SnPublisher>> developers(Ref ref) async {
|
Future<List<SnDeveloper>> developers(Ref ref) async {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
final resp = await client.get('/develop/developers');
|
final resp = await client.get('/develop/developers');
|
||||||
return resp.data
|
return resp.data
|
||||||
.map((e) => SnPublisher.fromJson(e))
|
.map((e) => SnDeveloper.fromJson(e))
|
||||||
.cast<SnPublisher>()
|
.cast<SnDeveloper>()
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -74,25 +74,25 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
final developers = ref.watch(developersProvider);
|
final developers = ref.watch(developersProvider);
|
||||||
final currentDeveloper = useState<SnPublisher?>(
|
final currentDeveloper = useState<SnDeveloper?>(
|
||||||
developers.value?.firstOrNull,
|
developers.value?.firstOrNull,
|
||||||
);
|
);
|
||||||
|
|
||||||
final List<DropdownMenuItem<SnPublisher>> developersMenu = developers.when(
|
final List<DropdownMenuItem<SnDeveloper>> developersMenu = developers.when(
|
||||||
data:
|
data:
|
||||||
(data) =>
|
(data) =>
|
||||||
data
|
data
|
||||||
.map(
|
.map(
|
||||||
(item) => DropdownMenuItem<SnPublisher>(
|
(item) => DropdownMenuItem<SnDeveloper>(
|
||||||
value: item,
|
value: item,
|
||||||
child: ListTile(
|
child: ListTile(
|
||||||
minTileHeight: 48,
|
minTileHeight: 48,
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
radius: 16,
|
radius: 16,
|
||||||
fileId: item.picture?.id,
|
fileId: item.publisher?.picture?.id,
|
||||||
),
|
),
|
||||||
title: Text(item.nick),
|
title: Text(item.publisher!.nick),
|
||||||
subtitle: Text('@${item.name}'),
|
subtitle: Text('@${item.publisher!.name}'),
|
||||||
trailing:
|
trailing:
|
||||||
currentDeveloper.value?.id == item.id
|
currentDeveloper.value?.id == item.id
|
||||||
? const Icon(Icons.check)
|
? const Icon(Icons.check)
|
||||||
@@ -107,7 +107,7 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final developerStats = ref.watch(
|
final developerStats = ref.watch(
|
||||||
developerStatsProvider(currentDeveloper.value?.name),
|
developerStatsProvider(currentDeveloper.value?.publisher?.name),
|
||||||
);
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
@@ -117,7 +117,7 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
title: Text('developerHub').tr(),
|
title: Text('developerHub').tr(),
|
||||||
actions: [
|
actions: [
|
||||||
DropdownButtonHideUnderline(
|
DropdownButtonHideUnderline(
|
||||||
child: DropdownButton2<SnPublisher>(
|
child: DropdownButton2<SnDeveloper>(
|
||||||
alignment: Alignment.centerRight,
|
alignment: Alignment.centerRight,
|
||||||
value: currentDeveloper.value,
|
value: currentDeveloper.value,
|
||||||
hint: CircleAvatar(
|
hint: CircleAvatar(
|
||||||
@@ -139,7 +139,7 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
...developersMenu.map(
|
...developersMenu.map(
|
||||||
(e) => ProfilePictureWidget(
|
(e) => ProfilePictureWidget(
|
||||||
radius: 16,
|
radius: 16,
|
||||||
fileId: e.value?.picture?.id,
|
fileId: e.value?.publisher?.picture?.id,
|
||||||
).center().padding(right: 8),
|
).center().padding(right: 8),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -193,10 +193,12 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
...(developers.value?.map(
|
...(developers.value?.map(
|
||||||
(developer) => ListTile(
|
(developer) => ListTile(
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
file: developer.picture,
|
file: developer.publisher?.picture,
|
||||||
|
),
|
||||||
|
title: Text(developer.publisher!.nick),
|
||||||
|
subtitle: Text(
|
||||||
|
'@${developer.publisher!.name}',
|
||||||
),
|
),
|
||||||
title: Text(developer.nick),
|
|
||||||
subtitle: Text('@${developer.name}'),
|
|
||||||
onTap: () {
|
onTap: () {
|
||||||
currentDeveloper.value = developer;
|
currentDeveloper.value = developer;
|
||||||
},
|
},
|
||||||
@@ -243,7 +245,8 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
context.pushNamed(
|
context.pushNamed(
|
||||||
'developerApps',
|
'developerApps',
|
||||||
pathParameters: {
|
pathParameters: {
|
||||||
'name': currentDeveloper.value!.name,
|
'name':
|
||||||
|
currentDeveloper.value!.publisher!.name,
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
@@ -257,7 +260,9 @@ class DeveloperHubScreen extends HookConsumerWidget {
|
|||||||
error: err,
|
error: err,
|
||||||
onRetry: () {
|
onRetry: () {
|
||||||
ref.invalidate(
|
ref.invalidate(
|
||||||
developerStatsProvider(currentDeveloper.value?.name),
|
developerStatsProvider(
|
||||||
|
currentDeveloper.value?.publisher!.name,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -354,7 +359,7 @@ class _DeveloperEnrollmentSheet extends HookConsumerWidget {
|
|||||||
? Center(
|
? Center(
|
||||||
child:
|
child:
|
||||||
Text(
|
Text(
|
||||||
'noPublishersToEnroll',
|
'noDevelopersToEnroll',
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
).tr(),
|
).tr(),
|
||||||
)
|
)
|
||||||
|
@@ -149,12 +149,12 @@ class _DeveloperStatsProviderElement
|
|||||||
String? get uname => (origin as DeveloperStatsProvider).uname;
|
String? get uname => (origin as DeveloperStatsProvider).uname;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$developersHash() => r'04f25db31f511f651a5add128d56631236ed0b39';
|
String _$developersHash() => r'252341098617ac398ce133994453f318dd3edbd2';
|
||||||
|
|
||||||
/// See also [developers].
|
/// See also [developers].
|
||||||
@ProviderFor(developers)
|
@ProviderFor(developers)
|
||||||
final developersProvider =
|
final developersProvider =
|
||||||
AutoDisposeFutureProvider<List<SnPublisher>>.internal(
|
AutoDisposeFutureProvider<List<SnDeveloper>>.internal(
|
||||||
developers,
|
developers,
|
||||||
name: r'developersProvider',
|
name: r'developersProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
@@ -167,6 +167,6 @@ final developersProvider =
|
|||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
typedef DevelopersRef = AutoDisposeFutureProviderRef<List<SnPublisher>>;
|
typedef DevelopersRef = AutoDisposeFutureProviderRef<List<SnDeveloper>>;
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
@@ -9,6 +9,7 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/models/poll.dart';
|
import 'package:island/models/poll.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
|
|
||||||
class PollEditorState {
|
class PollEditorState {
|
||||||
@@ -413,7 +414,7 @@ class PollEditorScreen extends ConsumerWidget {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return Scaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: Text(model.id == null ? 'Create Poll' : 'Edit Poll'),
|
title: Text(model.id == null ? 'Create Poll' : 'Edit Poll'),
|
||||||
actions: [
|
actions: [
|
||||||
@@ -428,175 +429,175 @@ class PollEditorScreen extends ConsumerWidget {
|
|||||||
const Gap(8),
|
const Gap(8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: SafeArea(
|
body: Column(
|
||||||
child: Form(
|
children: [
|
||||||
key: ValueKey(model.id),
|
Expanded(
|
||||||
child: ListView(
|
child: Form(
|
||||||
padding: const EdgeInsets.all(16),
|
key: ValueKey(model.id),
|
||||||
children: [
|
child: ListView(
|
||||||
TextFormField(
|
padding: const EdgeInsets.all(16),
|
||||||
initialValue: model.title ?? '',
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Title',
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
textInputAction: TextInputAction.next,
|
|
||||||
maxLength: 256,
|
|
||||||
onChanged: notifier.setTitle,
|
|
||||||
onTapOutside:
|
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
validator: (v) {
|
|
||||||
if (v == null || v.trim().isEmpty) {
|
|
||||||
return 'Title is required';
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Gap(12),
|
|
||||||
TextFormField(
|
|
||||||
initialValue: model.description ?? '',
|
|
||||||
decoration: const InputDecoration(
|
|
||||||
labelText: 'Description',
|
|
||||||
alignLabelWithHint: true,
|
|
||||||
border: OutlineInputBorder(
|
|
||||||
borderRadius: BorderRadius.all(Radius.circular(16)),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
maxLines: 3,
|
|
||||||
maxLength: 4096,
|
|
||||||
onChanged: notifier.setDescription,
|
|
||||||
onTapOutside:
|
|
||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
|
||||||
),
|
|
||||||
const Gap(12),
|
|
||||||
_EndDatePicker(
|
|
||||||
value: model.endedAt,
|
|
||||||
onChanged: notifier.setEndedAt,
|
|
||||||
),
|
|
||||||
const Gap(24),
|
|
||||||
Row(
|
|
||||||
children: [
|
children: [
|
||||||
Text(
|
TextFormField(
|
||||||
'Questions',
|
initialValue: model.title ?? '',
|
||||||
style: Theme.of(context).textTheme.titleLarge,
|
decoration: const InputDecoration(
|
||||||
),
|
labelText: 'Title',
|
||||||
const Spacer(),
|
border: OutlineInputBorder(
|
||||||
MenuAnchor(
|
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||||
builder: (context, controller, child) {
|
),
|
||||||
return FilledButton.icon(
|
),
|
||||||
onPressed: () {
|
textInputAction: TextInputAction.next,
|
||||||
controller.isOpen
|
maxLength: 256,
|
||||||
? controller.close()
|
onChanged: notifier.setTitle,
|
||||||
: controller.open();
|
onTapOutside:
|
||||||
},
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
icon: const Icon(Icons.add),
|
validator: (v) {
|
||||||
label: const Text('Add question'),
|
if (v == null || v.trim().isEmpty) {
|
||||||
);
|
return 'Title is required';
|
||||||
|
}
|
||||||
|
return null;
|
||||||
},
|
},
|
||||||
menuChildren:
|
|
||||||
SnPollQuestionType.values
|
|
||||||
.map(
|
|
||||||
(t) => MenuItemButton(
|
|
||||||
leadingIcon: Icon(_iconForType(t)),
|
|
||||||
onPressed: () => notifier.addQuestion(t),
|
|
||||||
child: Text(_labelForType(t)),
|
|
||||||
),
|
|
||||||
)
|
|
||||||
.toList(),
|
|
||||||
),
|
),
|
||||||
|
const Gap(12),
|
||||||
|
TextFormField(
|
||||||
|
initialValue: model.description ?? '',
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
labelText: 'Description',
|
||||||
|
alignLabelWithHint: true,
|
||||||
|
border: OutlineInputBorder(
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(16)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
maxLines: 3,
|
||||||
|
maxLength: 4096,
|
||||||
|
onChanged: notifier.setDescription,
|
||||||
|
onTapOutside:
|
||||||
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
),
|
||||||
|
const Gap(12),
|
||||||
|
_EndDatePicker(
|
||||||
|
value: model.endedAt,
|
||||||
|
onChanged: notifier.setEndedAt,
|
||||||
|
),
|
||||||
|
const Gap(24),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'Questions',
|
||||||
|
style: Theme.of(context).textTheme.titleLarge,
|
||||||
|
),
|
||||||
|
const Spacer(),
|
||||||
|
MenuAnchor(
|
||||||
|
builder: (context, controller, child) {
|
||||||
|
return FilledButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
controller.isOpen
|
||||||
|
? controller.close()
|
||||||
|
: controller.open();
|
||||||
|
},
|
||||||
|
icon: const Icon(Icons.add),
|
||||||
|
label: const Text('Add question'),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
menuChildren:
|
||||||
|
SnPollQuestionType.values
|
||||||
|
.map(
|
||||||
|
(t) => MenuItemButton(
|
||||||
|
leadingIcon: Icon(_iconForType(t)),
|
||||||
|
onPressed: () => notifier.addQuestion(t),
|
||||||
|
child: Text(_labelForType(t)),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
if (model.questions.isEmpty)
|
||||||
|
_EmptyState(
|
||||||
|
title: 'No questions yet',
|
||||||
|
subtitle:
|
||||||
|
'Use "Add question" to start building your poll.',
|
||||||
|
)
|
||||||
|
else
|
||||||
|
ReorderableListView.builder(
|
||||||
|
shrinkWrap: true,
|
||||||
|
physics: const NeverScrollableScrollPhysics(),
|
||||||
|
itemCount: model.questions.length,
|
||||||
|
onReorder: (oldIndex, newIndex) {
|
||||||
|
// Convert to stepwise moves using provided functions
|
||||||
|
if (newIndex > oldIndex) newIndex -= 1;
|
||||||
|
final steps = newIndex - oldIndex;
|
||||||
|
if (steps == 0) return;
|
||||||
|
if (steps > 0) {
|
||||||
|
for (int i = 0; i < steps; i++) {
|
||||||
|
notifier.moveQuestionDown(oldIndex + i);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for (int i = 0; i > steps; i--) {
|
||||||
|
notifier.moveQuestionUp(oldIndex + i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
buildDefaultDragHandles: false,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final q = model.questions[index];
|
||||||
|
return Card(
|
||||||
|
key: ValueKey('q_$index'),
|
||||||
|
margin: const EdgeInsets.symmetric(vertical: 8),
|
||||||
|
clipBehavior: Clip.antiAlias,
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
_QuestionHeader(
|
||||||
|
index: index,
|
||||||
|
question: q,
|
||||||
|
onMoveUp:
|
||||||
|
index > 0
|
||||||
|
? () => notifier.moveQuestionUp(index)
|
||||||
|
: null,
|
||||||
|
onMoveDown:
|
||||||
|
index < model.questions.length - 1
|
||||||
|
? () => notifier.moveQuestionDown(index)
|
||||||
|
: null,
|
||||||
|
onDelete: () => notifier.removeQuestion(index),
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(16),
|
||||||
|
child: _QuestionEditor(
|
||||||
|
index: index,
|
||||||
|
question: q,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Gap(96),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
const Gap(8),
|
),
|
||||||
if (model.questions.isEmpty)
|
),
|
||||||
_EmptyState(
|
Row(
|
||||||
title: 'No questions yet',
|
children: [
|
||||||
subtitle: 'Use "Add question" to start building your poll.',
|
OutlinedButton.icon(
|
||||||
)
|
onPressed: () {
|
||||||
else
|
Navigator.of(context).maybePop();
|
||||||
ReorderableListView.builder(
|
},
|
||||||
shrinkWrap: true,
|
icon: const Icon(Icons.close),
|
||||||
physics: const NeverScrollableScrollPhysics(),
|
label: const Text('Cancel'),
|
||||||
itemCount: model.questions.length,
|
),
|
||||||
onReorder: (oldIndex, newIndex) {
|
const Spacer(),
|
||||||
// Convert to stepwise moves using provided functions
|
FilledButton.icon(
|
||||||
if (newIndex > oldIndex) newIndex -= 1;
|
onPressed: () {
|
||||||
final steps = newIndex - oldIndex;
|
_submitPoll(context, ref);
|
||||||
if (steps == 0) return;
|
},
|
||||||
if (steps > 0) {
|
icon: const Icon(Icons.cloud_upload_outlined),
|
||||||
for (int i = 0; i < steps; i++) {
|
label: Text(model.id == null ? 'Create' : 'Update'),
|
||||||
notifier.moveQuestionDown(oldIndex + i);
|
),
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for (int i = 0; i > steps; i--) {
|
|
||||||
notifier.moveQuestionUp(oldIndex + i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
buildDefaultDragHandles: false,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final q = model.questions[index];
|
|
||||||
return Card(
|
|
||||||
key: ValueKey('q_$index'),
|
|
||||||
margin: const EdgeInsets.symmetric(vertical: 8),
|
|
||||||
clipBehavior: Clip.antiAlias,
|
|
||||||
child: Column(
|
|
||||||
children: [
|
|
||||||
_QuestionHeader(
|
|
||||||
index: index,
|
|
||||||
question: q,
|
|
||||||
onMoveUp:
|
|
||||||
index > 0
|
|
||||||
? () => notifier.moveQuestionUp(index)
|
|
||||||
: null,
|
|
||||||
onMoveDown:
|
|
||||||
index < model.questions.length - 1
|
|
||||||
? () => notifier.moveQuestionDown(index)
|
|
||||||
: null,
|
|
||||||
onDelete: () => notifier.removeQuestion(index),
|
|
||||||
),
|
|
||||||
const Divider(height: 1),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(16),
|
|
||||||
child: _QuestionEditor(index: index, question: q),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
const Gap(96),
|
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
),
|
],
|
||||||
),
|
|
||||||
bottomNavigationBar: Padding(
|
|
||||||
padding: EdgeInsets.fromLTRB(
|
|
||||||
16,
|
|
||||||
8,
|
|
||||||
16,
|
|
||||||
16 + MediaQuery.of(context).padding.bottom,
|
|
||||||
),
|
|
||||||
child: Row(
|
|
||||||
children: [
|
|
||||||
OutlinedButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
Navigator.of(context).maybePop();
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.close),
|
|
||||||
label: const Text('Cancel'),
|
|
||||||
),
|
|
||||||
const Spacer(),
|
|
||||||
FilledButton.icon(
|
|
||||||
onPressed: () {
|
|
||||||
_submitPoll(context, ref);
|
|
||||||
},
|
|
||||||
icon: const Icon(Icons.cloud_upload_outlined),
|
|
||||||
label: Text(model.id == null ? 'Create' : 'Update'),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
107
lib/screens/posts/post_category_detail.dart
Normal file
107
lib/screens/posts/post_category_detail.dart
Normal file
@@ -0,0 +1,107 @@
|
|||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:gap/gap.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/models/post_category.dart';
|
||||||
|
import 'package:island/models/post_tag.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
|
import 'package:island/widgets/response.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
part 'post_category_detail.g.dart';
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<SnPostCategory> postCategory(Ref ref, String slug) async {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
final resp = await apiClient.get('/sphere/posts/categories/$slug');
|
||||||
|
return SnPostCategory.fromJson(resp.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<SnPostTag> postTag(Ref ref, String slug) async {
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
final resp = await apiClient.get('/sphere/posts/tags/$slug');
|
||||||
|
return SnPostTag.fromJson(resp.data);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PostCategoryDetailScreen extends HookConsumerWidget {
|
||||||
|
final String slug;
|
||||||
|
final bool isCategory;
|
||||||
|
const PostCategoryDetailScreen({
|
||||||
|
super.key,
|
||||||
|
required this.slug,
|
||||||
|
required this.isCategory,
|
||||||
|
});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final postCategory =
|
||||||
|
isCategory ? ref.watch(postCategoryProvider(slug)) : null;
|
||||||
|
final postTag = isCategory ? null : ref.watch(postTagProvider(slug));
|
||||||
|
|
||||||
|
final postFilterTitle =
|
||||||
|
isCategory
|
||||||
|
? postCategory?.value?.categoryDisplayTitle ?? 'loading'
|
||||||
|
: postTag?.value?.name ?? postTag?.value?.slug ?? 'loading';
|
||||||
|
|
||||||
|
return AppScaffold(
|
||||||
|
isNoBackground: false,
|
||||||
|
appBar: AppBar(title: Text(postFilterTitle).tr()),
|
||||||
|
body: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
if (isCategory)
|
||||||
|
postCategory!.when(
|
||||||
|
data:
|
||||||
|
(category) => Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(category.categoryDisplayTitle).bold().fontSize(15),
|
||||||
|
Text('A category'),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24, vertical: 16),
|
||||||
|
error:
|
||||||
|
(error, _) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => ref.invalidate(postCategoryProvider(slug)),
|
||||||
|
),
|
||||||
|
loading: () => ResponseLoadingWidget(),
|
||||||
|
)
|
||||||
|
else
|
||||||
|
postTag!.when(
|
||||||
|
data:
|
||||||
|
(tag) => Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(tag.name ?? '#${tag.slug}').bold().fontSize(15),
|
||||||
|
Text('A tag'),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 24, vertical: 16),
|
||||||
|
error:
|
||||||
|
(error, _) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () => ref.invalidate(postTagProvider(slug)),
|
||||||
|
),
|
||||||
|
loading: () => ResponseLoadingWidget(),
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
Expanded(
|
||||||
|
child: CustomScrollView(
|
||||||
|
slivers: [
|
||||||
|
const SliverGap(4),
|
||||||
|
SliverPostList(
|
||||||
|
categories: isCategory ? [slug] : null,
|
||||||
|
tags: isCategory ? null : [slug],
|
||||||
|
),
|
||||||
|
SliverGap(MediaQuery.of(context).padding.bottom + 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
270
lib/screens/posts/post_category_detail.g.dart
Normal file
270
lib/screens/posts/post_category_detail.g.dart
Normal file
@@ -0,0 +1,270 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'post_category_detail.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$postCategoryHash() => r'0df2de729ba96819ee37377314615abef0c99547';
|
||||||
|
|
||||||
|
/// 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 [postCategory].
|
||||||
|
@ProviderFor(postCategory)
|
||||||
|
const postCategoryProvider = PostCategoryFamily();
|
||||||
|
|
||||||
|
/// See also [postCategory].
|
||||||
|
class PostCategoryFamily extends Family<AsyncValue<SnPostCategory>> {
|
||||||
|
/// See also [postCategory].
|
||||||
|
const PostCategoryFamily();
|
||||||
|
|
||||||
|
/// See also [postCategory].
|
||||||
|
PostCategoryProvider call(String slug) {
|
||||||
|
return PostCategoryProvider(slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PostCategoryProvider getProviderOverride(
|
||||||
|
covariant PostCategoryProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'postCategoryProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [postCategory].
|
||||||
|
class PostCategoryProvider extends AutoDisposeFutureProvider<SnPostCategory> {
|
||||||
|
/// See also [postCategory].
|
||||||
|
PostCategoryProvider(String slug)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => postCategory(ref as PostCategoryRef, slug),
|
||||||
|
from: postCategoryProvider,
|
||||||
|
name: r'postCategoryProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$postCategoryHash,
|
||||||
|
dependencies: PostCategoryFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
PostCategoryFamily._allTransitiveDependencies,
|
||||||
|
slug: slug,
|
||||||
|
);
|
||||||
|
|
||||||
|
PostCategoryProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.slug,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String slug;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<SnPostCategory> Function(PostCategoryRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: PostCategoryProvider._internal(
|
||||||
|
(ref) => create(ref as PostCategoryRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
slug: slug,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<SnPostCategory> createElement() {
|
||||||
|
return _PostCategoryProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is PostCategoryProvider && other.slug == slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, slug.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin PostCategoryRef on AutoDisposeFutureProviderRef<SnPostCategory> {
|
||||||
|
/// The parameter `slug` of this provider.
|
||||||
|
String get slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostCategoryProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<SnPostCategory>
|
||||||
|
with PostCategoryRef {
|
||||||
|
_PostCategoryProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get slug => (origin as PostCategoryProvider).slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
String _$postTagHash() => r'e050fdf9af81a843a9abd9cf979dd2672e0a2b93';
|
||||||
|
|
||||||
|
/// See also [postTag].
|
||||||
|
@ProviderFor(postTag)
|
||||||
|
const postTagProvider = PostTagFamily();
|
||||||
|
|
||||||
|
/// See also [postTag].
|
||||||
|
class PostTagFamily extends Family<AsyncValue<SnPostTag>> {
|
||||||
|
/// See also [postTag].
|
||||||
|
const PostTagFamily();
|
||||||
|
|
||||||
|
/// See also [postTag].
|
||||||
|
PostTagProvider call(String slug) {
|
||||||
|
return PostTagProvider(slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PostTagProvider getProviderOverride(covariant PostTagProvider provider) {
|
||||||
|
return call(provider.slug);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'postTagProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [postTag].
|
||||||
|
class PostTagProvider extends AutoDisposeFutureProvider<SnPostTag> {
|
||||||
|
/// See also [postTag].
|
||||||
|
PostTagProvider(String slug)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => postTag(ref as PostTagRef, slug),
|
||||||
|
from: postTagProvider,
|
||||||
|
name: r'postTagProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$postTagHash,
|
||||||
|
dependencies: PostTagFamily._dependencies,
|
||||||
|
allTransitiveDependencies: PostTagFamily._allTransitiveDependencies,
|
||||||
|
slug: slug,
|
||||||
|
);
|
||||||
|
|
||||||
|
PostTagProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.slug,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String slug;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<SnPostTag> Function(PostTagRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: PostTagProvider._internal(
|
||||||
|
(ref) => create(ref as PostTagRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
slug: slug,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<SnPostTag> createElement() {
|
||||||
|
return _PostTagProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is PostTagProvider && other.slug == slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, slug.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin PostTagRef on AutoDisposeFutureProviderRef<SnPostTag> {
|
||||||
|
/// The parameter `slug` of this provider.
|
||||||
|
String get slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PostTagProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<SnPostTag>
|
||||||
|
with PostTagRef {
|
||||||
|
_PostTagProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get slug => (origin as PostTagProvider).slug;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
@@ -92,6 +92,7 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
right: 0,
|
right: 0,
|
||||||
child: Material(
|
child: Material(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||||
child: postState
|
child: postState
|
||||||
.when(
|
.when(
|
||||||
data:
|
data:
|
||||||
@@ -107,8 +108,8 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
error: (_, _) => const SizedBox.shrink(),
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
)
|
)
|
||||||
.padding(
|
.padding(
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 16,
|
bottom: MediaQuery.of(context).padding.bottom + 8,
|
||||||
top: 16,
|
top: 8,
|
||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -99,7 +99,10 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
subscribing.value = true;
|
subscribing.value = true;
|
||||||
try {
|
try {
|
||||||
await apiClient.post("/publishers/$name/subscribe", data: {'tier': 0});
|
await apiClient.post(
|
||||||
|
"/sphere/publishers/$name/subscribe",
|
||||||
|
data: {'tier': 0},
|
||||||
|
);
|
||||||
ref.invalidate(publisherSubscriptionStatusProvider(name));
|
ref.invalidate(publisherSubscriptionStatusProvider(name));
|
||||||
HapticFeedback.heavyImpact();
|
HapticFeedback.heavyImpact();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
@@ -113,7 +116,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
subscribing.value = true;
|
subscribing.value = true;
|
||||||
try {
|
try {
|
||||||
await apiClient.post("/publishers/$name/unsubscribe");
|
await apiClient.post("/sphere/publishers/$name/unsubscribe");
|
||||||
ref.invalidate(publisherSubscriptionStatusProvider(name));
|
ref.invalidate(publisherSubscriptionStatusProvider(name));
|
||||||
HapticFeedback.heavyImpact();
|
HapticFeedback.heavyImpact();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
@@ -1,19 +1,28 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
|
import 'dart:developer';
|
||||||
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_app_update/azhon_app_update.dart';
|
||||||
|
import 'package:flutter_app_update/update_model.dart';
|
||||||
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:package_info_plus/package_info_plus.dart';
|
import 'package:package_info_plus/package_info_plus.dart';
|
||||||
|
import 'package:collection/collection.dart'; // Added for firstWhereOrNull
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher.dart';
|
import 'package:url_launcher/url_launcher.dart';
|
||||||
import 'package:island/widgets/content/sheet.dart';
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
|
|
||||||
/// Data model for a GitHub release we care about
|
/// Data model for a GitHub release we care about
|
||||||
class GithubReleaseInfo {
|
class GithubReleaseInfo {
|
||||||
final String tagName; // e.g. 3.1.0+118
|
final String tagName;
|
||||||
final String name; // release title
|
final String name;
|
||||||
final String body; // changelog markdown
|
final String body;
|
||||||
final String htmlUrl; // release page
|
final String htmlUrl;
|
||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
|
final List<GithubReleaseAsset> assets;
|
||||||
|
|
||||||
const GithubReleaseInfo({
|
const GithubReleaseInfo({
|
||||||
required this.tagName,
|
required this.tagName,
|
||||||
@@ -21,9 +30,28 @@ class GithubReleaseInfo {
|
|||||||
required this.body,
|
required this.body,
|
||||||
required this.htmlUrl,
|
required this.htmlUrl,
|
||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
|
this.assets = const [],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Data model for a GitHub release asset
|
||||||
|
class GithubReleaseAsset {
|
||||||
|
final String name;
|
||||||
|
final String browserDownloadUrl;
|
||||||
|
|
||||||
|
const GithubReleaseAsset({
|
||||||
|
required this.name,
|
||||||
|
required this.browserDownloadUrl,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory GithubReleaseAsset.fromJson(Map<String, dynamic> json) {
|
||||||
|
return GithubReleaseAsset(
|
||||||
|
name: json['name'] as String,
|
||||||
|
browserDownloadUrl: json['browser_download_url'] as String,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
/// Parses version and build number from "x.y.z+build"
|
/// Parses version and build number from "x.y.z+build"
|
||||||
class _ParsedVersion implements Comparable<_ParsedVersion> {
|
class _ParsedVersion implements Comparable<_ParsedVersion> {
|
||||||
final int major;
|
final int major;
|
||||||
@@ -62,7 +90,7 @@ class _ParsedVersion implements Comparable<_ParsedVersion> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class UpdateService {
|
class UpdateService {
|
||||||
UpdateService({Dio? dio})
|
UpdateService({Dio? dio, this.useProxy = false})
|
||||||
: _dio =
|
: _dio =
|
||||||
dio ??
|
dio ??
|
||||||
Dio(
|
Dio(
|
||||||
@@ -78,6 +106,9 @@ class UpdateService {
|
|||||||
);
|
);
|
||||||
|
|
||||||
final Dio _dio;
|
final Dio _dio;
|
||||||
|
final bool useProxy;
|
||||||
|
|
||||||
|
static const _proxyBaseUrl = 'https://ghfast.top/';
|
||||||
|
|
||||||
static const _releasesLatestApi =
|
static const _releasesLatestApi =
|
||||||
'https://api.github.com/repos/solsynth/solian/releases/latest';
|
'https://api.github.com/repos/solsynth/solian/releases/latest';
|
||||||
@@ -85,31 +116,52 @@ class UpdateService {
|
|||||||
/// Checks GitHub for the latest release and compares against the current app version.
|
/// Checks GitHub for the latest release and compares against the current app version.
|
||||||
/// If update is available, shows a bottom sheet with changelog and an action to open release page.
|
/// If update is available, shows a bottom sheet with changelog and an action to open release page.
|
||||||
Future<void> checkForUpdates(BuildContext context) async {
|
Future<void> checkForUpdates(BuildContext context) async {
|
||||||
|
log('[Update] Checking for updates...');
|
||||||
try {
|
try {
|
||||||
final release = await fetchLatestRelease();
|
final release = await fetchLatestRelease();
|
||||||
if (release == null) return;
|
if (release == null) {
|
||||||
|
log('[Update] No latest release found or could not fetch.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log('[Update] Fetched latest release: ${release.tagName}');
|
||||||
|
|
||||||
final info = await PackageInfo.fromPlatform();
|
final info = await PackageInfo.fromPlatform();
|
||||||
final localVersionStr = '${info.version}+${info.buildNumber}';
|
final localVersionStr = '${info.version}+${info.buildNumber}';
|
||||||
|
log('[Update] Local app version: $localVersionStr');
|
||||||
|
|
||||||
final latest = _ParsedVersion.tryParse(release.tagName);
|
final latest = _ParsedVersion.tryParse(release.tagName);
|
||||||
final local = _ParsedVersion.tryParse(localVersionStr);
|
final local = _ParsedVersion.tryParse(localVersionStr);
|
||||||
|
|
||||||
if (latest == null || local == null) {
|
if (latest == null || local == null) {
|
||||||
|
log(
|
||||||
|
'[Update] Failed to parse versions. Latest: ${release.tagName}, Local: $localVersionStr',
|
||||||
|
);
|
||||||
// If parsing fails, do nothing silently
|
// If parsing fails, do nothing silently
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
log('[Update] Parsed versions. Latest: $latest, Local: $local');
|
||||||
|
|
||||||
final needsUpdate = latest.compareTo(local) > 0;
|
final needsUpdate = latest.compareTo(local) > 0;
|
||||||
if (!needsUpdate) return;
|
if (!needsUpdate) {
|
||||||
|
log('[Update] App is up to date. No update needed.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
log('[Update] Update available! Latest: $latest, Local: $local');
|
||||||
|
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) {
|
||||||
|
log('[Update] Context not mounted, cannot show update sheet.');
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
// Delay to ensure UI is ready (if called at startup)
|
// Delay to ensure UI is ready (if called at startup)
|
||||||
await Future.delayed(const Duration(milliseconds: 100));
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
|
||||||
await showUpdateSheet(context, release);
|
if (context.mounted) {
|
||||||
} catch (_) {
|
await showUpdateSheet(context, release);
|
||||||
|
log('[Update] Update sheet shown.');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
log('[Update] Error checking for updates: $e');
|
||||||
// Ignore errors (network, api, etc.)
|
// Ignore errors (network, api, etc.)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -126,25 +178,68 @@ class UpdateService {
|
|||||||
context: context,
|
context: context,
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
useRootNavigator: true,
|
useRootNavigator: true,
|
||||||
builder:
|
builder: (ctx) {
|
||||||
(ctx) => _UpdateSheet(
|
String? androidUpdateUrl;
|
||||||
release: release,
|
if (Platform.isAndroid) {
|
||||||
onOpen: () async {
|
androidUpdateUrl = _getAndroidUpdateUrl(release.assets);
|
||||||
final uri = Uri.parse(release.htmlUrl);
|
}
|
||||||
if (await canLaunchUrl(uri)) {
|
return _UpdateSheet(
|
||||||
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
release: release,
|
||||||
}
|
onOpen: () async {
|
||||||
},
|
final uri = Uri.parse(release.htmlUrl);
|
||||||
),
|
if (await canLaunchUrl(uri)) {
|
||||||
|
await launchUrl(uri, mode: LaunchMode.externalApplication);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
androidUpdateUrl: androidUpdateUrl,
|
||||||
|
useProxy: useProxy, // Pass the useProxy flag
|
||||||
|
);
|
||||||
|
},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String? _getAndroidUpdateUrl(List<GithubReleaseAsset> assets) {
|
||||||
|
final arm64 = assets.firstWhereOrNull(
|
||||||
|
(asset) => asset.name == 'app-arm64-v8a-release.apk',
|
||||||
|
);
|
||||||
|
final armeabi = assets.firstWhereOrNull(
|
||||||
|
(asset) => asset.name == 'app-armeabi-v7a-release.apk',
|
||||||
|
);
|
||||||
|
final x86_64 = assets.firstWhereOrNull(
|
||||||
|
(asset) => asset.name == 'app-x86_64-release.apk',
|
||||||
|
);
|
||||||
|
|
||||||
|
// Prioritize arm64, then armeabi, then x86_64
|
||||||
|
if (arm64 != null) {
|
||||||
|
return arm64.browserDownloadUrl;
|
||||||
|
} else if (armeabi != null) {
|
||||||
|
return armeabi.browserDownloadUrl;
|
||||||
|
} else if (x86_64 != null) {
|
||||||
|
return x86_64.browserDownloadUrl;
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
/// Fetch the latest release info from GitHub.
|
/// Fetch the latest release info from GitHub.
|
||||||
/// Public so other screens (e.g., About) can manually trigger update checks.
|
/// Public so other screens (e.g., About) can manually trigger update checks.
|
||||||
Future<GithubReleaseInfo?> fetchLatestRelease() async {
|
Future<GithubReleaseInfo?> fetchLatestRelease() async {
|
||||||
final resp = await _dio.get(_releasesLatestApi);
|
final apiEndpoint =
|
||||||
if (resp.statusCode != 200) return null;
|
useProxy
|
||||||
|
? '$_proxyBaseUrl${Uri.encodeComponent(_releasesLatestApi)}'
|
||||||
|
: _releasesLatestApi;
|
||||||
|
|
||||||
|
log(
|
||||||
|
'[Update] Fetching latest release from GitHub API: $apiEndpoint (Proxy: $useProxy)',
|
||||||
|
);
|
||||||
|
final resp = await _dio.get(apiEndpoint);
|
||||||
|
if (resp.statusCode != 200) {
|
||||||
|
log(
|
||||||
|
'[Update] Failed to fetch latest release. Status code: ${resp.statusCode}',
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
final data = resp.data as Map<String, dynamic>;
|
final data = resp.data as Map<String, dynamic>;
|
||||||
|
log('[Update] Successfully fetched release data.');
|
||||||
|
|
||||||
final tagName = (data['tag_name'] ?? '').toString();
|
final tagName = (data['tag_name'] ?? '').toString();
|
||||||
final name = (data['name'] ?? tagName).toString();
|
final name = (data['name'] ?? tagName).toString();
|
||||||
@@ -152,25 +247,70 @@ class UpdateService {
|
|||||||
final htmlUrl = (data['html_url'] ?? '').toString();
|
final htmlUrl = (data['html_url'] ?? '').toString();
|
||||||
final createdAtStr = (data['created_at'] ?? '').toString();
|
final createdAtStr = (data['created_at'] ?? '').toString();
|
||||||
final createdAt = DateTime.tryParse(createdAtStr) ?? DateTime.now();
|
final createdAt = DateTime.tryParse(createdAtStr) ?? DateTime.now();
|
||||||
|
final assetsData =
|
||||||
|
(data['assets'] as List<dynamic>?)
|
||||||
|
?.map((e) => GithubReleaseAsset.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
[];
|
||||||
|
|
||||||
if (tagName.isEmpty || htmlUrl.isEmpty) return null;
|
if (tagName.isEmpty || htmlUrl.isEmpty) {
|
||||||
|
log(
|
||||||
|
'[Update] Missing tag_name or html_url in release data. TagName: "$tagName", HtmlUrl: "$htmlUrl"',
|
||||||
|
);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
log('[Update] Returning GithubReleaseInfo for tag: $tagName');
|
||||||
return GithubReleaseInfo(
|
return GithubReleaseInfo(
|
||||||
tagName: tagName,
|
tagName: tagName,
|
||||||
name: name,
|
name: name,
|
||||||
body: body,
|
body: body,
|
||||||
htmlUrl: htmlUrl,
|
htmlUrl: htmlUrl,
|
||||||
createdAt: createdAt,
|
createdAt: createdAt,
|
||||||
|
assets: assetsData,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _UpdateSheet extends StatelessWidget {
|
class _UpdateSheet extends StatefulWidget {
|
||||||
const _UpdateSheet({required this.release, required this.onOpen});
|
const _UpdateSheet({
|
||||||
|
required this.release,
|
||||||
|
required this.onOpen,
|
||||||
|
this.androidUpdateUrl,
|
||||||
|
this.useProxy = false,
|
||||||
|
});
|
||||||
|
|
||||||
|
final String? androidUpdateUrl;
|
||||||
|
final bool useProxy;
|
||||||
final GithubReleaseInfo release;
|
final GithubReleaseInfo release;
|
||||||
final VoidCallback onOpen;
|
final VoidCallback onOpen;
|
||||||
|
|
||||||
|
@override
|
||||||
|
State<_UpdateSheet> createState() => _UpdateSheetState();
|
||||||
|
}
|
||||||
|
|
||||||
|
class _UpdateSheetState extends State<_UpdateSheet> {
|
||||||
|
late bool _useProxy;
|
||||||
|
|
||||||
|
@override
|
||||||
|
void initState() {
|
||||||
|
super.initState();
|
||||||
|
_useProxy = widget.useProxy;
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _installUpdate(String url) async {
|
||||||
|
final downloadUrl =
|
||||||
|
_useProxy ? 'https://ghfast.top/${Uri.encodeComponent(url)}' : url;
|
||||||
|
|
||||||
|
UpdateModel model = UpdateModel(
|
||||||
|
downloadUrl,
|
||||||
|
"solian-update-${widget.release.tagName}.apk",
|
||||||
|
"launcher_icon",
|
||||||
|
'https://apps.apple.com/us/app/solian/id6499032345',
|
||||||
|
);
|
||||||
|
AzhonAppUpdate.update(model);
|
||||||
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
final theme = Theme.of(context);
|
final theme = Theme.of(context);
|
||||||
@@ -186,8 +326,11 @@ class _UpdateSheet extends StatelessWidget {
|
|||||||
Column(
|
Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
Text(release.name, style: theme.textTheme.titleMedium).bold(),
|
Text(
|
||||||
Text(release.tagName).fontSize(12),
|
widget.release.name,
|
||||||
|
style: theme.textTheme.titleMedium,
|
||||||
|
).bold(),
|
||||||
|
Text(widget.release.tagName).fontSize(12),
|
||||||
],
|
],
|
||||||
).padding(vertical: 16, horizontal: 16),
|
).padding(vertical: 16, horizontal: 16),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
@@ -197,21 +340,45 @@ class _UpdateSheet extends StatelessWidget {
|
|||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
vertical: 16,
|
vertical: 16,
|
||||||
),
|
),
|
||||||
child: SelectableText(
|
child: MarkdownTextContent(
|
||||||
release.body.isEmpty
|
content:
|
||||||
? 'No changelog provided.'
|
widget.release.body.isEmpty
|
||||||
: release.body,
|
? 'No changelog provided.'
|
||||||
style: theme.textTheme.bodyMedium,
|
: widget.release.body,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (!kIsWeb && Platform.isAndroid)
|
||||||
|
SwitchListTile(
|
||||||
|
title: const Text('Use GitHub Proxy for Download'),
|
||||||
|
value: _useProxy,
|
||||||
|
onChanged: (value) {
|
||||||
|
setState(() {
|
||||||
|
_useProxy = value;
|
||||||
|
});
|
||||||
|
},
|
||||||
|
).padding(horizontal: 8),
|
||||||
Column(
|
Column(
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Row(
|
||||||
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
|
if (!kIsWeb &&
|
||||||
|
Platform.isAndroid &&
|
||||||
|
widget.androidUpdateUrl != null)
|
||||||
|
Expanded(
|
||||||
|
child: FilledButton.icon(
|
||||||
|
onPressed: () {
|
||||||
|
log(widget.androidUpdateUrl!);
|
||||||
|
_installUpdate(widget.androidUpdateUrl!);
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.update),
|
||||||
|
label: const Text('Install update'),
|
||||||
|
),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FilledButton.icon(
|
child: FilledButton.icon(
|
||||||
onPressed: onOpen,
|
onPressed: widget.onOpen,
|
||||||
icon: const Icon(Icons.open_in_new),
|
icon: const Icon(Icons.open_in_new),
|
||||||
label: const Text('Open release page'),
|
label: const Text('Open release page'),
|
||||||
),
|
),
|
||||||
|
@@ -55,7 +55,7 @@ class AccountStatusCreationSheet extends HookConsumerWidget {
|
|||||||
'attitude': attitude.value,
|
'attitude': attitude.value,
|
||||||
'is_invisible': isInvisible.value,
|
'is_invisible': isInvisible.value,
|
||||||
'is_not_disturb': isNotDisturb.value,
|
'is_not_disturb': isNotDisturb.value,
|
||||||
'cleared_at': clearedAt.value?.toIso8601String(),
|
'cleared_at': clearedAt.value?.toUtc().toIso8601String(),
|
||||||
if (labelController.text.isNotEmpty) 'label': labelController.text,
|
if (labelController.text.isNotEmpty) 'label': labelController.text,
|
||||||
},
|
},
|
||||||
options: Options(method: initialStatus == null ? 'POST' : 'PATCH'),
|
options: Options(method: initialStatus == null ? 'POST' : 'PATCH'),
|
||||||
|
@@ -331,7 +331,7 @@ class _WebSocketIndicator extends HookConsumerWidget {
|
|||||||
final user = ref.watch(userInfoProvider);
|
final user = ref.watch(userInfoProvider);
|
||||||
final websocketState = ref.watch(websocketStateProvider);
|
final websocketState = ref.watch(websocketStateProvider);
|
||||||
final indicatorHeight =
|
final indicatorHeight =
|
||||||
MediaQuery.of(context).padding.top + (isDesktop ? 27.5 : 20);
|
MediaQuery.of(context).padding.top + (isDesktop ? 27.5 : 25);
|
||||||
|
|
||||||
Color indicatorColor;
|
Color indicatorColor;
|
||||||
String indicatorText;
|
String indicatorText;
|
||||||
|
@@ -5,6 +5,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
|||||||
import 'package:island/pods/websocket.dart';
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/services/notify.dart';
|
import 'package:island/services/notify.dart';
|
||||||
import 'package:island/services/sharing_intent.dart';
|
import 'package:island/services/sharing_intent.dart';
|
||||||
|
import 'package:island/services/update_service.dart';
|
||||||
import 'package:island/widgets/content/network_status_sheet.dart';
|
import 'package:island/widgets/content/network_status_sheet.dart';
|
||||||
import 'package:island/widgets/tour/tour.dart';
|
import 'package:island/widgets/tour/tour.dart';
|
||||||
|
|
||||||
@@ -21,6 +22,7 @@ class AppWrapper extends HookConsumerWidget {
|
|||||||
});
|
});
|
||||||
final sharingService = SharingIntentService();
|
final sharingService = SharingIntentService();
|
||||||
sharingService.initialize(context);
|
sharingService.initialize(context);
|
||||||
|
UpdateService().checkForUpdates(context);
|
||||||
return () {
|
return () {
|
||||||
sharingService.dispose();
|
sharingService.dispose();
|
||||||
ntySubs?.cancel();
|
ntySubs?.cancel();
|
||||||
|
@@ -142,7 +142,7 @@ class CloudVideoWidget extends HookConsumerWidget {
|
|||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
children: [
|
children: [
|
||||||
Row(
|
Wrap(
|
||||||
spacing: 8,
|
spacing: 8,
|
||||||
children: [
|
children: [
|
||||||
if (item.fileMeta?['duration'] != null)
|
if (item.fileMeta?['duration'] != null)
|
||||||
@@ -199,8 +199,8 @@ class CloudVideoWidget extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
).padding(horizontal: 16, bottom: 12),
|
||||||
).padding(horizontal: 16, bottom: 12),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
@@ -6,6 +6,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:flutter_highlight/themes/a11y-dark.dart';
|
import 'package:flutter_highlight/themes/a11y-dark.dart';
|
||||||
import 'package:flutter_highlight/themes/a11y-light.dart';
|
import 'package:flutter_highlight/themes/a11y-light.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:google_fonts/google_fonts.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
@@ -71,7 +72,22 @@ class MarkdownTextContent extends HookConsumerWidget {
|
|||||||
textStyle: textStyle ?? Theme.of(context).textTheme.bodyMedium!,
|
textStyle: textStyle ?? Theme.of(context).textTheme.bodyMedium!,
|
||||||
),
|
),
|
||||||
HrConfig(height: 1, color: Theme.of(context).dividerColor),
|
HrConfig(height: 1, color: Theme.of(context).dividerColor),
|
||||||
PreConfig(theme: isDark ? a11yDarkTheme : a11yLightTheme),
|
PreConfig(
|
||||||
|
theme: isDark ? a11yDarkTheme : a11yLightTheme,
|
||||||
|
textStyle: GoogleFonts.robotoMono(fontSize: 14),
|
||||||
|
styleNotMatched: GoogleFonts.robotoMono(fontSize: 14),
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHighest,
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
TableConfig(
|
||||||
|
wrapper:
|
||||||
|
(child) => SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
LinkConfig(
|
LinkConfig(
|
||||||
style:
|
style:
|
||||||
linkStyle ??
|
linkStyle ??
|
||||||
@@ -160,7 +176,7 @@ class MarkdownTextContent extends HookConsumerWidget {
|
|||||||
uri: stickerUri,
|
uri: stickerUri,
|
||||||
width: size,
|
width: size,
|
||||||
height: size,
|
height: size,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.contain,
|
||||||
noCacheOptimization: true,
|
noCacheOptimization: true,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
76
lib/widgets/debug_sheet.dart
Normal file
76
lib/widgets/debug_sheet.dart
Normal file
@@ -0,0 +1,76 @@
|
|||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter/services.dart';
|
||||||
|
import 'package:flutter_cache_manager/flutter_cache_manager.dart';
|
||||||
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
|
import 'package:island/pods/message.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/pods/websocket.dart';
|
||||||
|
import 'package:island/widgets/content/network_status_sheet.dart';
|
||||||
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
|
||||||
|
class DebugSheet extends HookConsumerWidget {
|
||||||
|
const DebugSheet({super.key});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final wsNotifier = ref.watch(websocketStateProvider.notifier);
|
||||||
|
|
||||||
|
return SheetScaffold(
|
||||||
|
titleText: 'Debug',
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
minTileHeight: 48,
|
||||||
|
leading: const Icon(Symbols.wifi),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
title: Text('Connection Status'),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
onTap: () {
|
||||||
|
showModalBottomSheet(
|
||||||
|
context: context,
|
||||||
|
isScrollControlled: true,
|
||||||
|
builder:
|
||||||
|
(context) => NetworkStatusSheet(
|
||||||
|
onReconnect: () => wsNotifier.connect(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Divider(height: 1),
|
||||||
|
ListTile(
|
||||||
|
minTileHeight: 48,
|
||||||
|
leading: const Icon(Symbols.copy_all),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
title: Text('Copy access token'),
|
||||||
|
onTap: () async {
|
||||||
|
final tk = ref.watch(tokenProvider);
|
||||||
|
Clipboard.setData(ClipboardData(text: tk!.token));
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
minTileHeight: 48,
|
||||||
|
leading: const Icon(Symbols.delete),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
title: Text('Reset database'),
|
||||||
|
onTap: () async {
|
||||||
|
resetDatabase(ref);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
minTileHeight: 48,
|
||||||
|
leading: const Icon(Symbols.clear),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
title: Text('Clear cache'),
|
||||||
|
onTap: () async {
|
||||||
|
DefaultCacheManager().emptyCache();
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
@@ -248,7 +248,7 @@ class _PaymentContentState extends ConsumerState<_PaymentContent> {
|
|||||||
try {
|
try {
|
||||||
final client = ref.read(apiClientProvider);
|
final client = ref.read(apiClientProvider);
|
||||||
final response = await client.post(
|
final response = await client.post(
|
||||||
'/orders/${widget.order.id}/pay',
|
'/id/orders/${widget.order.id}/pay',
|
||||||
data: {'pin_code': pin},
|
data: {'pin_code': pin},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@@ -6,7 +6,6 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post_category.dart';
|
import 'package:island/models/post_category.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/services/text.dart';
|
|
||||||
import 'package:island/widgets/content/sheet.dart';
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
import 'package:island/widgets/post/compose_shared.dart';
|
import 'package:island/widgets/post/compose_shared.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
@@ -16,12 +15,12 @@ import 'package:textfield_tags/textfield_tags.dart';
|
|||||||
part 'compose_settings_sheet.g.dart';
|
part 'compose_settings_sheet.g.dart';
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<List<PostCategory>> postCategories(Ref ref) async {
|
Future<List<SnPostCategory>> postCategories(Ref ref) async {
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
final resp = await apiClient.get('/sphere/posts/categories');
|
final resp = await apiClient.get('/sphere/posts/categories');
|
||||||
return resp.data
|
return resp.data
|
||||||
.map((e) => PostCategory.fromJson(e))
|
.map((e) => SnPostCategory.fromJson(e))
|
||||||
.cast<PostCategory>()
|
.cast<SnPostCategory>()
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -215,16 +214,9 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
String getCategoryDisplayTitle(PostCategory category) {
|
|
||||||
final capitalizedSlug = category.slug.capitalizeEachWord();
|
|
||||||
if ('postCategory$capitalizedSlug'.trExists()) {
|
|
||||||
return 'postCategory$capitalizedSlug'.tr();
|
|
||||||
}
|
|
||||||
return category.name ?? category.slug;
|
|
||||||
}
|
|
||||||
|
|
||||||
return SheetScaffold(
|
return SheetScaffold(
|
||||||
titleText: 'postSettings'.tr(),
|
titleText: 'postSettings'.tr(),
|
||||||
|
heightFactor: 0.6,
|
||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
child: Column(
|
child: Column(
|
||||||
@@ -253,7 +245,7 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
|
|
||||||
// Categories field
|
// Categories field
|
||||||
// FIXME: Sometimes the entire dropdown crashes: 'package:flutter/src/rendering/stack.dart': Failed assertion: line 799 pos 12: 'firstChild == null || child != null': is not true.
|
// FIXME: Sometimes the entire dropdown crashes: 'package:flutter/src/rendering/stack.dart': Failed assertion: line 799 pos 12: 'firstChild == null || child != null': is not true.
|
||||||
DropdownButtonFormField2<PostCategory>(
|
DropdownButtonFormField2<SnPostCategory>(
|
||||||
isExpanded: true,
|
isExpanded: true,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
contentPadding: const EdgeInsets.symmetric(vertical: 9),
|
contentPadding: const EdgeInsets.symmetric(vertical: 9),
|
||||||
@@ -263,7 +255,7 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
hint: Text('categories'.tr(), style: TextStyle(fontSize: 15)),
|
hint: Text('categories'.tr(), style: TextStyle(fontSize: 15)),
|
||||||
items:
|
items:
|
||||||
(postCategories.value ?? <PostCategory>[]).map((item) {
|
(postCategories.value ?? <SnPostCategory>[]).map((item) {
|
||||||
return DropdownMenuItem(
|
return DropdownMenuItem(
|
||||||
value: item,
|
value: item,
|
||||||
enabled: false,
|
enabled: false,
|
||||||
@@ -299,7 +291,7 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
const SizedBox(width: 16),
|
const SizedBox(width: 16),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Text(
|
child: Text(
|
||||||
getCategoryDisplayTitle(item),
|
item.categoryDisplayTitle,
|
||||||
style: const TextStyle(fontSize: 14),
|
style: const TextStyle(fontSize: 14),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -331,7 +323,7 @@ class ComposeSettingsSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
margin: const EdgeInsets.only(right: 4),
|
margin: const EdgeInsets.only(right: 4),
|
||||||
child: Text(
|
child: Text(
|
||||||
getCategoryDisplayTitle(category),
|
category.categoryDisplayTitle,
|
||||||
style: TextStyle(
|
style: TextStyle(
|
||||||
color: Theme.of(context).colorScheme.onPrimary,
|
color: Theme.of(context).colorScheme.onPrimary,
|
||||||
fontSize: 13,
|
fontSize: 13,
|
||||||
|
@@ -6,12 +6,12 @@ part of 'compose_settings_sheet.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$postCategoriesHash() => r'503ce6f0fdd728a8cb991665006c3b4bffbb94d4';
|
String _$postCategoriesHash() => r'24337fe806d088b6468a350f62d5a5d40232a73c';
|
||||||
|
|
||||||
/// See also [postCategories].
|
/// See also [postCategories].
|
||||||
@ProviderFor(postCategories)
|
@ProviderFor(postCategories)
|
||||||
final postCategoriesProvider =
|
final postCategoriesProvider =
|
||||||
AutoDisposeFutureProvider<List<PostCategory>>.internal(
|
AutoDisposeFutureProvider<List<SnPostCategory>>.internal(
|
||||||
postCategories,
|
postCategories,
|
||||||
name: r'postCategoriesProvider',
|
name: r'postCategoriesProvider',
|
||||||
debugGetCreateSourceHash:
|
debugGetCreateSourceHash:
|
||||||
@@ -24,6 +24,6 @@ final postCategoriesProvider =
|
|||||||
|
|
||||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
// ignore: unused_element
|
// ignore: unused_element
|
||||||
typedef PostCategoriesRef = AutoDisposeFutureProviderRef<List<PostCategory>>;
|
typedef PostCategoriesRef = AutoDisposeFutureProviderRef<List<SnPostCategory>>;
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
@@ -31,7 +31,7 @@ class ComposeState {
|
|||||||
final ValueNotifier<Map<int, double>> attachmentProgress;
|
final ValueNotifier<Map<int, double>> attachmentProgress;
|
||||||
final ValueNotifier<SnPublisher?> currentPublisher;
|
final ValueNotifier<SnPublisher?> currentPublisher;
|
||||||
final ValueNotifier<bool> submitting;
|
final ValueNotifier<bool> submitting;
|
||||||
final ValueNotifier<List<PostCategory>> categories;
|
final ValueNotifier<List<SnPostCategory>> categories;
|
||||||
StringTagController tagsController;
|
StringTagController tagsController;
|
||||||
final String draftId;
|
final String draftId;
|
||||||
int postType;
|
int postType;
|
||||||
@@ -109,7 +109,7 @@ class ComposeLogic {
|
|||||||
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
||||||
currentPublisher: ValueNotifier<SnPublisher?>(originalPost?.publisher),
|
currentPublisher: ValueNotifier<SnPublisher?>(originalPost?.publisher),
|
||||||
tagsController: tagsController,
|
tagsController: tagsController,
|
||||||
categories: ValueNotifier<List<PostCategory>>(
|
categories: ValueNotifier<List<SnPostCategory>>(
|
||||||
originalPost?.categories ?? [],
|
originalPost?.categories ?? [],
|
||||||
),
|
),
|
||||||
draftId: id,
|
draftId: id,
|
||||||
@@ -140,7 +140,7 @@ class ComposeLogic {
|
|||||||
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
attachmentProgress: ValueNotifier<Map<int, double>>({}),
|
||||||
currentPublisher: ValueNotifier<SnPublisher?>(null),
|
currentPublisher: ValueNotifier<SnPublisher?>(null),
|
||||||
tagsController: tagsController,
|
tagsController: tagsController,
|
||||||
categories: ValueNotifier<List<PostCategory>>([]),
|
categories: ValueNotifier<List<SnPostCategory>>([]),
|
||||||
draftId: draft.id,
|
draftId: draft.id,
|
||||||
postType: postType,
|
postType: postType,
|
||||||
pollId: null,
|
pollId: null,
|
||||||
|
@@ -273,7 +273,7 @@ class PostItem extends HookConsumerWidget {
|
|||||||
: item.reactionsCount.entries
|
: item.reactionsCount.entries
|
||||||
.sortedBy((e) => e.value)
|
.sortedBy((e) => e.value)
|
||||||
.map((e) => e.key)
|
.map((e) => e.key)
|
||||||
.first;
|
.last;
|
||||||
|
|
||||||
final postLanguage =
|
final postLanguage =
|
||||||
item.content != null
|
item.content != null
|
||||||
@@ -315,7 +315,7 @@ class PostItem extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
String _parseVisibility(int visibility) {
|
String parseVisibility(int visibility) {
|
||||||
switch (visibility) {
|
switch (visibility) {
|
||||||
case 1:
|
case 1:
|
||||||
return 'postVisibilityFriends';
|
return 'postVisibilityFriends';
|
||||||
@@ -377,12 +377,10 @@ class PostItem extends HookConsumerWidget {
|
|||||||
if (item.editedAt != null)
|
if (item.editedAt != null)
|
||||||
Text(
|
Text(
|
||||||
'editedAt'.tr(args: [item.editedAt!.formatSystem()]),
|
'editedAt'.tr(args: [item.editedAt!.formatSystem()]),
|
||||||
style: TextStyle(height: 1.2),
|
|
||||||
).fontSize(10),
|
).fontSize(10),
|
||||||
if (item.visibility != 0)
|
if (item.visibility != 0)
|
||||||
Text(
|
Text(
|
||||||
_parseVisibility(item.visibility).tr(),
|
parseVisibility(item.visibility).tr(),
|
||||||
style: TextStyle(height: 1.45),
|
|
||||||
).fontSize(10),
|
).fontSize(10),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -482,7 +480,9 @@ class PostItem extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
else if (item.content?.isNotEmpty ?? false)
|
else if ((item.content?.isNotEmpty ?? false) ||
|
||||||
|
(item.title?.isNotEmpty ?? false) ||
|
||||||
|
(item.description?.isNotEmpty ?? false))
|
||||||
Padding(
|
Padding(
|
||||||
padding: EdgeInsets.only(
|
padding: EdgeInsets.only(
|
||||||
left: renderingPadding.horizontal,
|
left: renderingPadding.horizontal,
|
||||||
@@ -573,6 +573,58 @@ class PostItem extends HookConsumerWidget {
|
|||||||
vertical: 4,
|
vertical: 4,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if (item.tags.isNotEmpty)
|
||||||
|
Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
spacing: 2,
|
||||||
|
children: [
|
||||||
|
if (item.tags.isNotEmpty)
|
||||||
|
Wrap(
|
||||||
|
runAlignment: WrapAlignment.center,
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.label, size: 16).padding(top: 2),
|
||||||
|
for (final tag
|
||||||
|
in isFullPost ? item.tags : item.tags.take(3))
|
||||||
|
InkWell(
|
||||||
|
child: Text('#${tag.name ?? tag.slug}'),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'postTagDetail',
|
||||||
|
pathParameters: {'slug': tag.slug},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (!isFullPost && item.tags.length > 3)
|
||||||
|
Text('+${item.tags.length - 3}').opacity(0.6),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (item.categories.isNotEmpty)
|
||||||
|
Wrap(
|
||||||
|
runAlignment: WrapAlignment.center,
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.category, size: 16).padding(top: 2),
|
||||||
|
for (final category
|
||||||
|
in isFullPost
|
||||||
|
? item.categories
|
||||||
|
: item.categories.take(2))
|
||||||
|
InkWell(
|
||||||
|
child: Text(category.categoryDisplayTitle),
|
||||||
|
onTap: () {
|
||||||
|
GoRouter.of(context).pushNamed(
|
||||||
|
'postCategoryDetail',
|
||||||
|
pathParameters: {'slug': category.slug},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
if (!isFullPost && item.categories.length > 2)
|
||||||
|
Text('+${item.categories.length - 2}').opacity(0.6),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: renderingPadding.horizontal + 4, top: 4),
|
||||||
if (item.meta?['embeds'] != null)
|
if (item.meta?['embeds'] != null)
|
||||||
...((item.meta!['embeds'] as List<dynamic>)
|
...((item.meta!['embeds'] as List<dynamic>)
|
||||||
.map((embedData) => convertMapKeysToSnakeCase(embedData))
|
.map((embedData) => convertMapKeysToSnakeCase(embedData))
|
||||||
|
@@ -15,7 +15,12 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
static const int _pageSize = 20;
|
static const int _pageSize = 20;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<CursorPagingData<SnPost>> build(String? pubName, int? type) {
|
Future<CursorPagingData<SnPost>> build(
|
||||||
|
String? pubName, {
|
||||||
|
int? type,
|
||||||
|
List<String>? categories,
|
||||||
|
List<String>? tags,
|
||||||
|
}) {
|
||||||
return fetch(cursor: null);
|
return fetch(cursor: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -29,6 +34,8 @@ class PostListNotifier extends _$PostListNotifier
|
|||||||
'take': _pageSize,
|
'take': _pageSize,
|
||||||
if (pubName != null) 'pub': pubName,
|
if (pubName != null) 'pub': pubName,
|
||||||
if (type != null) 'type': type,
|
if (type != null) 'type': type,
|
||||||
|
if (tags != null) 'tags': tags,
|
||||||
|
if (categories != null) 'categories': categories,
|
||||||
};
|
};
|
||||||
|
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
@@ -62,6 +69,8 @@ enum PostItemType {
|
|||||||
class SliverPostList extends HookConsumerWidget {
|
class SliverPostList extends HookConsumerWidget {
|
||||||
final String? pubName;
|
final String? pubName;
|
||||||
final int? type;
|
final int? type;
|
||||||
|
final List<String>? categories;
|
||||||
|
final List<String>? tags;
|
||||||
final PostItemType itemType;
|
final PostItemType itemType;
|
||||||
final Color? backgroundColor;
|
final Color? backgroundColor;
|
||||||
final EdgeInsets? padding;
|
final EdgeInsets? padding;
|
||||||
@@ -73,6 +82,8 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
super.key,
|
super.key,
|
||||||
this.pubName,
|
this.pubName,
|
||||||
this.type,
|
this.type,
|
||||||
|
this.categories,
|
||||||
|
this.tags,
|
||||||
this.itemType = PostItemType.regular,
|
this.itemType = PostItemType.regular,
|
||||||
this.backgroundColor,
|
this.backgroundColor,
|
||||||
this.padding,
|
this.padding,
|
||||||
@@ -84,9 +95,26 @@ class SliverPostList extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
return PagingHelperSliverView(
|
return PagingHelperSliverView(
|
||||||
provider: postListNotifierProvider(pubName, type),
|
provider: postListNotifierProvider(
|
||||||
futureRefreshable: postListNotifierProvider(pubName, type).future,
|
pubName,
|
||||||
notifierRefreshable: postListNotifierProvider(pubName, type).notifier,
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
|
),
|
||||||
|
futureRefreshable:
|
||||||
|
postListNotifierProvider(
|
||||||
|
pubName,
|
||||||
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
|
).future,
|
||||||
|
notifierRefreshable:
|
||||||
|
postListNotifierProvider(
|
||||||
|
pubName,
|
||||||
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
|
).notifier,
|
||||||
contentBuilder:
|
contentBuilder:
|
||||||
(data, widgetCount, endItemView) => SliverList.builder(
|
(data, widgetCount, endItemView) => SliverList.builder(
|
||||||
itemCount: widgetCount,
|
itemCount: widgetCount,
|
||||||
|
@@ -6,7 +6,7 @@ part of 'post_list.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$postListNotifierHash() => r'78222d62957f85713d17aecd95af0305b764e86c';
|
String _$postListNotifierHash() => r'2ca4f3cfbbcd04f3cc32e7f7bd511a5811042829';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -33,8 +33,15 @@ abstract class _$PostListNotifier
|
|||||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPost>> {
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPost>> {
|
||||||
late final String? pubName;
|
late final String? pubName;
|
||||||
late final int? type;
|
late final int? type;
|
||||||
|
late final List<String>? categories;
|
||||||
|
late final List<String>? tags;
|
||||||
|
|
||||||
FutureOr<CursorPagingData<SnPost>> build(String? pubName, int? type);
|
FutureOr<CursorPagingData<SnPost>> build(
|
||||||
|
String? pubName, {
|
||||||
|
int? type,
|
||||||
|
List<String>? categories,
|
||||||
|
List<String>? tags,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// See also [PostListNotifier].
|
/// See also [PostListNotifier].
|
||||||
@@ -48,15 +55,30 @@ class PostListNotifierFamily
|
|||||||
const PostListNotifierFamily();
|
const PostListNotifierFamily();
|
||||||
|
|
||||||
/// See also [PostListNotifier].
|
/// See also [PostListNotifier].
|
||||||
PostListNotifierProvider call(String? pubName, int? type) {
|
PostListNotifierProvider call(
|
||||||
return PostListNotifierProvider(pubName, type);
|
String? pubName, {
|
||||||
|
int? type,
|
||||||
|
List<String>? categories,
|
||||||
|
List<String>? tags,
|
||||||
|
}) {
|
||||||
|
return PostListNotifierProvider(
|
||||||
|
pubName,
|
||||||
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
PostListNotifierProvider getProviderOverride(
|
PostListNotifierProvider getProviderOverride(
|
||||||
covariant PostListNotifierProvider provider,
|
covariant PostListNotifierProvider provider,
|
||||||
) {
|
) {
|
||||||
return call(provider.pubName, provider.type);
|
return call(
|
||||||
|
provider.pubName,
|
||||||
|
type: provider.type,
|
||||||
|
categories: provider.categories,
|
||||||
|
tags: provider.tags,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||||
@@ -82,24 +104,32 @@ class PostListNotifierProvider
|
|||||||
CursorPagingData<SnPost>
|
CursorPagingData<SnPost>
|
||||||
> {
|
> {
|
||||||
/// See also [PostListNotifier].
|
/// See also [PostListNotifier].
|
||||||
PostListNotifierProvider(String? pubName, int? type)
|
PostListNotifierProvider(
|
||||||
: this._internal(
|
String? pubName, {
|
||||||
() =>
|
int? type,
|
||||||
PostListNotifier()
|
List<String>? categories,
|
||||||
..pubName = pubName
|
List<String>? tags,
|
||||||
..type = type,
|
}) : this._internal(
|
||||||
from: postListNotifierProvider,
|
() =>
|
||||||
name: r'postListNotifierProvider',
|
PostListNotifier()
|
||||||
debugGetCreateSourceHash:
|
..pubName = pubName
|
||||||
const bool.fromEnvironment('dart.vm.product')
|
..type = type
|
||||||
? null
|
..categories = categories
|
||||||
: _$postListNotifierHash,
|
..tags = tags,
|
||||||
dependencies: PostListNotifierFamily._dependencies,
|
from: postListNotifierProvider,
|
||||||
allTransitiveDependencies:
|
name: r'postListNotifierProvider',
|
||||||
PostListNotifierFamily._allTransitiveDependencies,
|
debugGetCreateSourceHash:
|
||||||
pubName: pubName,
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
type: type,
|
? null
|
||||||
);
|
: _$postListNotifierHash,
|
||||||
|
dependencies: PostListNotifierFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
PostListNotifierFamily._allTransitiveDependencies,
|
||||||
|
pubName: pubName,
|
||||||
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
|
);
|
||||||
|
|
||||||
PostListNotifierProvider._internal(
|
PostListNotifierProvider._internal(
|
||||||
super._createNotifier, {
|
super._createNotifier, {
|
||||||
@@ -110,16 +140,25 @@ class PostListNotifierProvider
|
|||||||
required super.from,
|
required super.from,
|
||||||
required this.pubName,
|
required this.pubName,
|
||||||
required this.type,
|
required this.type,
|
||||||
|
required this.categories,
|
||||||
|
required this.tags,
|
||||||
}) : super.internal();
|
}) : super.internal();
|
||||||
|
|
||||||
final String? pubName;
|
final String? pubName;
|
||||||
final int? type;
|
final int? type;
|
||||||
|
final List<String>? categories;
|
||||||
|
final List<String>? tags;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
FutureOr<CursorPagingData<SnPost>> runNotifierBuild(
|
FutureOr<CursorPagingData<SnPost>> runNotifierBuild(
|
||||||
covariant PostListNotifier notifier,
|
covariant PostListNotifier notifier,
|
||||||
) {
|
) {
|
||||||
return notifier.build(pubName, type);
|
return notifier.build(
|
||||||
|
pubName,
|
||||||
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -130,7 +169,9 @@ class PostListNotifierProvider
|
|||||||
() =>
|
() =>
|
||||||
create()
|
create()
|
||||||
..pubName = pubName
|
..pubName = pubName
|
||||||
..type = type,
|
..type = type
|
||||||
|
..categories = categories
|
||||||
|
..tags = tags,
|
||||||
from: from,
|
from: from,
|
||||||
name: null,
|
name: null,
|
||||||
dependencies: null,
|
dependencies: null,
|
||||||
@@ -138,6 +179,8 @@ class PostListNotifierProvider
|
|||||||
debugGetCreateSourceHash: null,
|
debugGetCreateSourceHash: null,
|
||||||
pubName: pubName,
|
pubName: pubName,
|
||||||
type: type,
|
type: type,
|
||||||
|
categories: categories,
|
||||||
|
tags: tags,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -155,7 +198,9 @@ class PostListNotifierProvider
|
|||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return other is PostListNotifierProvider &&
|
return other is PostListNotifierProvider &&
|
||||||
other.pubName == pubName &&
|
other.pubName == pubName &&
|
||||||
other.type == type;
|
other.type == type &&
|
||||||
|
other.categories == categories &&
|
||||||
|
other.tags == tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -163,6 +208,8 @@ class PostListNotifierProvider
|
|||||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
hash = _SystemHash.combine(hash, pubName.hashCode);
|
hash = _SystemHash.combine(hash, pubName.hashCode);
|
||||||
hash = _SystemHash.combine(hash, type.hashCode);
|
hash = _SystemHash.combine(hash, type.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, categories.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, tags.hashCode);
|
||||||
|
|
||||||
return _SystemHash.finish(hash);
|
return _SystemHash.finish(hash);
|
||||||
}
|
}
|
||||||
@@ -177,6 +224,12 @@ mixin PostListNotifierRef
|
|||||||
|
|
||||||
/// The parameter `type` of this provider.
|
/// The parameter `type` of this provider.
|
||||||
int? get type;
|
int? get type;
|
||||||
|
|
||||||
|
/// The parameter `categories` of this provider.
|
||||||
|
List<String>? get categories;
|
||||||
|
|
||||||
|
/// The parameter `tags` of this provider.
|
||||||
|
List<String>? get tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
class _PostListNotifierProviderElement
|
class _PostListNotifierProviderElement
|
||||||
@@ -192,6 +245,11 @@ class _PostListNotifierProviderElement
|
|||||||
String? get pubName => (origin as PostListNotifierProvider).pubName;
|
String? get pubName => (origin as PostListNotifierProvider).pubName;
|
||||||
@override
|
@override
|
||||||
int? get type => (origin as PostListNotifierProvider).type;
|
int? get type => (origin as PostListNotifierProvider).type;
|
||||||
|
@override
|
||||||
|
List<String>? get categories =>
|
||||||
|
(origin as PostListNotifierProvider).categories;
|
||||||
|
@override
|
||||||
|
List<String>? get tags => (origin as PostListNotifierProvider).tags;
|
||||||
}
|
}
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
|
@@ -1,11 +1,13 @@
|
|||||||
import 'package:dio/dio.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/models/publisher.dart';
|
import 'package:island/models/publisher.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/screens/creators/publishers.dart';
|
import 'package:island/screens/creators/publishers.dart';
|
||||||
|
import 'package:island/screens/posts/compose.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/post/publishers_modal.dart';
|
import 'package:island/widgets/post/publishers_modal.dart';
|
||||||
@@ -14,8 +16,14 @@ import 'package:styled_widget/styled_widget.dart';
|
|||||||
|
|
||||||
class PostQuickReply extends HookConsumerWidget {
|
class PostQuickReply extends HookConsumerWidget {
|
||||||
final SnPost parent;
|
final SnPost parent;
|
||||||
final Function? onPosted;
|
final VoidCallback? onPosted;
|
||||||
const PostQuickReply({super.key, required this.parent, this.onPosted});
|
final VoidCallback? onLaunch;
|
||||||
|
const PostQuickReply({
|
||||||
|
super.key,
|
||||||
|
required this.parent,
|
||||||
|
this.onPosted,
|
||||||
|
this.onLaunch,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -48,7 +56,7 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
'content': contentController.text,
|
'content': contentController.text,
|
||||||
'replied_post_id': parent.id,
|
'replied_post_id': parent.id,
|
||||||
},
|
},
|
||||||
options: Options(headers: {'X-Pub': currentPublisher.value?.name}),
|
queryParameters: {'pub': currentPublisher.value?.name},
|
||||||
);
|
);
|
||||||
contentController.clear();
|
contentController.clear();
|
||||||
onPosted?.call();
|
onPosted?.call();
|
||||||
@@ -83,9 +91,10 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
child: TextField(
|
child: TextField(
|
||||||
controller: contentController,
|
controller: contentController,
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Post your reply',
|
hintText: 'postReplyPlaceholder'.tr(),
|
||||||
border: const OutlineInputBorder(),
|
border: InputBorder.none,
|
||||||
isDense: true,
|
isDense: true,
|
||||||
|
isCollapsed: true,
|
||||||
contentPadding: EdgeInsets.symmetric(
|
contentPadding: EdgeInsets.symmetric(
|
||||||
horizontal: 12,
|
horizontal: 12,
|
||||||
vertical: 8,
|
vertical: 8,
|
||||||
@@ -97,6 +106,26 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
IconButton(
|
||||||
|
onPressed: () {
|
||||||
|
onLaunch?.call();
|
||||||
|
GoRouter.of(context)
|
||||||
|
.pushNamed(
|
||||||
|
'postCompose',
|
||||||
|
extra: PostComposeInitialState(
|
||||||
|
content: contentController.text,
|
||||||
|
replyingTo: parent,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.then((value) {
|
||||||
|
if (value != null) onPosted?.call();
|
||||||
|
});
|
||||||
|
},
|
||||||
|
icon: const Icon(Symbols.launch, size: 20),
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
visualDensity: VisualDensity.compact,
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
visualDensity: VisualDensity.compact,
|
visualDensity: VisualDensity.compact,
|
||||||
@@ -110,6 +139,7 @@ class PostQuickReply extends HookConsumerWidget {
|
|||||||
: Icon(Symbols.send, size: 20),
|
: Icon(Symbols.send, size: 20),
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
onPressed: submitting.value ? null : performAction,
|
onPressed: submitting.value ? null : performAction,
|
||||||
|
constraints: const BoxConstraints(),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
@@ -38,14 +38,18 @@ class PostRepliesSheet extends HookConsumerWidget {
|
|||||||
if (user.value != null)
|
if (user.value != null)
|
||||||
Material(
|
Material(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
child: PostQuickReply(
|
child: PostQuickReply(
|
||||||
parent: post,
|
parent: post,
|
||||||
onPosted: () {
|
onPosted: () {
|
||||||
ref.invalidate(postRepliesNotifierProvider(post.id));
|
ref.invalidate(postRepliesNotifierProvider(post.id));
|
||||||
},
|
},
|
||||||
|
onLaunch: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
).padding(
|
).padding(
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 16,
|
bottom: MediaQuery.of(context).padding.bottom + 8,
|
||||||
top: 16,
|
top: 8,
|
||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
@@ -130,25 +130,25 @@ PODS:
|
|||||||
- sqflite_darwin (0.0.4):
|
- sqflite_darwin (0.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (3.50.3):
|
- sqlite3 (3.50.4):
|
||||||
- sqlite3/common (= 3.50.3)
|
- sqlite3/common (= 3.50.4)
|
||||||
- sqlite3/common (3.50.3)
|
- sqlite3/common (3.50.4)
|
||||||
- sqlite3/dbstatvtab (3.50.3):
|
- sqlite3/dbstatvtab (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/fts5 (3.50.3):
|
- sqlite3/fts5 (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/math (3.50.3):
|
- sqlite3/math (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/perf-threadsafe (3.50.3):
|
- sqlite3/perf-threadsafe (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/rtree (3.50.3):
|
- sqlite3/rtree (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3/session (3.50.3):
|
- sqlite3/session (3.50.4):
|
||||||
- sqlite3/common
|
- sqlite3/common
|
||||||
- sqlite3_flutter_libs (0.0.1):
|
- sqlite3_flutter_libs (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- sqlite3 (~> 3.50.3)
|
- sqlite3 (~> 3.50.4)
|
||||||
- sqlite3/dbstatvtab
|
- sqlite3/dbstatvtab
|
||||||
- sqlite3/fts5
|
- sqlite3/fts5
|
||||||
- sqlite3/math
|
- sqlite3/math
|
||||||
@@ -328,8 +328,8 @@ 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: 83105acd294c9137c026e2da1931c30b4588ab81
|
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
|
||||||
sqlite3_flutter_libs: 616267f2fca40e9c6af8c5d82324e05667040b6e
|
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
|
||||||
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
super_native_extensions: c2795d6d9aedf4a79fae25cb6160b71b50549189
|
||||||
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
url_launcher_macos: 0fba8ddabfc33ce0a9afe7c5fef5aab3d8d2d673
|
||||||
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
volume_controller: 5c068e6d085c80dadd33fc2c918d2114b775b3dd
|
||||||
|
@@ -2,6 +2,12 @@
|
|||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
|
<key>CLIENT_ID</key>
|
||||||
|
<string>961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com</string>
|
||||||
|
<key>REVERSED_CLIENT_ID</key>
|
||||||
|
<string>com.googleusercontent.apps.961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig</string>
|
||||||
|
<key>ANDROID_CLIENT_ID</key>
|
||||||
|
<string>961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com</string>
|
||||||
<key>API_KEY</key>
|
<key>API_KEY</key>
|
||||||
<string>AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8</string>
|
<string>AIzaSyCzQIyiYKoYHTpGXhN-IjgMML8z797WVD8</string>
|
||||||
<key>GCM_SENDER_ID</key>
|
<key>GCM_SENDER_ID</key>
|
||||||
|
80
pubspec.lock
80
pubspec.lock
@@ -73,22 +73,6 @@ packages:
|
|||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.13.0"
|
version: "2.13.0"
|
||||||
auto_route:
|
|
||||||
dependency: transitive
|
|
||||||
description:
|
|
||||||
name: auto_route
|
|
||||||
sha256: b8c036fa613a98a759cf0fdcba26e62f4985dcbff01a5e760ab411e8554bbaf0
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "10.1.0+1"
|
|
||||||
auto_route_generator:
|
|
||||||
dependency: "direct dev"
|
|
||||||
description:
|
|
||||||
name: auto_route_generator
|
|
||||||
sha256: "9e3846fcbeacba5c362557328dd8c8fbc953b6a0cbc3395365e8d8f92eea29c4"
|
|
||||||
url: "https://pub.dev"
|
|
||||||
source: hosted
|
|
||||||
version: "10.1.0"
|
|
||||||
avatar_stack:
|
avatar_stack:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -205,10 +189,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: built_value
|
name: built_value
|
||||||
sha256: "0b1b12a0a549605e5f04476031cd0bc91ead1d7c8e830773a18ee54179b3cb62"
|
sha256: ba95c961bafcd8686d1cf63be864eb59447e795e124d98d6a27d91fcd13602fb
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "8.11.0"
|
version: "8.11.1"
|
||||||
cached_network_image:
|
cached_network_image:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -453,10 +437,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: dio
|
name: dio
|
||||||
sha256: "253a18bbd4851fecba42f7343a1df3a9a4c1d31a2c1b37e221086b4fa8c8dbc9"
|
sha256: d90ee57923d1828ac14e492ca49440f65477f4bb1263575900be731a3dac66a9
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "5.8.0+1"
|
version: "5.9.0"
|
||||||
dio_web_adapter:
|
dio_web_adapter:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -573,10 +557,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: file_picker
|
name: file_picker
|
||||||
sha256: "13ba4e627ef24503a465d1d61b32596ce10eb6b8903678d362a528f9939b4aa8"
|
sha256: "8f9f429998f9232d65bc4757af74475ce44fc80f10704ff5dfa8b1d14fc429b9"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.2.1"
|
version: "10.2.3"
|
||||||
file_selector_linux:
|
file_selector_linux:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -678,6 +662,14 @@ packages:
|
|||||||
description: flutter
|
description: flutter
|
||||||
source: sdk
|
source: sdk
|
||||||
version: "0.0.0"
|
version: "0.0.0"
|
||||||
|
flutter_app_update:
|
||||||
|
dependency: "direct main"
|
||||||
|
description:
|
||||||
|
name: flutter_app_update
|
||||||
|
sha256: "09290240949c4651581cd6fc535e52d019e189e694d6019c56b5a56c2e69ba65"
|
||||||
|
url: "https://pub.dev"
|
||||||
|
source: hosted
|
||||||
|
version: "3.2.2"
|
||||||
flutter_blurhash:
|
flutter_blurhash:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -911,10 +903,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: flutter_plugin_android_lifecycle
|
name: flutter_plugin_android_lifecycle
|
||||||
sha256: f948e346c12f8d5480d2825e03de228d0eb8c3a737e4cdaa122267b89c022b5e
|
sha256: "6382ce712ff69b0f719640ce957559dde459e55ecd433c767e06d139ddf16cab"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.0.28"
|
version: "2.0.29"
|
||||||
flutter_popup_card:
|
flutter_popup_card:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1033,10 +1025,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: font_awesome_flutter
|
name: font_awesome_flutter
|
||||||
sha256: d3a89184101baec7f4600d58840a764d2ef760fe1c5a20ef9e6b0e9b24a07a3a
|
sha256: f50ce90dbe26d977415b9540400d6778bef00894aced6358ae578abd92b14b10
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "10.8.0"
|
version: "10.9.0"
|
||||||
freezed:
|
freezed:
|
||||||
dependency: "direct dev"
|
dependency: "direct dev"
|
||||||
description:
|
description:
|
||||||
@@ -1089,10 +1081,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: go_router
|
name: go_router
|
||||||
sha256: c489908a54ce2131f1d1b7cc631af9c1a06fac5ca7c449e959192089f9489431
|
sha256: "8b1f37dfaf6e958c6b872322db06f946509433bec3de753c3491a42ae9ec2b48"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "16.0.0"
|
version: "16.1.0"
|
||||||
google_fonts:
|
google_fonts:
|
||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
@@ -1153,10 +1145,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: http
|
name: http
|
||||||
sha256: "2c11f3f94c687ee9bad77c171151672986360b2b001d109814ee7140b2cf261b"
|
sha256: bb2ce4590bc2667c96f318d68cac1b5a7987ec819351d32b1c987239a815e007
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.4.0"
|
version: "1.5.0"
|
||||||
http_multi_server:
|
http_multi_server:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1193,10 +1185,10 @@ packages:
|
|||||||
dependency: "direct main"
|
dependency: "direct main"
|
||||||
description:
|
description:
|
||||||
name: image_picker_android
|
name: image_picker_android
|
||||||
sha256: "6fae381e6af2bbe0365a5e4ce1db3959462fa0c4d234facf070746024bb80c8d"
|
sha256: b08e9a04d0f8d91f4a6e767a745b9871bfbc585410205c311d0492de20a7ccd6
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.8.12+24"
|
version: "0.8.12+25"
|
||||||
image_picker_for_web:
|
image_picker_for_web:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -1361,18 +1353,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: local_auth_android
|
name: local_auth_android
|
||||||
sha256: "82b2bdeee2199a510d3b7716121e96a6609da86693bb0863edd8566355406b79"
|
sha256: "316503f6772dea9c0c038bb7aac4f68ab00112d707d258c770f7fc3c250a2d88"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.0.50"
|
version: "1.0.51"
|
||||||
local_auth_darwin:
|
local_auth_darwin:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: local_auth_darwin
|
name: local_auth_darwin
|
||||||
sha256: "25163ce60a5a6c468cf7a0e3dc8a165f824cabc2aa9e39a5e9fc5c2311b7686f"
|
sha256: "0e9706a8543a4a2eee60346294d6a633dd7c3ee60fae6b752570457c4ff32055"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "1.5.0"
|
version: "1.6.0"
|
||||||
local_auth_platform_interface:
|
local_auth_platform_interface:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2033,10 +2025,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: shared_preferences_android
|
name: shared_preferences_android
|
||||||
sha256: "20cbd561f743a342c76c151d6ddb93a9ce6005751e7aa458baad3858bfbfb6ac"
|
sha256: "5bcf0772a761b04f8c6bf814721713de6f3e5d9d89caf8d3fe031b02a342379e"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.4.10"
|
version: "2.4.11"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2206,18 +2198,18 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqlite3
|
name: sqlite3
|
||||||
sha256: dd806fff004a0aeb01e208b858dbc649bc72104670d425a81a6dd17698535f6e
|
sha256: f393d92c71bdcc118d6203d07c991b9be0f84b1a6f89dd4f7eed348131329924
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "2.8.0"
|
version: "2.9.0"
|
||||||
sqlite3_flutter_libs:
|
sqlite3_flutter_libs:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: sqlite3_flutter_libs
|
name: sqlite3_flutter_libs
|
||||||
sha256: fd996da5515a73aacd0a04ae7063db5fe8df42670d974df4c3ee538c652eef2e
|
sha256: "2b03273e71867a8a4d030861fc21706200debe5c5858a4b9e58f4a1c129586a4"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "0.5.38"
|
version: "0.5.39"
|
||||||
sqlparser:
|
sqlparser:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
@@ -2424,10 +2416,10 @@ packages:
|
|||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
name: url_launcher_android
|
name: url_launcher_android
|
||||||
sha256: "8582d7f6fe14d2652b4c45c9b6c14c0b678c2af2d083a11b604caeba51930d79"
|
sha256: "0aedad096a85b49df2e4725fa32118f9fa580f3b14af7a2d2221896a02cd5656"
|
||||||
url: "https://pub.dev"
|
url: "https://pub.dev"
|
||||||
source: hosted
|
source: hosted
|
||||||
version: "6.3.16"
|
version: "6.3.17"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
dependency: transitive
|
dependency: transitive
|
||||||
description:
|
description:
|
||||||
|
12
pubspec.yaml
12
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+117
|
version: 3.1.0+122
|
||||||
|
|
||||||
environment:
|
environment:
|
||||||
sdk: ^3.7.2
|
sdk: ^3.7.2
|
||||||
@@ -39,12 +39,12 @@ dependencies:
|
|||||||
flutter_hooks: ^0.21.2
|
flutter_hooks: ^0.21.2
|
||||||
hooks_riverpod: ^2.6.1
|
hooks_riverpod: ^2.6.1
|
||||||
bitsdojo_window: ^0.1.6
|
bitsdojo_window: ^0.1.6
|
||||||
go_router: ^16.0.0
|
go_router: ^16.1.0
|
||||||
styled_widget: ^0.4.1
|
styled_widget: ^0.4.1
|
||||||
shared_preferences: ^2.5.3
|
shared_preferences: ^2.5.3
|
||||||
flutter_riverpod: ^2.6.1
|
flutter_riverpod: ^2.6.1
|
||||||
path_provider: ^2.1.5
|
path_provider: ^2.1.5
|
||||||
dio: ^5.8.0+1
|
dio: ^5.9.0
|
||||||
very_good_infinite_list: ^0.9.0
|
very_good_infinite_list: ^0.9.0
|
||||||
freezed_annotation: ^3.1.0
|
freezed_annotation: ^3.1.0
|
||||||
json_annotation: ^4.9.0
|
json_annotation: ^4.9.0
|
||||||
@@ -73,10 +73,10 @@ dependencies:
|
|||||||
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.2.1
|
file_picker: ^10.2.3
|
||||||
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+24
|
image_picker_android: ^0.8.12+25
|
||||||
super_context_menu: ^0.9.1
|
super_context_menu: ^0.9.1
|
||||||
modal_bottom_sheet: ^3.0.0
|
modal_bottom_sheet: ^3.0.0
|
||||||
firebase_messaging: ^16.0.0
|
firebase_messaging: ^16.0.0
|
||||||
@@ -133,6 +133,7 @@ dependencies:
|
|||||||
flutter_typeahead: ^5.2.0
|
flutter_typeahead: ^5.2.0
|
||||||
flutter_langdetect: ^0.0.2
|
flutter_langdetect: ^0.0.2
|
||||||
waveform_flutter: ^1.2.0
|
waveform_flutter: ^1.2.0
|
||||||
|
flutter_app_update: ^3.2.2
|
||||||
|
|
||||||
dev_dependencies:
|
dev_dependencies:
|
||||||
flutter_test:
|
flutter_test:
|
||||||
@@ -144,7 +145,6 @@ 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.1.0
|
|
||||||
build_runner: ^2.5.4
|
build_runner: ^2.5.4
|
||||||
freezed: ^3.1.0
|
freezed: ^3.1.0
|
||||||
json_serializable: ^6.9.5
|
json_serializable: ^6.9.5
|
||||||
|
Reference in New Issue
Block a user