Compare commits
152 Commits
391604d4a2
...
features/w
| Author | SHA1 | Date | |
|---|---|---|---|
|
983ae2a1fc
|
|||
|
6fc94001b3
|
|||
|
44dbcfdc94
|
|||
|
b57caf56db
|
|||
|
dbcd1b6d36
|
|||
|
a8055de910
|
|||
|
49b15e7674
|
|||
|
e2369c40db
|
|||
|
44c5d91620
|
|||
|
7a5a2407b7
|
|||
|
234434f102
|
|||
|
9c3b228d02
|
|||
|
82682cae9a
|
|||
|
fcbd5fe680
|
|||
|
ad91b17af7
|
|||
|
24fa637329
|
|||
|
926ae5402f
|
|||
|
1a37d384e6
|
|||
|
d4cf598f69
|
|||
|
0106c08891
|
|||
|
9697def808
|
|||
|
6572875229
|
|||
|
66590b9079
|
|||
|
08b9604b55
|
|||
|
0602bbd277
|
|||
|
76e7ba7898
|
|||
|
6e6616b236
|
|||
|
071d51b25e
|
|||
|
a958362461
|
|||
|
6749bb00fe
|
|||
|
11fb20c673
|
|||
|
a7990f83db
|
|||
|
5f4cdf7937
|
|||
|
3330ca14dd
|
|||
|
1719b1c8fe
|
|||
|
3c2c51bfaf
|
|||
|
239d6750ff
|
|||
|
8b0c91977a
|
|||
|
f74cca8464
|
|||
|
08091d51bf
|
|||
|
481190811b
|
|||
|
4b32b65d1c
|
|||
|
50ac7109bb
|
|||
|
62da279c71
|
|||
|
fde6dbf891
|
|||
|
613bf4fb42
|
|||
|
00ae586016
|
|||
|
ea0d132dce
|
|||
|
aa2df1e847
|
|||
|
50672795f3
|
|||
|
383de9568d
|
|||
|
01fa228e45
|
|||
|
1e71ad33a6
|
|||
|
92c0260ecd
|
|||
|
0a161ad255
|
|||
|
c003f27b9a
|
|||
|
19db8309c4
|
|||
|
aa72ce08e8
|
|||
|
4639b00b86
|
|||
|
cc5460ea55
|
|||
|
eafac811e6
|
|||
|
e3be691596
|
|||
|
aa180a1358
|
|||
|
c2707b8af1
|
|||
|
62fd0500f3
|
|||
|
eeae865cc8
|
|||
|
cdf1413fe0
|
|||
|
327b4c04f1
|
|||
|
bd903ce29c
|
|||
|
1b8ecb15ce
|
|||
|
d4e380a97a
|
|||
|
126048b4fa
|
|||
|
8bec18813d
|
|||
|
1ae81794b1
|
|||
|
2a7d12de48
|
|||
|
64c60ead48
|
|||
| 001549b190 | |||
| 4595865ad3 | |||
|
|
1834643167 | ||
|
|
0e816eaa3e | ||
|
|
7c1f24b824 | ||
|
c6594ea2ce
|
|||
|
3bec6e683e
|
|||
|
83e92e2eed
|
|||
|
|
b7d44d96ba | ||
|
a83b929d42
|
|||
|
9423affa75
|
|||
|
cda23db609
|
|||
|
61074bc5a3
|
|||
|
5feafa9255
|
|||
|
e604577c1f
|
|||
|
af0ddd1273
|
|||
|
8a6bb34808
|
|||
|
4ef8445c77
|
|||
|
ec39ad6ca3
|
|||
|
eabb3154f1
|
|||
|
910bf20eef
|
|||
|
5efa9b2ae8
|
|||
|
dd3e39e891
|
|||
|
b6896ded23
|
|||
|
f28a73ff9c
|
|||
|
a014b64235
|
|||
|
7e0e7c20d7
|
|||
|
389fa515ba
|
|||
|
681ead02eb
|
|||
|
8d1c145b0b
|
|||
|
51b4754182
|
|||
|
8a2b321701
|
|||
|
f685a7a249
|
|||
|
76009147e9
|
|||
|
ce12f28e56
|
|||
|
3604373a1e
|
|||
|
9704a4c2c7
|
|||
|
67def56ad1
|
|||
|
1be33916af
|
|||
|
e8ff1bfd22
|
|||
|
3ae56f3d89
|
|||
|
707143e998
|
|||
|
1fd34eb2a3
|
|||
|
d7ca41e946
|
|||
|
ad9fb0719a
|
|||
|
e2d315afd4
|
|||
|
6124dbfd79
|
|||
|
5327f04ec0
|
|||
|
41c56a2319
|
|||
|
f9d033542e
|
|||
|
91784e65e6
|
|||
|
9d39c6a825
|
|||
|
537e49f1a4
|
|||
|
75bbd4df71
|
|||
|
6ef4580d93
|
|||
|
6ffd498761
|
|||
|
27157e7cc1
|
|||
|
bbb07d574a
|
|||
|
c660a419e2
|
|||
|
c3f61467c8
|
|||
|
9bc47df452
|
|||
|
9ef8ca4d45
|
|||
|
b55cbd08d1
|
|||
|
8c6bd0feaa
|
|||
|
7dd4b20628
|
|||
|
fec0cb7640
|
|||
|
75deb04a2b
|
|||
|
7c7ed21a96
|
|||
|
a201f20793
|
|||
|
598c51bc1a
|
|||
|
e1ea61c5f1
|
|||
|
ac424bde36
|
|||
|
b43b70df3f
|
|||
|
4321aa621a
|
|||
|
d5d275fb43
|
|||
|
6bb3307144
|
@@ -75,3 +75,4 @@ dependencies {
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,11 @@
|
||||
"reactionPositive": "Postive",
|
||||
"reactionNegative": "Negative",
|
||||
"reactionNeutral": "Neutral",
|
||||
"customReaction": "Custom Reaction",
|
||||
"customReactions": "Custom Reactions",
|
||||
"stickerPlaceholder": "Sticker Placeholder",
|
||||
"reactionAttitude": "Reaction Attitude",
|
||||
"addReaction": "Add Reaction",
|
||||
"connectionConnected": "Connected",
|
||||
"connectionDisconnected": "Disconnected",
|
||||
"connectionReconnecting": "Reconnecting",
|
||||
@@ -166,8 +171,8 @@
|
||||
"checkInResultLevel3": "Good Luck",
|
||||
"checkInResultLevel4": "Best Luck",
|
||||
"checkInActivityTitle": "{} checked in on {} and got a {}",
|
||||
"eventCalander": "Event Calander",
|
||||
"eventCalanderEmpty": "No events on that day.",
|
||||
"eventCalendar": "Event Calendar",
|
||||
"eventCalendarEmpty": "No events on that day.",
|
||||
"fortuneGraph": "Fortune Trend",
|
||||
"noFortuneData": "No fortune data available for this month.",
|
||||
"creatorHub": "Creator Hub",
|
||||
@@ -474,7 +479,6 @@
|
||||
"accountProfileView": "View Profile",
|
||||
"unspecified": "Unspecified",
|
||||
"added": "Added",
|
||||
"preview": "Preview",
|
||||
"togglePreview": "Toggle Preview",
|
||||
"subscribe": "Subscribe",
|
||||
"unsubscribe": "Unsubscribe",
|
||||
@@ -635,6 +639,10 @@
|
||||
"chatNotJoined": "You have not joined this chat yet.",
|
||||
"chatUnableJoin": "You can't join this chat due to it's access control settings.",
|
||||
"chatJoin": "Join the Chat",
|
||||
"chatReplyingTo": "Replying to {}",
|
||||
"chatForwarding": "Forwarding message",
|
||||
"chatEditing": "Editing message",
|
||||
"chatNoContent": "No content",
|
||||
"realmJoin": "Join the Realm",
|
||||
"realmJoinSuccess": "Successfully joined the realm.",
|
||||
"search": "Search",
|
||||
@@ -863,6 +871,7 @@
|
||||
"pollShortTextAnswerPreview": "Short text answer (preview)",
|
||||
"award": "Award",
|
||||
"awardPost": "Award Post",
|
||||
"awardPoints": "Awarded {} points",
|
||||
"awardMessage": "Message",
|
||||
"awardMessageHint": "Enter your award message...",
|
||||
"awardAttitude": "Attitude",
|
||||
@@ -1103,6 +1112,9 @@
|
||||
"openReleasePage": "Open release page",
|
||||
"postCompose": "Compose Post",
|
||||
"postPublish": "Publish Post",
|
||||
"restoreDraftTitle": "Restore Draft",
|
||||
"restoreDraftMessage": "A draft was found. Do you want to restore it?",
|
||||
"draft": "Draft",
|
||||
"purchaseGift": "Purchase Gift",
|
||||
"selectRecipient": "Select Recipient",
|
||||
"changeRecipient": "Change Recipient",
|
||||
@@ -1208,5 +1220,87 @@
|
||||
"enterPinToConfirmTransfer": "Enter your 6-digit PIN to confirm transfer",
|
||||
"transferCreatedSuccessfully": "Transfer created successfully!",
|
||||
"postUpdate": "Update",
|
||||
"fileMetadata": "File Metadata"
|
||||
"fileMetadata": "File Metadata",
|
||||
"resend": "Resend",
|
||||
"fileInfoTitle": "File Information",
|
||||
"download": "Download",
|
||||
"info": "Info",
|
||||
"noStickers": "No Stickers",
|
||||
"noStickersInPack": "This pack does not contains stickers",
|
||||
"noStickerPacks": "No Sticker Packs",
|
||||
"refresh": "Refresh",
|
||||
"spoiler": "Spoiler",
|
||||
"activityHeatmap": "Activity Heatmap",
|
||||
"custom": "Custom",
|
||||
"usernameColor": "Username Color",
|
||||
"colorType": "Color Type",
|
||||
"plain": "Plain",
|
||||
"gradient": "Gradient",
|
||||
"colorValue": "Color Value",
|
||||
"gradientDirection": "Gradient Direction",
|
||||
"gradientDirectionToRight": "To Right",
|
||||
"gradientDirectionToLeft": "To Left",
|
||||
"gradientDirectionToBottom": "To Bottom",
|
||||
"gradientDirectionToTop": "To Top",
|
||||
"gradientDirectionToBottomRight": "To Bottom Right",
|
||||
"gradientDirectionToBottomLeft": "To Bottom Left",
|
||||
"gradientDirectionToTopRight": "To Top Right",
|
||||
"gradientDirectionToTopLeft": "To Top Left",
|
||||
"gradientColors": "Gradient Colors",
|
||||
"color": "Color",
|
||||
"addColor": "Add Color",
|
||||
"preview": "Preview",
|
||||
"availableWithYourPlan": "Available with your plan",
|
||||
"upgradeRequired": "Upgrade required",
|
||||
"settingsDisableAnimation": "Disable Animation",
|
||||
"addTag": "Add Tag",
|
||||
"postFeaturedOn": "Post featured on {}",
|
||||
"messageSentAt": "Sent at {}",
|
||||
"myTickets": "My Tickets",
|
||||
"drawHistory": "Draw History",
|
||||
"lottery": "Lottery",
|
||||
"noLotteryTickets": "No lottery tickets yet",
|
||||
"buyYourFirstTicket": "Buy your first lottery ticket to get started!",
|
||||
"buyTicket": "Buy Ticket",
|
||||
"ticketNumbers": "Numbers: {}, Special: {}",
|
||||
"cost": "Cost",
|
||||
"multiplier": "Multiplier",
|
||||
"prizeWon": "Prize Won",
|
||||
"pending": "Pending",
|
||||
"drawn": "Drawn",
|
||||
"won": "Won",
|
||||
"lost": "Lost",
|
||||
"noDrawHistory": "No draw history yet",
|
||||
"buyLotteryTicket": "Buy Lottery Ticket",
|
||||
"selectNumbers": "Select Numbers",
|
||||
"select5UniqueNumbers": "Select 5 unique numbers",
|
||||
"selectSpecialNumber": "Select Special Number",
|
||||
"selectMultiplier": "Select Multiplier",
|
||||
"baseCost": "Base Cost",
|
||||
"totalCost": "Total Cost",
|
||||
"prizeStructure": "Prize Structure",
|
||||
"enterPinToConfirmPurchase": "Enter your PIN to confirm purchase",
|
||||
"ticketPurchasedSuccessfully": "Ticket purchased successfully!",
|
||||
"winningNumbers": "Winning Numbers",
|
||||
"specialNumber": "Special Number",
|
||||
"totalTickets": "Total Tickets",
|
||||
"totalWinners": "Total Winners",
|
||||
"prizePool": "Prize Pool",
|
||||
"enterPinToConfirmPayment": "Enter your PIN code to confirm payment",
|
||||
"purchase": "Purchase",
|
||||
"multiplierLabel": "Multiplier",
|
||||
"specialOnly": "Special Only",
|
||||
"matches": "Matches",
|
||||
"thoughtDefaultTopic": "Reflection",
|
||||
"thoughtAiName": "SN-chan",
|
||||
"thoughtUserName": "You",
|
||||
"thoughtStreamingHint": "Sn-chan is thinking...",
|
||||
"thoughtInputHint": "Ask sn-chan anything...",
|
||||
"thoughtNewConversation": "Start New Conversation",
|
||||
"thoughtParseError": "Failed to parse AI response",
|
||||
"thoughtFunctionCall": "Function Call",
|
||||
"aiThought": "AI Thought",
|
||||
"aiThoughtTitle": "Let sn-chan think",
|
||||
"postReferenceUnavailable": "Referenced post is unavailable",
|
||||
"fabLocation": "FAB Location"
|
||||
}
|
||||
|
||||
@@ -940,7 +940,7 @@
|
||||
"editBot": "编辑机器人",
|
||||
"botAutomatedBy": "由 {} 自动化",
|
||||
"botDetails": "机器人详情",
|
||||
"overview": "总揽",
|
||||
"overview": "总览",
|
||||
"keys": "密钥",
|
||||
"botNotFound": "机器人未找到。",
|
||||
"newBotKey": "新建密钥",
|
||||
@@ -1060,7 +1060,7 @@
|
||||
"selectPool": "选择储存池",
|
||||
"choosePool": "选择一个储存池",
|
||||
"errorLoadingPools": "加载池时出错",
|
||||
"quotaCostInfo": "此上传将消耗{} 配额点",
|
||||
"quotaCostInfo": "此上传将消耗 {} 配额点",
|
||||
"uploadConstraints": "上传限制",
|
||||
"fileSizeExceeded": "文件大小超过了 {} 的最大限制",
|
||||
"fileTypeNotAccepted": "此储存池不接受该文件类型",
|
||||
@@ -1076,5 +1076,19 @@
|
||||
"recycledFilesDeleted": "被回收文件成功删除",
|
||||
"failedToDeleteRecycledFiles": "删除被回收文件失败",
|
||||
"upload": "上传",
|
||||
"systemWallet": "中央统筹"
|
||||
"systemWallet": "中央统筹",
|
||||
"postCompose": "撰写帖子",
|
||||
"postPublish": "发布帖子",
|
||||
"restoreDraftTitle": "恢复草稿",
|
||||
"restoreDraftMessage": "发现了一个草稿。你想要恢复它吗?",
|
||||
"draft": "草稿",
|
||||
"thoughtDefaultTopic": "寻思",
|
||||
"thoughtAiName": "SN 酱",
|
||||
"thoughtUserName": "您",
|
||||
"thoughtStreamingHint": "SN 酱正在思考...",
|
||||
"thoughtInputHint": "问 SN 酱任何问题...",
|
||||
"thoughtNewConversation": "开始新对话",
|
||||
"thoughtParseError": "解析 AI 响应失败",
|
||||
"aiThought": "寻思",
|
||||
"aiThoughtTitle": "让 SN 酱寻思寻思"
|
||||
}
|
||||
@@ -1075,5 +1075,7 @@
|
||||
"deleteRecycledFiles": "刪除已回收檔案",
|
||||
"recycledFilesDeleted": "已回收檔案刪除成功",
|
||||
"failedToDeleteRecycledFiles": "已回收檔案刪除失敗",
|
||||
"upload": "上傳"
|
||||
"upload": "上傳",
|
||||
"postCompose": "撰寫帖子",
|
||||
"postPublish": "發佈帖子"
|
||||
}
|
||||
15
ios/Podfile
15
ios/Podfile
@@ -1,6 +1,3 @@
|
||||
# Uncomment this line to define a global platform for your project
|
||||
platform :ios, '15.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
@@ -28,6 +25,8 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe
|
||||
flutter_ios_podfile_setup
|
||||
|
||||
target 'Runner' do
|
||||
platform :ios, '15.0'
|
||||
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
@@ -50,6 +49,16 @@ target 'Runner' do
|
||||
end
|
||||
end
|
||||
|
||||
target 'WatchRunner Watch App' do
|
||||
platform :watchos, '11.0'
|
||||
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
pod 'Kingfisher', '~> 8.0'
|
||||
pod 'KingfisherWebP'
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
|
||||
181
ios/Podfile.lock
181
ios/Podfile.lock
@@ -44,83 +44,83 @@ PODS:
|
||||
- Flutter
|
||||
- file_saver (0.0.1):
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- Firebase/Crashlytics (12.2.0):
|
||||
- Firebase/CoreOnly (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- Firebase/Crashlytics (12.4.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseCrashlytics (~> 12.2.0)
|
||||
- Firebase/Messaging (12.2.0):
|
||||
- FirebaseCrashlytics (~> 12.4.0)
|
||||
- Firebase/Messaging (12.4.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 12.2.0)
|
||||
- firebase_analytics (12.0.2):
|
||||
- FirebaseMessaging (~> 12.4.0)
|
||||
- firebase_analytics (12.0.3):
|
||||
- firebase_core
|
||||
- FirebaseAnalytics (= 12.2.0)
|
||||
- FirebaseAnalytics (= 12.4.0)
|
||||
- Flutter
|
||||
- firebase_core (4.1.1):
|
||||
- Firebase/CoreOnly (= 12.2.0)
|
||||
- firebase_core (4.2.0):
|
||||
- Firebase/CoreOnly (= 12.4.0)
|
||||
- Flutter
|
||||
- firebase_crashlytics (5.0.2):
|
||||
- Firebase/Crashlytics (= 12.2.0)
|
||||
- firebase_crashlytics (5.0.3):
|
||||
- Firebase/Crashlytics (= 12.4.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_messaging (16.0.2):
|
||||
- Firebase/Messaging (= 12.2.0)
|
||||
- firebase_messaging (16.0.3):
|
||||
- Firebase/Messaging (= 12.4.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseAnalytics (12.2.0):
|
||||
- FirebaseAnalytics/Default (= 12.2.0)
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- FirebaseAnalytics (12.4.0):
|
||||
- FirebaseAnalytics/Default (= 12.4.0)
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseAnalytics/Default (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- GoogleAppMeasurement/Default (= 12.2.0)
|
||||
- FirebaseAnalytics/Default (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleAppMeasurement/Default (= 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseCore (12.2.0):
|
||||
- FirebaseCoreInternal (~> 12.2.0)
|
||||
- FirebaseCore (12.4.0):
|
||||
- FirebaseCoreInternal (~> 12.4.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreExtension (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseCoreInternal (12.2.0):
|
||||
- FirebaseCoreExtension (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseCoreInternal (12.4.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- FirebaseCrashlytics (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- FirebaseRemoteConfigInterop (~> 12.2.0)
|
||||
- FirebaseSessions (~> 12.2.0)
|
||||
- FirebaseCrashlytics (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- FirebaseRemoteConfigInterop (~> 12.4.0)
|
||||
- FirebaseSessions (~> 12.4.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseInstallations (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseMessaging (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- FirebaseMessaging (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Reachability (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseRemoteConfigInterop (12.2.0)
|
||||
- FirebaseSessions (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseCoreExtension (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- FirebaseRemoteConfigInterop (12.4.0)
|
||||
- FirebaseSessions (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseCoreExtension (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
@@ -157,27 +157,28 @@ PODS:
|
||||
- gal (1.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- GoogleAdsOnDeviceConversion (2.3.0):
|
||||
- GoogleAdsOnDeviceConversion (3.1.0):
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Core (12.2.0):
|
||||
- GoogleAppMeasurement/Core (12.4.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Default (12.2.0):
|
||||
- GoogleAdsOnDeviceConversion (= 2.3.0)
|
||||
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (= 12.2.0)
|
||||
- GoogleAppMeasurement/Default (12.4.0):
|
||||
- GoogleAdsOnDeviceConversion (~> 3.1.0)
|
||||
- GoogleAppMeasurement/Core (= 12.4.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (= 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (12.2.0):
|
||||
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (12.4.0):
|
||||
- GoogleAppMeasurement/Core (= 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
@@ -217,8 +218,23 @@ PODS:
|
||||
- Flutter
|
||||
- irondash_engine_context (0.0.1):
|
||||
- Flutter
|
||||
- Kingfisher (8.5.0)
|
||||
- livekit_client (2.5.0):
|
||||
- Kingfisher (8.6.0)
|
||||
- KingfisherWebP (1.7.2):
|
||||
- Kingfisher (~> 8.0)
|
||||
- libwebp (>= 1.1.0)
|
||||
- libwebp (1.5.0):
|
||||
- libwebp/demux (= 1.5.0)
|
||||
- libwebp/mux (= 1.5.0)
|
||||
- libwebp/sharpyuv (= 1.5.0)
|
||||
- libwebp/webp (= 1.5.0)
|
||||
- libwebp/demux (1.5.0):
|
||||
- libwebp/webp
|
||||
- libwebp/mux (1.5.0):
|
||||
- libwebp/demux
|
||||
- libwebp/sharpyuv (1.5.0)
|
||||
- libwebp/webp (1.5.0):
|
||||
- libwebp/sharpyuv
|
||||
- livekit_client (2.5.3):
|
||||
- Flutter
|
||||
- flutter_webrtc
|
||||
- WebRTC-SDK (= 137.7151.04)
|
||||
@@ -254,9 +270,9 @@ PODS:
|
||||
- record_ios (1.1.0):
|
||||
- Flutter
|
||||
- SAMKeychain (1.5.3)
|
||||
- SDWebImage (5.21.2):
|
||||
- SDWebImage/Core (= 5.21.2)
|
||||
- SDWebImage/Core (5.21.2)
|
||||
- SDWebImage (5.21.3):
|
||||
- SDWebImage/Core (= 5.21.3)
|
||||
- SDWebImage/Core (5.21.3)
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
@@ -332,6 +348,7 @@ DEPENDENCIES:
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
|
||||
- Kingfisher (~> 8.0)
|
||||
- KingfisherWebP
|
||||
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
||||
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||
@@ -374,6 +391,8 @@ SPEC REPOS:
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- Kingfisher
|
||||
- KingfisherWebP
|
||||
- libwebp
|
||||
- nanopb
|
||||
- OrderedSet
|
||||
- PromisesObjC
|
||||
@@ -486,20 +505,20 @@ SPEC CHECKSUMS:
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
|
||||
firebase_analytics: 8c78ce6224e0623152379d6cc7ef3d9098477b7e
|
||||
firebase_core: dfc4bd142bee4bc53a5d482397ca322c2dd3165d
|
||||
firebase_crashlytics: e55dcf895eed0dd87c447dd5aff8db7f1bb8bbdb
|
||||
firebase_messaging: 38c66c1184695b0c87abe51d40fc590718abed1a
|
||||
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
|
||||
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
|
||||
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5
|
||||
FirebaseCoreInternal: 56ea29f3dad2894f81b060f706f9d53509b6ed3b
|
||||
FirebaseCrashlytics: f83cbf176d5c637ade108c0aacf1ccbd5ec499bf
|
||||
FirebaseInstallations: 3e884b01feabdf67582a80f3250425a00979b4ed
|
||||
FirebaseMessaging: 43ec73bbfedd0c385a849bb91593ab4ad4b9e48e
|
||||
FirebaseRemoteConfigInterop: 0896fd52ab72586a355c8f389ff85aaa9e5375e1
|
||||
FirebaseSessions: f4692789e770bec66ce17d772c0e9561c4f11737
|
||||
Firebase: f07b15ae5a6ec0f93713e30b923d9970d144af3e
|
||||
firebase_analytics: 1d024068b1d4707d5ba7a42a12976ddf3316d835
|
||||
firebase_core: 744984dbbed8b3036abf34f0b98d80f130a7e464
|
||||
firebase_crashlytics: f3a9a4338ab99b67042f64e9e22e1bf349cb44ed
|
||||
firebase_messaging: 82c70650c426a0a14873e1acdb9ec2b443c4e8b4
|
||||
FirebaseAnalytics: 0fc2b20091f0ddd21bf73397cf8f0eb5346dc24f
|
||||
FirebaseCore: bb595f3114953664e3c1dc032f008a244147cfd3
|
||||
FirebaseCoreExtension: 7e1f7118ee970e001a8013719fb90950ee5e0018
|
||||
FirebaseCoreInternal: d7f5a043c2cd01a08103ab586587c1468047bca6
|
||||
FirebaseCrashlytics: a6ece278a837c7e88de2d9b5da0a3542f2342395
|
||||
FirebaseInstallations: ae9f4902cb5bf1d0c5eaa31ec1f4e5495a0714e2
|
||||
FirebaseMessaging: d33971b7bb252745ea6cd31ab190d1a1df4b8ed5
|
||||
FirebaseRemoteConfigInterop: 1e31ec72b89c9924367c59bfb5ec9ab60d1d6766
|
||||
FirebaseSessions: ba7c7a7ca8696a8d540eb3fe3800fbe98c79786d
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
@@ -512,14 +531,16 @@ SPEC CHECKSUMS:
|
||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||
flutter_webrtc: c3e21fc0dcd9d8eb246ae4d5256fcbeb2f5ecd22
|
||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||
GoogleAdsOnDeviceConversion: 9090c435cde08903e8dd1ba2c77fbec9e46d9afe
|
||||
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
|
||||
GoogleAdsOnDeviceConversion: e03a386840803ea7eef3fd22a061930142c039c1
|
||||
GoogleAppMeasurement: 1e718274b7e015cefd846ac1fcf7820c70dc017d
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
||||
livekit_client: a6f5fa86ac28ccd7ded53626a5379961db311ab4
|
||||
Kingfisher: 64278f126a815d0e2d391cdf71311b85882c4de0
|
||||
KingfisherWebP: 38b9721821947f547afb78f933f75f4f9e0ae402
|
||||
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
|
||||
livekit_client: 86c8af579274e4b7a215185a8080db2d4e176f40
|
||||
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
@@ -528,16 +549,16 @@ SPEC CHECKSUMS:
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
pointer_interceptor_ios: ec847ef8b0915778bed2b2cef636f4d177fa8eed
|
||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||
pointer_interceptor_ios: da06a662d5bfd329602b45b2ab41bc0fb5fdb0f0
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
|
||||
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
|
||||
@@ -545,11 +566,11 @@ SPEC CHECKSUMS:
|
||||
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
syncfusion_flutter_pdfviewer: 90dc48305d2e33d4aa20681d1e98ddeda891bc14
|
||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||
WebRTC-SDK: 40d4f5ba05cadff14e4db5614aec402a633f007e
|
||||
|
||||
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
||||
PODFILE CHECKSUM: 3096dc559be56aca856e757e1dc65ca039801e2e
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
archiveVersion = 1;
|
||||
classes = {
|
||||
};
|
||||
objectVersion = 54;
|
||||
objectVersion = 77;
|
||||
objects = {
|
||||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
7310A7DF2EB10963002C0FD3 /* WatchRunner Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
73ACDFAD2E3D0E6100B63535 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */; };
|
||||
73ACDFC32E3D0E6100B63535 /* SolianBroadcastExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
@@ -20,6 +21,7 @@
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
A1D34487886D362AC8B99B2E /* Pods_WatchRunner_Watch_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 802C1CFCA7F1E069AAEFB454 /* Pods_WatchRunner_Watch_App.framework */; };
|
||||
B87C0E607033790E71B54D73 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D834CA86410B09796B312B /* Pods_Runner.framework */; };
|
||||
D174D53FF3E8EA943491A5CC /* Pods_SolianShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */; };
|
||||
D1772CE196985AE8E8C9F2E5 /* Pods_SolianNotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */; };
|
||||
@@ -58,6 +60,17 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
7310A7DE2EB10963002C0FD3 /* Embed Watch Content */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
7310A7DF2EB10963002C0FD3 /* WatchRunner Watch App.app in Embed Watch Content */,
|
||||
);
|
||||
name = "Embed Watch Content";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -84,6 +97,7 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.profile.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
14118AC858B441AB16B7309E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
@@ -100,6 +114,7 @@
|
||||
39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianNotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3A1C47BD29CC6AC2587D4DBE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "WatchRunner Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
|
||||
@@ -111,6 +126,8 @@
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
802C1CFCA7F1E069AAEFB454 /* Pods_WatchRunner_Watch_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WatchRunner_Watch_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.debug.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
8B40620B1EEBB09456406A3C /* Pods-SolianNotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.profile.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
@@ -120,6 +137,7 @@
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9AE244813FCDFAA941430393 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.release.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.release.xcconfig"; sourceTree = "<group>"; };
|
||||
A499FDB2082EB000933AA8C5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-SolianShareExtension/Pods-SolianShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
@@ -162,6 +180,11 @@
|
||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
7310A7D52EB10962002C0FD3 /* WatchRunner Watch App */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
path = "WatchRunner Watch App";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
73268D272DEB012A0076E970 /* Services */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
@@ -205,6 +228,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7310A7D12EB10962002C0FD3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
A1D34487886D362AC8B99B2E /* Pods_WatchRunner_Watch_App.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73ACDFA82E3D0E6100B63535 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -258,6 +289,7 @@
|
||||
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */,
|
||||
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */,
|
||||
73ACDFB82E3D0E6100B63535 /* UIKit.framework */,
|
||||
802C1CFCA7F1E069AAEFB454 /* Pods_WatchRunner_Watch_App.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -280,6 +312,9 @@
|
||||
17FAB080A9C53193ABD9C15B /* Pods-SolianShareExtension.debug.xcconfig */,
|
||||
27C66EFB5A705F1A822C3EB0 /* Pods-SolianShareExtension.release.xcconfig */,
|
||||
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */,
|
||||
86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */,
|
||||
A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */,
|
||||
103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@@ -303,6 +338,7 @@
|
||||
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
||||
73C305CF2E0BE878009035B9 /* SolianShareExtension */,
|
||||
73ACDFAE2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||
7310A7D52EB10962002C0FD3 /* WatchRunner Watch App */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
91E124CE95BCB4DCD890160D /* Pods */,
|
||||
@@ -319,6 +355,7 @@
|
||||
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */,
|
||||
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */,
|
||||
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */,
|
||||
7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -363,6 +400,28 @@
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
7310A7D32EB10962002C0FD3 /* WatchRunner Watch App */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7310A7E32EB10963002C0FD3 /* Build configuration list for PBXNativeTarget "WatchRunner Watch App" */;
|
||||
buildPhases = (
|
||||
DDEDA1BA6278B94F0F7B9B61 /* [CP] Check Pods Manifest.lock */,
|
||||
7310A7D02EB10962002C0FD3 /* Sources */,
|
||||
7310A7D12EB10962002C0FD3 /* Frameworks */,
|
||||
7310A7D22EB10962002C0FD3 /* Resources */,
|
||||
C74B07D6587D29C67A198025 /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
7310A7D52EB10962002C0FD3 /* WatchRunner Watch App */,
|
||||
);
|
||||
name = "WatchRunner Watch App";
|
||||
productName = "WatchRunner Watch App";
|
||||
productReference = 7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */;
|
||||
@@ -434,6 +493,7 @@
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */,
|
||||
7310A7DE2EB10963002C0FD3 /* Embed Watch Content */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
@@ -463,7 +523,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 1640;
|
||||
LastSwiftUpdateCheck = 2600;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
@@ -471,6 +531,9 @@
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
7310A7D32EB10962002C0FD3 = {
|
||||
CreatedOnToolsVersion = 26.0.1;
|
||||
};
|
||||
73ACDFAA2E3D0E6100B63535 = {
|
||||
CreatedOnToolsVersion = 16.4;
|
||||
};
|
||||
@@ -504,6 +567,7 @@
|
||||
73CDD6792DEC00480059D95D /* SolianNotificationService */,
|
||||
73C305CD2E0BE878009035B9 /* SolianShareExtension */,
|
||||
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||
7310A7D32EB10962002C0FD3 /* WatchRunner Watch App */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -516,6 +580,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7310A7D22EB10962002C0FD3 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73ACDFA92E3D0E6100B63535 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -598,10 +669,14 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
@@ -659,10 +734,14 @@
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
@@ -683,6 +762,49 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
C74B07D6587D29C67A198025 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
DDEDA1BA6278B94F0F7B9B61 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||
"${PODS_ROOT}/Manifest.lock",
|
||||
);
|
||||
name = "[CP] Check Pods Manifest.lock";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-WatchRunner Watch App-checkManifestLockResult.txt",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E86CDE9D6464F4F52B910856 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -734,6 +856,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7310A7D02EB10962002C0FD3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73ACDFA72E3D0E6100B63535 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -943,6 +1072,144 @@
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
7310A7E02EB10963002C0FD3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = WatchRunner;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.watchkitapp;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7310A7E12EB10963002C0FD3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = WatchRunner;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.watchkitapp;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
7310A7E22EB10963002C0FD3 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||
ENABLE_PREVIEWS = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = WatchRunner;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
MTL_FAST_MATH = YES;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.watchkitapp;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SDKROOT = watchos;
|
||||
SKIP_INSTALL = YES;
|
||||
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = 4;
|
||||
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
73ACDFC42E3D0E6100B63535 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -1487,6 +1754,16 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
7310A7E32EB10963002C0FD3 /* Build configuration list for PBXNativeTarget "WatchRunner Watch App" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7310A7E02EB10963002C0FD3 /* Debug */,
|
||||
7310A7E12EB10963002C0FD3 /* Release */,
|
||||
7310A7E22EB10963002C0FD3 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
import WatchConnectivity
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
let notifyDelegate = NotifyDelegate()
|
||||
private var watchConnectivityService: WatchConnectivityService?
|
||||
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
@@ -28,6 +30,55 @@ import UIKit
|
||||
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
|
||||
if WCSession.isSupported() {
|
||||
watchConnectivityService = WatchConnectivityService()
|
||||
}
|
||||
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
||||
|
||||
class WatchConnectivityService: NSObject, WCSessionDelegate {
|
||||
private let session: WCSession
|
||||
|
||||
override init() {
|
||||
self.session = .default
|
||||
super.init()
|
||||
print("[iOS] Activating WCSession")
|
||||
self.session.delegate = self
|
||||
self.session.activate()
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
|
||||
if let error = error {
|
||||
print("[iOS] WCSession activation failed with error: \(error.localizedDescription)")
|
||||
return
|
||||
}
|
||||
print("[iOS] WCSession activated with state: \(activationState.rawValue)")
|
||||
}
|
||||
|
||||
func sessionDidBecomeInactive(_ session: WCSession) {}
|
||||
|
||||
func sessionDidDeactivate(_ session: WCSession) {
|
||||
session.activate()
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
|
||||
print("[iOS] Received message: \(message)")
|
||||
if let request = message["request"] as? String, request == "data" {
|
||||
let token = UserDefaults.standard.getFlutterToken()
|
||||
let serverUrl = UserDefaults.standard.getServerUrl()
|
||||
|
||||
print("[iOS] Retrieved token: \(token ?? "nil")")
|
||||
print("[iOS] Retrieved serverUrl: \(serverUrl)")
|
||||
|
||||
var data: [String: Any] = ["serverUrl": serverUrl]
|
||||
if let token = token {
|
||||
data["token"] = token
|
||||
}
|
||||
|
||||
print("[iOS] Replying with data: \(data)")
|
||||
replyHandler(data)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1 +1,334 @@
|
||||
{"images":[{"size":"20x20","idiom":"universal","filename":"Icon-App-20x20@2x.png","scale":"2x","platform":"ios"},{"size":"20x20","idiom":"universal","filename":"Icon-App-20x20@3x.png","scale":"3x","platform":"ios"},{"size":"29x29","idiom":"universal","filename":"Icon-App-29x29@2x.png","scale":"2x","platform":"ios"},{"size":"29x29","idiom":"universal","filename":"Icon-App-29x29@3x.png","scale":"3x","platform":"ios"},{"size":"38x38","idiom":"universal","filename":"Icon-App-38x38@2x.png","scale":"2x","platform":"ios"},{"size":"38x38","idiom":"universal","filename":"Icon-App-38x38@3x.png","scale":"3x","platform":"ios"},{"size":"40x40","idiom":"universal","filename":"Icon-App-40x40@2x.png","scale":"2x","platform":"ios"},{"size":"40x40","idiom":"universal","filename":"Icon-App-40x40@3x.png","scale":"3x","platform":"ios"},{"size":"60x60","idiom":"universal","filename":"Icon-App-60x60@2x.png","scale":"2x","platform":"ios"},{"size":"60x60","idiom":"universal","filename":"Icon-App-60x60@3x.png","scale":"3x","platform":"ios"},{"size":"64x64","idiom":"universal","filename":"Icon-App-64x64@2x.png","scale":"2x","platform":"ios"},{"size":"64x64","idiom":"universal","filename":"Icon-App-64x64@3x.png","scale":"3x","platform":"ios"},{"size":"68x68","idiom":"universal","filename":"Icon-App-68x68@2x.png","scale":"2x","platform":"ios"},{"size":"76x76","idiom":"universal","filename":"Icon-App-76x76@2x.png","scale":"2x","platform":"ios"},{"size":"83.5x83.5","idiom":"universal","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x","platform":"ios"},{"size":"1024x1024","idiom":"universal","filename":"Icon-App-1024x1024@1x.png","scale":"1x","platform":"ios"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"},{"size":"20x20","idiom":"universal","filename":"Icon-App-Dark-20x20@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"20x20","idiom":"universal","filename":"Icon-App-Dark-20x20@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"29x29","idiom":"universal","filename":"Icon-App-Dark-29x29@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"29x29","idiom":"universal","filename":"Icon-App-Dark-29x29@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"38x38","idiom":"universal","filename":"Icon-App-Dark-38x38@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"38x38","idiom":"universal","filename":"Icon-App-Dark-38x38@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"40x40","idiom":"universal","filename":"Icon-App-Dark-40x40@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"40x40","idiom":"universal","filename":"Icon-App-Dark-40x40@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"60x60","idiom":"universal","filename":"Icon-App-Dark-60x60@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"60x60","idiom":"universal","filename":"Icon-App-Dark-60x60@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"64x64","idiom":"universal","filename":"Icon-App-Dark-64x64@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"64x64","idiom":"universal","filename":"Icon-App-Dark-64x64@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"68x68","idiom":"universal","filename":"Icon-App-Dark-68x68@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"76x76","idiom":"universal","filename":"Icon-App-Dark-76x76@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"83.5x83.5","idiom":"universal","filename":"Icon-App-Dark-83.5x83.5@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"1024x1024","idiom":"universal","filename":"Icon-App-Dark-1024x1024@1x.png","scale":"1x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]}],"info":{"version":1,"author":"xcode"}}
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Icon-App-20x20@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-20x20@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-29x29@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-29x29@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-38x38@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "38x38"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-38x38@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "38x38"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-40x40@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-40x40@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-60x60@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-60x60@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-64x64@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "64x64"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-64x64@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "64x64"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-68x68@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "68x68"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-76x76@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-20x20@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-20x20@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-29x29@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-29x29@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-38x38@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "38x38"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-38x38@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "38x38"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-40x40@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-40x40@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-60x60@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-60x60@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-64x64@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "64x64"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-64x64@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "64x64"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-68x68@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "68x68"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-76x76@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-83.5x83.5@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"appearances" : [
|
||||
{
|
||||
"appearance" : "luminosity",
|
||||
"value" : "dark"
|
||||
}
|
||||
],
|
||||
"filename" : "Icon-App-Dark-1024x1024@1x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"idiom" : "ios-marketing",
|
||||
"scale" : "1x",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 295 B |
Binary file not shown.
|
Before Width: | Height: | Size: 282 B |
Binary file not shown.
|
Before Width: | Height: | Size: 406 B |
Binary file not shown.
|
Before Width: | Height: | Size: 762 B |
@@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
|
||||
func getAttachmentUrl(for identifier: String) -> String {
|
||||
let serverBaseUrl = "https://api.solian.app"
|
||||
let serverBaseUrl = UserDefaults.standard.getServerUrl()
|
||||
|
||||
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/drive/files/\(identifier)"
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ extension UserDefaults {
|
||||
}
|
||||
|
||||
func getServerUrl(forKey key: String = "app_server_url") -> String {
|
||||
return self.getFlutterValue(forKey: key) ?? "https://nt.solian.app"
|
||||
return self.getFlutterValue(forKey: key) ?? "https://api.solian.app"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,15 +85,8 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
customIdentifier: nil
|
||||
)
|
||||
|
||||
let intent = self.createMessageIntent(with: sender, meta: metaCopy, body: content.body)
|
||||
self.donateInteraction(for: intent)
|
||||
let updatedContent = try? request.content.updating(from: intent)
|
||||
content.categoryIdentifier = "CHAT_MESSAGE"
|
||||
if let updatedContent = updatedContent {
|
||||
self.contentHandler?(updatedContent)
|
||||
} else {
|
||||
self.contentHandler?(content)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"platform" : "universal",
|
||||
"reference" : "systemIndigoColor"
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "Icon-App-1024x1024@1x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
Binary file not shown.
|
After Width: | Height: | Size: 48 KiB |
6
ios/WatchRunner Watch App/Assets.xcassets/Contents.json
Normal file
6
ios/WatchRunner Watch App/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
50
ios/WatchRunner Watch App/ContentView.swift
Normal file
50
ios/WatchRunner Watch App/ContentView.swift
Normal file
@@ -0,0 +1,50 @@
|
||||
//
|
||||
// ContentView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/28.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// The root view of the app.
|
||||
struct ContentView: View {
|
||||
@StateObject private var appState = AppState()
|
||||
@State private var selection: Panel? = .explore
|
||||
|
||||
enum Panel: Hashable {
|
||||
case explore
|
||||
case chat
|
||||
case notifications
|
||||
case account
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationSplitView {
|
||||
List(selection: $selection) {
|
||||
Label("Explore", systemImage: "globe").tag(Panel.explore)
|
||||
Label("Chat", systemImage: "message").tag(Panel.chat)
|
||||
Label("Notifications", systemImage: "bell").tag(Panel.notifications)
|
||||
Label("Account", systemImage: "person.circle").tag(Panel.account)
|
||||
}
|
||||
.listStyle(.automatic)
|
||||
} detail: {
|
||||
switch selection {
|
||||
case .explore:
|
||||
ExploreView()
|
||||
.environmentObject(appState)
|
||||
case .chat:
|
||||
ChatView()
|
||||
.environmentObject(appState)
|
||||
case .notifications:
|
||||
NotificationView()
|
||||
.environmentObject(appState)
|
||||
case .account:
|
||||
AccountView()
|
||||
.environmentObject(appState)
|
||||
case .none:
|
||||
Text("Select a panel")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
88
ios/WatchRunner Watch App/Layouts/FlowLayout.swift
Normal file
88
ios/WatchRunner Watch App/Layouts/FlowLayout.swift
Normal file
@@ -0,0 +1,88 @@
|
||||
//
|
||||
// FlowLayout.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Custom Layouts
|
||||
|
||||
struct FlowLayout: Layout {
|
||||
var alignment: HorizontalAlignment = .leading
|
||||
var spacing: CGFloat = 10
|
||||
|
||||
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
|
||||
let containerWidth = proposal.width ?? 0
|
||||
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
|
||||
|
||||
var currentX: CGFloat = 0
|
||||
var currentY: CGFloat = 0
|
||||
var lineHeight: CGFloat = 0
|
||||
var totalHeight: CGFloat = 0
|
||||
|
||||
for size in sizes {
|
||||
if currentX + size.width > containerWidth {
|
||||
// New line
|
||||
currentX = 0
|
||||
currentY += lineHeight + spacing
|
||||
totalHeight = currentY + size.height
|
||||
lineHeight = 0
|
||||
}
|
||||
|
||||
currentX += size.width + spacing
|
||||
lineHeight = max(lineHeight, size.height)
|
||||
}
|
||||
totalHeight = currentY + lineHeight
|
||||
|
||||
return CGSize(width: containerWidth, height: totalHeight)
|
||||
}
|
||||
|
||||
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
|
||||
let containerWidth = bounds.width
|
||||
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
|
||||
|
||||
var currentX: CGFloat = 0
|
||||
var currentY: CGFloat = 0
|
||||
var lineHeight: CGFloat = 0
|
||||
var lineElements: [(offset: Int, size: CGSize)] = []
|
||||
|
||||
func placeLine() {
|
||||
let lineWidth = lineElements.map { $0.size.width }.reduce(0, +) + CGFloat(lineElements.count - 1) * spacing
|
||||
var startX: CGFloat = 0
|
||||
switch alignment {
|
||||
case .leading:
|
||||
startX = bounds.minX
|
||||
case .center:
|
||||
startX = bounds.minX + (containerWidth - lineWidth) / 2
|
||||
case .trailing:
|
||||
startX = bounds.maxX - lineWidth
|
||||
default:
|
||||
startX = bounds.minX
|
||||
}
|
||||
|
||||
var xOffset = startX
|
||||
for (offset, size) in lineElements {
|
||||
subviews[offset].place(at: CGPoint(x: xOffset, y: bounds.minY + currentY), proposal: ProposedViewSize(size)) // Use bounds.minY + currentY
|
||||
xOffset += size.width + spacing
|
||||
}
|
||||
lineElements.removeAll() // Clear elements for the next line
|
||||
}
|
||||
|
||||
for (offset, size) in sizes.enumerated() {
|
||||
if currentX + size.width > containerWidth && !lineElements.isEmpty {
|
||||
// New line
|
||||
placeLine()
|
||||
currentX = 0
|
||||
currentY += lineHeight + spacing
|
||||
lineHeight = 0
|
||||
}
|
||||
|
||||
lineElements.append((offset, size))
|
||||
currentX += size.width + spacing
|
||||
lineHeight = max(lineHeight, size.height)
|
||||
}
|
||||
placeLine() // Place the last line
|
||||
}
|
||||
}
|
||||
365
ios/WatchRunner Watch App/Models/Models.swift
Normal file
365
ios/WatchRunner Watch App/Models/Models.swift
Normal file
@@ -0,0 +1,365 @@
|
||||
// Models.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - Models
|
||||
|
||||
struct AppToken: Codable {
|
||||
let token: String
|
||||
}
|
||||
|
||||
struct SnActivity: Codable, Identifiable {
|
||||
let id: String
|
||||
let type: String
|
||||
let data: ActivityData?
|
||||
let createdAt: Date
|
||||
}
|
||||
|
||||
enum ActivityData: Codable {
|
||||
case post(SnPost)
|
||||
case discovery(DiscoveryData)
|
||||
case unknown
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
if let post = try? container.decode(SnPost.self) {
|
||||
self = .post(post)
|
||||
return
|
||||
}
|
||||
if let discoveryData = try? container.decode(DiscoveryData.self) {
|
||||
self = .discovery(discoveryData)
|
||||
return
|
||||
}
|
||||
self = .unknown
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
// Not needed for decoding
|
||||
}
|
||||
}
|
||||
|
||||
struct SnPost: Codable, Identifiable {
|
||||
let id: String
|
||||
let title: String?
|
||||
let content: String?
|
||||
let publisher: SnPublisher
|
||||
let attachments: [SnCloudFile]
|
||||
let tags: [SnPostTag]
|
||||
}
|
||||
|
||||
struct DiscoveryData: Codable {
|
||||
let items: [DiscoveryItem]
|
||||
}
|
||||
|
||||
struct DiscoveryItem: Codable, Identifiable {
|
||||
var id = UUID()
|
||||
let type: String
|
||||
let data: DiscoveryItemData
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case type, data
|
||||
}
|
||||
}
|
||||
|
||||
enum DiscoveryItemData: Codable {
|
||||
case realm(SnRealm)
|
||||
case publisher(SnPublisher)
|
||||
case article(SnWebArticle)
|
||||
case unknown
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
if let realm = try? container.decode(SnRealm.self) {
|
||||
self = .realm(realm)
|
||||
return
|
||||
}
|
||||
if let publisher = try? container.decode(SnPublisher.self) {
|
||||
self = .publisher(publisher)
|
||||
return
|
||||
}
|
||||
if let article = try? container.decode(SnWebArticle.self) {
|
||||
self = .article(article)
|
||||
return
|
||||
}
|
||||
self = .unknown
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
// Not needed for decoding
|
||||
}
|
||||
}
|
||||
|
||||
struct SnRealm: Codable, Identifiable {
|
||||
let id: String
|
||||
let name: String
|
||||
let description: String?
|
||||
}
|
||||
|
||||
struct SnPublisher: Codable, Identifiable {
|
||||
let id: String
|
||||
let name: String
|
||||
let nick: String?
|
||||
let description: String?
|
||||
let picture: SnCloudFile?
|
||||
}
|
||||
|
||||
struct SnCloudFile: Codable, Identifiable {
|
||||
let id: String
|
||||
let mimeType: String?
|
||||
}
|
||||
|
||||
struct SnPostTag: Codable, Identifiable {
|
||||
let id: String
|
||||
let slug: String
|
||||
let name: String?
|
||||
}
|
||||
|
||||
struct SnWebArticle: Codable, Identifiable {
|
||||
let id: String
|
||||
let title: String
|
||||
let url: String
|
||||
}
|
||||
|
||||
struct SnNotification: Codable, Identifiable {
|
||||
let id: String
|
||||
let topic: String
|
||||
let title: String
|
||||
let subtitle: String
|
||||
let content: String
|
||||
let meta: [String: AnyCodable]?
|
||||
let priority: Int
|
||||
let viewedAt: Date?
|
||||
let accountId: String
|
||||
let createdAt: Date
|
||||
let updatedAt: Date
|
||||
let deletedAt: Date?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id
|
||||
case topic
|
||||
case title
|
||||
case subtitle
|
||||
case content
|
||||
case meta
|
||||
case priority
|
||||
case viewedAt = "viewedAt"
|
||||
case accountId = "accountId"
|
||||
case createdAt = "createdAt"
|
||||
case updatedAt = "updatedAt"
|
||||
case deletedAt = "deletedAt"
|
||||
}
|
||||
}
|
||||
|
||||
struct AnyCodable: Codable {
|
||||
let value: Any
|
||||
|
||||
init(_ value: Any) {
|
||||
self.value = value
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.singleValueContainer()
|
||||
if let intValue = try? container.decode(Int.self) {
|
||||
value = intValue
|
||||
} else if let doubleValue = try? container.decode(Double.self) {
|
||||
value = doubleValue
|
||||
} else if let boolValue = try? container.decode(Bool.self) {
|
||||
value = boolValue
|
||||
} else if let stringValue = try? container.decode(String.self) {
|
||||
value = stringValue
|
||||
} else if let arrayValue = try? container.decode([AnyCodable].self) {
|
||||
value = arrayValue
|
||||
} else if let dictValue = try? container.decode([String: AnyCodable].self) {
|
||||
value = dictValue
|
||||
} else {
|
||||
value = NSNull()
|
||||
}
|
||||
}
|
||||
|
||||
func encode(to encoder: Encoder) throws {
|
||||
var container = encoder.singleValueContainer()
|
||||
switch value {
|
||||
case let intValue as Int:
|
||||
try container.encode(intValue)
|
||||
case let doubleValue as Double:
|
||||
try container.encode(doubleValue)
|
||||
case let boolValue as Bool:
|
||||
try container.encode(boolValue)
|
||||
case let stringValue as String:
|
||||
try container.encode(stringValue)
|
||||
case let arrayValue as [AnyCodable]:
|
||||
try container.encode(arrayValue)
|
||||
case let dictValue as [String: AnyCodable]:
|
||||
try container.encode(dictValue)
|
||||
default:
|
||||
try container.encodeNil()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct NotificationResponse {
|
||||
let notifications: [SnNotification]
|
||||
let total: Int
|
||||
let hasMore: Bool
|
||||
}
|
||||
|
||||
struct ActivityResponse {
|
||||
let activities: [SnActivity]
|
||||
let hasMore: Bool
|
||||
let nextCursor: String?
|
||||
}
|
||||
|
||||
struct SnAccount: Codable {
|
||||
let id: String
|
||||
let name: String
|
||||
let nick: String
|
||||
let profile: SnUserProfile
|
||||
let createdAt: Date
|
||||
}
|
||||
|
||||
struct SnUserProfile: Codable {
|
||||
let bio: String?
|
||||
let picture: SnCloudFile?
|
||||
let background: SnCloudFile?
|
||||
let level: Int
|
||||
let experience: Int
|
||||
let levelingProgress: Double
|
||||
}
|
||||
|
||||
struct SnAccountStatus: Codable {
|
||||
let id: String
|
||||
let attitude: Int
|
||||
let isOnline: Bool
|
||||
let isInvisible: Bool
|
||||
let isNotDisturb: Bool
|
||||
let isCustomized: Bool
|
||||
let label: String
|
||||
let meta: [String: AnyCodable]?
|
||||
let clearedAt: Date?
|
||||
let accountId: String
|
||||
let createdAt: Date
|
||||
let updatedAt: Date
|
||||
let deletedAt: Date?
|
||||
}
|
||||
|
||||
// MARK: - Chat Models
|
||||
|
||||
struct SnChatRoom: Codable, Identifiable {
|
||||
let id: String
|
||||
let name: String?
|
||||
let description: String?
|
||||
let type: Int
|
||||
let isPublic: Bool
|
||||
let isCommunity: Bool
|
||||
let picture: SnCloudFile?
|
||||
let background: SnCloudFile?
|
||||
let realmId: String?
|
||||
let realm: SnRealm?
|
||||
let createdAt: Date
|
||||
let updatedAt: Date
|
||||
let deletedAt: Date?
|
||||
let members: [SnChatMember]?
|
||||
}
|
||||
|
||||
struct SnChatMessage: Codable, Identifiable {
|
||||
let id: String
|
||||
let type: String
|
||||
let content: String?
|
||||
let nonce: String?
|
||||
let meta: [String: AnyCodable]
|
||||
let membersMentioned: [String]?
|
||||
let editedAt: Date?
|
||||
let attachments: [SnCloudFile]
|
||||
let reactions: [SnChatReaction]
|
||||
let repliedMessageId: String?
|
||||
let forwardedMessageId: String?
|
||||
let senderId: String
|
||||
let sender: SnChatMember
|
||||
let chatRoomId: String
|
||||
let createdAt: Date
|
||||
let updatedAt: Date
|
||||
let deletedAt: Date?
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case id, type, content, nonce, meta, membersMentioned, editedAt, attachments, reactions, repliedMessageId, forwardedMessageId, senderId, sender, chatRoomId, createdAt, updatedAt, deletedAt
|
||||
}
|
||||
|
||||
init(from decoder: Decoder) throws {
|
||||
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||
id = try container.decode(String.self, forKey: .id)
|
||||
type = try container.decode(String.self, forKey: .type)
|
||||
content = try container.decodeIfPresent(String.self, forKey: .content)
|
||||
nonce = try container.decodeIfPresent(String.self, forKey: .nonce)
|
||||
meta = try container.decode([String: AnyCodable].self, forKey: .meta)
|
||||
membersMentioned = try container.decodeIfPresent([String].self, forKey: .membersMentioned) ?? []
|
||||
editedAt = try container.decodeIfPresent(Date.self, forKey: .editedAt)
|
||||
attachments = try container.decode([SnCloudFile].self, forKey: .attachments)
|
||||
reactions = try container.decode([SnChatReaction].self, forKey: .reactions)
|
||||
repliedMessageId = try container.decodeIfPresent(String.self, forKey: .repliedMessageId)
|
||||
forwardedMessageId = try container.decodeIfPresent(String.self, forKey: .forwardedMessageId)
|
||||
senderId = try container.decode(String.self, forKey: .senderId)
|
||||
sender = try container.decode(SnChatMember.self, forKey: .sender)
|
||||
chatRoomId = try container.decode(String.self, forKey: .chatRoomId)
|
||||
createdAt = try container.decode(Date.self, forKey: .createdAt)
|
||||
updatedAt = try container.decode(Date.self, forKey: .updatedAt)
|
||||
deletedAt = try container.decodeIfPresent(Date.self, forKey: .deletedAt)
|
||||
}
|
||||
}
|
||||
|
||||
struct SnChatReaction: Codable, Identifiable {
|
||||
let id: String
|
||||
let messageId: String
|
||||
let senderId: String
|
||||
let sender: SnChatMember
|
||||
let symbol: String
|
||||
let attitude: Int
|
||||
let createdAt: Date
|
||||
let updatedAt: Date
|
||||
let deletedAt: Date?
|
||||
}
|
||||
|
||||
struct SnChatMember: Codable, Identifiable {
|
||||
let id: String
|
||||
let chatRoomId: String
|
||||
let chatRoom: SnChatRoom?
|
||||
let accountId: String
|
||||
let account: SnAccount
|
||||
let nick: String?
|
||||
let role: Int
|
||||
let notify: Int
|
||||
let joinedAt: Date?
|
||||
let breakUntil: Date?
|
||||
let timeoutUntil: Date?
|
||||
let isBot: Bool
|
||||
let status: SnAccountStatus?
|
||||
let createdAt: Date
|
||||
let updatedAt: Date
|
||||
let deletedAt: Date?
|
||||
}
|
||||
|
||||
struct SnChatSummary: Codable {
|
||||
let unreadCount: Int
|
||||
let lastMessage: SnChatMessage?
|
||||
}
|
||||
|
||||
struct ChatRoomsResponse {
|
||||
let rooms: [SnChatRoom]
|
||||
}
|
||||
|
||||
struct ChatInvitesResponse {
|
||||
let invites: [SnChatMember]
|
||||
}
|
||||
|
||||
struct MessageSyncResponse: Codable {
|
||||
let messages: [SnChatMessage]
|
||||
let currentTimestamp: Date
|
||||
|
||||
enum CodingKeys: String, CodingKey {
|
||||
case messages
|
||||
case currentTimestamp = "current_timestamp"
|
||||
}
|
||||
}
|
||||
15
ios/WatchRunner Watch App/Previews/CustomPreviews.swift
Normal file
15
ios/WatchRunner Watch App/Previews/CustomPreviews.swift
Normal file
@@ -0,0 +1,15 @@
|
||||
//
|
||||
// CustomPreviews.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
#Preview {
|
||||
NavigationStack {
|
||||
ActivityListView(filter: "Preview", mockActivities: SnActivity.mock)
|
||||
.environmentObject(AppState())
|
||||
}
|
||||
}
|
||||
35
ios/WatchRunner Watch App/Previews/MockData.swift
Normal file
35
ios/WatchRunner Watch App/Previews/MockData.swift
Normal file
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// MockData.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
#if DEBUG
|
||||
extension SnActivity {
|
||||
static var mock: [SnActivity] {
|
||||
let mockPublisher = SnPublisher(id: "pub1", name: "Mock Publisher", nick: "mock_nick", description: "A publisher for testing", picture: SnCloudFile(id: "mock_avatar_id", mimeType: "image/png"))
|
||||
let mockTag1 = SnPostTag(id: "tag1", slug: "swiftui", name: "SwiftUI")
|
||||
let mockTag2 = SnPostTag(id: "tag2", slug: "watchos", name: "watchOS")
|
||||
let mockAttachment1 = SnCloudFile(id: "mock_image_id_1", mimeType: "image/jpeg")
|
||||
let mockAttachment2 = SnCloudFile(id: "mock_image_id_2", mimeType: "image/png")
|
||||
|
||||
let post1 = SnPost(id: "1", title: "Hello from a Mock Post!", content: "This is a mock post content. It can be a bit longer to see how it wraps.", publisher: mockPublisher, attachments: [mockAttachment1, mockAttachment2], tags: [mockTag1, mockTag2])
|
||||
let activity1 = SnActivity(id: "1", type: "posts.new", data: .post(post1), createdAt: Date())
|
||||
|
||||
let realm1 = SnRealm(id: "r1", name: "SwiftUI Previews", description: "A place for designing in previews.")
|
||||
let publisher1 = SnPublisher(id: "p1", name: "The Mock Times", nick: "mock_times", description: "All the news that's fit to mock.", picture: nil)
|
||||
let article1 = SnWebArticle(id: "a1", title: "The Art of Mocking Data", url: "https://example.com")
|
||||
|
||||
let discoveryItem1 = DiscoveryItem(type: "realm", data: .realm(realm1))
|
||||
let discoveryItem2 = DiscoveryItem(type: "publisher", data: .publisher(publisher1))
|
||||
let discoveryItem3 = DiscoveryItem(type: "article", data: .article(article1))
|
||||
let discoveryData = DiscoveryData(items: [discoveryItem1, discoveryItem2, discoveryItem3])
|
||||
let activity2 = SnActivity(id: "2", type: "discovery", data: .discovery(discoveryData), createdAt: Date())
|
||||
|
||||
return [activity1, activity2]
|
||||
}
|
||||
}
|
||||
#endif
|
||||
97
ios/WatchRunner Watch App/Services/ImageLoader.swift
Normal file
97
ios/WatchRunner Watch App/Services/ImageLoader.swift
Normal file
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// ImageLoader.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Kingfisher
|
||||
import KingfisherWebP
|
||||
import Combine
|
||||
|
||||
// MARK: - Image Loader
|
||||
|
||||
@MainActor
|
||||
class ImageLoader: ObservableObject {
|
||||
@Published var image: Image?
|
||||
@Published var errorMessage: String?
|
||||
@Published var isLoading = false
|
||||
|
||||
private var currentTask: DownloadTask?
|
||||
|
||||
init() {}
|
||||
|
||||
deinit {
|
||||
currentTask?.cancel()
|
||||
}
|
||||
|
||||
func loadImage(from initialUrl: URL, token: String) async {
|
||||
isLoading = true
|
||||
errorMessage = nil
|
||||
image = nil
|
||||
|
||||
// Create request modifier for authorization
|
||||
let modifier = AnyModifier { request in
|
||||
var r = request
|
||||
r.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
r.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
return r
|
||||
}
|
||||
|
||||
// Use WebP processor as default since the app seems to handle WebP images
|
||||
let processor = WebPProcessor.default
|
||||
|
||||
// Use KingfisherManager to retrieve image with caching
|
||||
currentTask = KingfisherManager.shared.retrieveImage(
|
||||
with: initialUrl,
|
||||
options: [
|
||||
.requestModifier(modifier),
|
||||
.processor(processor),
|
||||
.cacheOriginalImage, // Cache the original image data
|
||||
.loadDiskFileSynchronously // Load from disk cache synchronously if available
|
||||
]
|
||||
) { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
|
||||
Task { @MainActor in
|
||||
switch result {
|
||||
case .success(let value):
|
||||
self.image = Image(uiImage: value.image)
|
||||
print("[watchOS] Image loaded successfully from \(value.cacheType == .none ? "network" : "cache (\(value.cacheType))").")
|
||||
self.isLoading = false
|
||||
case .failure(let error):
|
||||
// If WebP processor fails (likely due to format), try with default processor
|
||||
let defaultProcessor = DefaultImageProcessor.default
|
||||
self.currentTask = KingfisherManager.shared.retrieveImage(
|
||||
with: initialUrl,
|
||||
options: [
|
||||
.requestModifier(modifier),
|
||||
.processor(defaultProcessor),
|
||||
.cacheOriginalImage,
|
||||
.loadDiskFileSynchronously
|
||||
]
|
||||
) { [weak self] fallbackResult in
|
||||
guard let self = self else { return }
|
||||
|
||||
Task { @MainActor in
|
||||
switch fallbackResult {
|
||||
case .success(let value):
|
||||
self.image = Image(uiImage: value.image)
|
||||
print("[watchOS] Image loaded successfully from \(value.cacheType == .none ? "network" : "cache (\(value.cacheType))") using fallback processor.")
|
||||
case .failure(let fallbackError):
|
||||
self.errorMessage = fallbackError.localizedDescription
|
||||
print("[watchOS] Image loading failed: \(fallbackError.localizedDescription)")
|
||||
}
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cancel() {
|
||||
currentTask?.cancel()
|
||||
}
|
||||
}
|
||||
399
ios/WatchRunner Watch App/Services/NetworkService.swift
Normal file
399
ios/WatchRunner Watch App/Services/NetworkService.swift
Normal file
@@ -0,0 +1,399 @@
|
||||
//
|
||||
// NetworkService.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - Network Service
|
||||
|
||||
class NetworkService {
|
||||
private let session = URLSession.shared
|
||||
|
||||
func fetchActivities(filter: String, cursor: String? = nil, token: String, serverUrl: String) async throws -> ActivityResponse {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
var components = URLComponents(url: baseURL.appendingPathComponent("/sphere/activities"), resolvingAgainstBaseURL: false)!
|
||||
var queryItems = [URLQueryItem(name: "take", value: "20")]
|
||||
if filter.lowercased() != "explore" {
|
||||
queryItems.append(URLQueryItem(name: "filter", value: filter.lowercased()))
|
||||
}
|
||||
if let cursor = cursor {
|
||||
queryItems.append(URLQueryItem(name: "cursor", value: cursor))
|
||||
}
|
||||
components.queryItems = queryItems
|
||||
|
||||
var request = URLRequest(url: components.url!)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, _) = try await session.data(for: request)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
let activities = try decoder.decode([SnActivity].self, from: data)
|
||||
|
||||
let hasMore = (activities.first?.type ?? "empty") != "empty"
|
||||
let nextCursor = activities.isEmpty ? nil : activities.map { $0.createdAt }.min()?.ISO8601Format()
|
||||
|
||||
return ActivityResponse(activities: activities, hasMore: hasMore, nextCursor: nextCursor)
|
||||
}
|
||||
|
||||
func createPost(title: String, content: String, token: String, serverUrl: String) async throws {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/sphere/posts")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let body: [String: Any] = ["title": title, "content": content]
|
||||
request.httpBody = try JSONSerialization.data(withJSONObject: body)
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 201 {
|
||||
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||
print("[watchOS] createPost failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||
}
|
||||
}
|
||||
|
||||
func fetchNotifications(offset: Int = 0, take: Int = 20, token: String, serverUrl: String) async throws -> NotificationResponse {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
var components = URLComponents(url: baseURL.appendingPathComponent("/ring/notifications"), resolvingAgainstBaseURL: false)!
|
||||
var queryItems = [URLQueryItem(name: "offset", value: String(offset)), URLQueryItem(name: "take", value: String(take))]
|
||||
components.queryItems = queryItems
|
||||
|
||||
var request = URLRequest(url: components.url!)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
let notifications = try decoder.decode([SnNotification].self, from: data)
|
||||
|
||||
let httpResponse = response as? HTTPURLResponse
|
||||
let total = Int(httpResponse?.value(forHTTPHeaderField: "X-Total") ?? "0") ?? 0
|
||||
let hasMore = offset + notifications.count < total
|
||||
|
||||
return NotificationResponse(notifications: notifications, total: total, hasMore: hasMore)
|
||||
}
|
||||
|
||||
func fetchUserProfile(token: String, serverUrl: String) async throws -> SnAccount {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/pass/accounts/me")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, _) = try await session.data(for: request)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
return try decoder.decode(SnAccount.self, from: data)
|
||||
}
|
||||
|
||||
func fetchAccountStatus(token: String, serverUrl: String) async throws -> SnAccountStatus? {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/pass/accounts/me/statuses")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 404 {
|
||||
return nil
|
||||
}
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
return try decoder.decode(SnAccountStatus.self, from: data)
|
||||
}
|
||||
|
||||
func createOrUpdateStatus(attitude: Int, isInvisible: Bool, isNotDisturb: Bool, label: String?, token: String, serverUrl: String) async throws -> SnAccountStatus {
|
||||
// Check if there's already a customized status
|
||||
let existingStatus = try? await fetchAccountStatus(token: token, serverUrl: serverUrl)
|
||||
let method = (existingStatus?.isCustomized == true) ? "PATCH" : "POST"
|
||||
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/pass/accounts/me/statuses")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = method
|
||||
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
var body: [String: Any] = [
|
||||
"attitude": attitude,
|
||||
"is_invisible": isInvisible,
|
||||
"is_not_disturb": isNotDisturb
|
||||
]
|
||||
|
||||
if let label = label, !label.isEmpty {
|
||||
body["label"] = label
|
||||
}
|
||||
|
||||
request.httpBody = try JSONSerialization.data(withJSONObject: body)
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 201 && httpResponse.statusCode != 200 {
|
||||
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||
print("[watchOS] createOrUpdateStatus failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||
}
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
return try decoder.decode(SnAccountStatus.self, from: data)
|
||||
}
|
||||
|
||||
func clearStatus(token: String, serverUrl: String) async throws {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/pass/accounts/me/statuses")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "DELETE"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 204 {
|
||||
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||
print("[watchOS] clearStatus failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Chat API Methods
|
||||
|
||||
func fetchChatRooms(token: String, serverUrl: String) async throws -> ChatRoomsResponse {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/sphere/chat")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, _) = try await session.data(for: request)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
let rooms = try decoder.decode([SnChatRoom].self, from: data)
|
||||
return ChatRoomsResponse(rooms: rooms)
|
||||
}
|
||||
|
||||
func fetchChatRoom(identifier: String, token: String, serverUrl: String) async throws -> SnChatRoom {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/sphere/chat/\(identifier)")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 404 {
|
||||
throw URLError(.resourceUnavailable)
|
||||
}
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
return try decoder.decode(SnChatRoom.self, from: data)
|
||||
}
|
||||
|
||||
func fetchChatInvites(token: String, serverUrl: String) async throws -> ChatInvitesResponse {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/sphere/chat/invites")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, _) = try await session.data(for: request)
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
let invites = try decoder.decode([SnChatMember].self, from: data)
|
||||
return ChatInvitesResponse(invites: invites)
|
||||
}
|
||||
|
||||
func acceptChatInvite(chatRoomId: String, token: String, serverUrl: String) async throws {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/sphere/chat/invites/\(chatRoomId)/accept")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
|
||||
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||
print("[watchOS] acceptChatInvite failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||
}
|
||||
}
|
||||
|
||||
func declineChatInvite(chatRoomId: String, token: String, serverUrl: String) async throws {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
let url = baseURL.appendingPathComponent("/sphere/chat/invites/\(chatRoomId)/decline")
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.httpMethod = "POST"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
|
||||
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||
print("[watchOS] declineChatInvite failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - Message API Methods
|
||||
|
||||
func fetchChatMessages(chatRoomId: String, token: String, serverUrl: String, before: Date? = nil, take: Int = 50) async throws -> [SnChatMessage] {
|
||||
guard let baseURL = URL(string: serverUrl) else {
|
||||
throw URLError(.badURL)
|
||||
}
|
||||
|
||||
// Try a different pattern: /sphere/chat/messages with roomId as query param
|
||||
var components = URLComponents(
|
||||
url: baseURL.appendingPathComponent("/sphere/chat/\(chatRoomId)/messages"),
|
||||
resolvingAgainstBaseURL: false
|
||||
)!
|
||||
var queryItems = [
|
||||
URLQueryItem(name: "take", value: String(take))
|
||||
]
|
||||
if let before = before {
|
||||
queryItems.append(URLQueryItem(name: "before", value: ISO8601DateFormatter().string(from: before)))
|
||||
}
|
||||
components.queryItems = queryItems
|
||||
|
||||
var request = URLRequest(url: components.url!)
|
||||
request.httpMethod = "GET"
|
||||
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||
|
||||
let (data, response) = try await session.data(for: request)
|
||||
|
||||
if let httpResponse = response as? HTTPURLResponse {
|
||||
_ = String(data: data, encoding: .utf8) ?? "Unable to decode response body"
|
||||
|
||||
if httpResponse.statusCode != 200 {
|
||||
print("[watchOS] fetchChatMessages failed with status \(httpResponse.statusCode)")
|
||||
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||
}
|
||||
}
|
||||
|
||||
// Check if data is empty
|
||||
if data.isEmpty {
|
||||
print("[watchOS] fetchChatMessages received empty response data")
|
||||
return []
|
||||
}
|
||||
|
||||
let decoder = JSONDecoder()
|
||||
decoder.dateDecodingStrategy = .iso8601
|
||||
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||
|
||||
do {
|
||||
let messages = try decoder.decode([SnChatMessage].self, from: data)
|
||||
print("[watchOS] fetchChatMessages successfully decoded \(messages.count) messages")
|
||||
return messages
|
||||
} catch DecodingError.dataCorrupted(let context) {
|
||||
print(context)
|
||||
return []
|
||||
} catch DecodingError.keyNotFound(let key, let context) {
|
||||
print("Key '\(key)' not found:", context.debugDescription)
|
||||
print("codingPath:", context.codingPath)
|
||||
return []
|
||||
} catch DecodingError.valueNotFound(let value, let context) {
|
||||
print("Value '\(value)' not found:", context.debugDescription)
|
||||
print("codingPath:", context.codingPath)
|
||||
return []
|
||||
} catch DecodingError.typeMismatch(let type, let context) {
|
||||
print("Type '\(type)' mismatch:", context.debugDescription)
|
||||
print("codingPath:", context.codingPath)
|
||||
return []
|
||||
} catch {
|
||||
print("error: ", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
}
|
||||
39
ios/WatchRunner Watch App/State/AppState.swift
Normal file
39
ios/WatchRunner Watch App/State/AppState.swift
Normal file
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// AppState.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
// MARK: - App State
|
||||
|
||||
@MainActor
|
||||
class AppState: ObservableObject {
|
||||
@Published var token: String? = nil
|
||||
@Published var serverUrl: String? = nil
|
||||
@Published var isReady = false
|
||||
|
||||
let networkService = NetworkService()
|
||||
private var wcService = WatchConnectivityService()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
|
||||
init() {
|
||||
wcService.$token.combineLatest(wcService.$serverUrl)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] token, serverUrl in
|
||||
self?.token = token
|
||||
self?.serverUrl = serverUrl
|
||||
if token != nil && serverUrl != nil {
|
||||
self?.isReady = true
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func requestData() {
|
||||
wcService.requestDataFromPhone()
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
//
|
||||
// WatchConnectivityService.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import WatchConnectivity
|
||||
import Combine
|
||||
|
||||
// MARK: - Watch Connectivity
|
||||
|
||||
class WatchConnectivityService: NSObject, WCSessionDelegate, ObservableObject {
|
||||
@Published var token: String?
|
||||
@Published var serverUrl: String?
|
||||
|
||||
private let session: WCSession
|
||||
private let userDefaults = UserDefaults.standard
|
||||
private let tokenKey = "token"
|
||||
private let serverUrlKey = "serverUrl"
|
||||
|
||||
override init() {
|
||||
self.session = .default
|
||||
super.init()
|
||||
print("[watchOS] Activating WCSession")
|
||||
self.session.delegate = self
|
||||
self.session.activate()
|
||||
|
||||
// Load cached data
|
||||
self.token = userDefaults.string(forKey: tokenKey)
|
||||
self.serverUrl = userDefaults.string(forKey: serverUrlKey)
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
|
||||
if let error = error {
|
||||
print("[watchOS] WCSession activation failed with error: \(error.localizedDescription)")
|
||||
return
|
||||
}
|
||||
print("[watchOS] WCSession activated with state: \(activationState.rawValue)")
|
||||
if activationState == .activated {
|
||||
requestDataFromPhone()
|
||||
}
|
||||
}
|
||||
|
||||
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
|
||||
print("[watchOS] Received message: \(message)")
|
||||
DispatchQueue.main.async {
|
||||
if let token = message["token"] as? String {
|
||||
self.token = token
|
||||
self.userDefaults.set(token, forKey: self.tokenKey)
|
||||
}
|
||||
if let serverUrl = message["serverUrl"] as? String {
|
||||
self.serverUrl = serverUrl
|
||||
self.userDefaults.set(serverUrl, forKey: self.serverUrlKey)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func requestDataFromPhone() {
|
||||
guard session.isReachable else {
|
||||
print("[watchOS] Phone is not reachable")
|
||||
return
|
||||
}
|
||||
|
||||
print("[watchOS] Requesting data from phone")
|
||||
session.sendMessage(["request": "data"]) { [weak self] response in
|
||||
guard let self = self else { return }
|
||||
print("[watchOS] Received reply: \(response)")
|
||||
DispatchQueue.main.async {
|
||||
if let token = response["token"] as? String {
|
||||
self.token = token
|
||||
self.userDefaults.set(token, forKey: self.tokenKey)
|
||||
}
|
||||
if let serverUrl = response["serverUrl"] as? String {
|
||||
self.serverUrl = serverUrl
|
||||
self.userDefaults.set(serverUrl, forKey: self.serverUrlKey)
|
||||
}
|
||||
}
|
||||
} errorHandler: { error in
|
||||
print("[watchOS] sendMessage failed with error: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
20
ios/WatchRunner Watch App/Utils/AttachmentUtils.swift
Normal file
20
ios/WatchRunner Watch App/Utils/AttachmentUtils.swift
Normal file
@@ -0,0 +1,20 @@
|
||||
//
|
||||
// AttachmentUtils.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
|
||||
// MARK: - Helper Functions
|
||||
|
||||
func getAttachmentUrl(for fileId: String, serverUrl: String) -> URL? {
|
||||
let urlString: String
|
||||
if fileId.starts(with: "http") {
|
||||
urlString = fileId
|
||||
} else {
|
||||
urlString = "\(serverUrl)/drive/files/\(fileId)"
|
||||
}
|
||||
return URL(string: urlString)
|
||||
}
|
||||
73
ios/WatchRunner Watch App/ViewModels/ActivityViewModel.swift
Normal file
73
ios/WatchRunner Watch App/ViewModels/ActivityViewModel.swift
Normal file
@@ -0,0 +1,73 @@
|
||||
//
|
||||
// ActivityViewModel.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
// MARK: - View Models
|
||||
|
||||
@MainActor
|
||||
class ActivityViewModel: ObservableObject {
|
||||
@Published var activities: [SnActivity] = []
|
||||
@Published var isLoading = false
|
||||
@Published var isLoadingMore = false
|
||||
@Published var errorMessage: String?
|
||||
@Published var hasMore = false
|
||||
|
||||
private let networkService = NetworkService()
|
||||
let filter: String
|
||||
private var isMock = false
|
||||
private var hasFetched = false
|
||||
private var nextCursor: String?
|
||||
|
||||
init(filter: String, mockActivities: [SnActivity]? = nil) {
|
||||
self.filter = filter
|
||||
if let mockActivities = mockActivities {
|
||||
self.activities = mockActivities
|
||||
self.isMock = true
|
||||
}
|
||||
}
|
||||
|
||||
func fetchActivities(token: String, serverUrl: String) async {
|
||||
if isMock || hasFetched { return }
|
||||
guard !isLoading else { return }
|
||||
isLoading = true
|
||||
errorMessage = nil
|
||||
hasFetched = true
|
||||
nextCursor = nil
|
||||
|
||||
do {
|
||||
let response = try await networkService.fetchActivities(filter: filter, cursor: nil, token: token, serverUrl: serverUrl)
|
||||
self.activities = response.activities
|
||||
self.hasMore = response.hasMore
|
||||
self.nextCursor = response.nextCursor
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
print("[watchOS] fetchActivities failed with error: \(error)")
|
||||
hasFetched = false
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
func loadMoreActivities(token: String, serverUrl: String) async {
|
||||
guard !isLoadingMore && hasMore && nextCursor != nil else { return }
|
||||
isLoadingMore = true
|
||||
|
||||
do {
|
||||
let response = try await networkService.fetchActivities(filter: filter, cursor: nextCursor, token: token, serverUrl: serverUrl)
|
||||
self.activities.append(contentsOf: response.activities)
|
||||
self.hasMore = response.hasMore
|
||||
self.nextCursor = response.nextCursor
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
print("[watchOS] loadMoreActivities failed with error: \(error)")
|
||||
}
|
||||
|
||||
isLoadingMore = false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
//
|
||||
// ComposePostViewModel.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import Foundation
|
||||
import Combine
|
||||
|
||||
@MainActor
|
||||
class ComposePostViewModel: ObservableObject {
|
||||
@Published var title = ""
|
||||
@Published var content = ""
|
||||
@Published var isPosting = false
|
||||
@Published var errorMessage: String?
|
||||
@Published var didPost = false
|
||||
|
||||
private let networkService = NetworkService()
|
||||
|
||||
func createPost(token: String, serverUrl: String) async {
|
||||
guard !isPosting else { return }
|
||||
isPosting = true
|
||||
errorMessage = nil
|
||||
|
||||
do {
|
||||
try await networkService.createPost(title: title, content: content, token: token, serverUrl: serverUrl)
|
||||
didPost = true
|
||||
} catch {
|
||||
errorMessage = error.localizedDescription
|
||||
}
|
||||
|
||||
isPosting = false
|
||||
}
|
||||
}
|
||||
284
ios/WatchRunner Watch App/Views/AccountView.swift
Normal file
284
ios/WatchRunner Watch App/Views/AccountView.swift
Normal file
@@ -0,0 +1,284 @@
|
||||
//
|
||||
// AccountView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/30.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct AccountView: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@State private var user: SnAccount?
|
||||
@State private var status: SnAccountStatus?
|
||||
@State private var isLoading = false
|
||||
@State private var error: Error?
|
||||
@State private var showingClearConfirmation = false
|
||||
|
||||
@StateObject private var profileImageLoader = ImageLoader()
|
||||
@StateObject private var bannerImageLoader = ImageLoader()
|
||||
|
||||
private let networkService = NetworkService()
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
.padding()
|
||||
} else if let error = error {
|
||||
VStack {
|
||||
Text("Failed to load account")
|
||||
.foregroundColor(.red)
|
||||
Text(error.localizedDescription)
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
.padding()
|
||||
} else if let user = user {
|
||||
VStack(spacing: 16) {
|
||||
// Banner
|
||||
if user.profile.background != nil {
|
||||
if bannerImageLoader.isLoading {
|
||||
ProgressView()
|
||||
.frame(height: 80)
|
||||
} else if let bannerImage = bannerImageLoader.image {
|
||||
bannerImage
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fill)
|
||||
.frame(height: 80)
|
||||
.clipped()
|
||||
.cornerRadius(8)
|
||||
} else if bannerImageLoader.errorMessage != nil {
|
||||
Rectangle()
|
||||
.fill(Color.gray.opacity(0.3))
|
||||
.frame(height: 80)
|
||||
.cornerRadius(8)
|
||||
} else {
|
||||
Rectangle()
|
||||
.fill(Color.gray.opacity(0.3))
|
||||
.frame(height: 80)
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
||||
|
||||
// Profile Picture
|
||||
HStack(spacing: 16)
|
||||
{
|
||||
if profileImageLoader.isLoading {
|
||||
ProgressView()
|
||||
.frame(width: 60, height: 60)
|
||||
} else if let profileImage = profileImageLoader.image {
|
||||
profileImage
|
||||
.resizable()
|
||||
.frame(width: 60, height: 60)
|
||||
.clipShape(Circle())
|
||||
} else if profileImageLoader.errorMessage != nil {
|
||||
Circle()
|
||||
.fill(Color.red.opacity(0.3))
|
||||
.frame(width: 60, height: 60)
|
||||
.overlay(
|
||||
Image(systemName: "exclamationmark.triangle")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.foregroundColor(.red)
|
||||
)
|
||||
} else {
|
||||
Circle()
|
||||
.fill(Color.gray.opacity(0.3))
|
||||
.frame(width: 60, height: 60)
|
||||
.overlay(
|
||||
Image(systemName: "person.circle.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.foregroundColor(.gray)
|
||||
)
|
||||
}
|
||||
|
||||
// Username and Handle
|
||||
VStack(alignment: .leading) {
|
||||
Text(user.nick)
|
||||
.font(.headline)
|
||||
Text("@\(user.name)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
// Status
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
HStack {
|
||||
Text("Status")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
Spacer()
|
||||
if status?.isCustomized == true {
|
||||
Button(action: {
|
||||
showingClearConfirmation = true
|
||||
}) {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color.red.opacity(0.1))
|
||||
.frame(width: 28, height: 28)
|
||||
Image(systemName: "trash")
|
||||
.foregroundColor(.red)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.frame(width: 28, height: 28)
|
||||
}
|
||||
NavigationLink(
|
||||
destination: StatusCreationView(initialStatus: status?.isCustomized == true ? status : nil)
|
||||
.environmentObject(appState)
|
||||
) {
|
||||
ZStack {
|
||||
Circle()
|
||||
.fill(Color.blue.opacity(0.1))
|
||||
.frame(width: 28, height: 28)
|
||||
Image(systemName: "pencil")
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
.frame(width: 28, height: 28)
|
||||
}
|
||||
|
||||
if let status = status {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack {
|
||||
Circle()
|
||||
.fill(status.isOnline ? Color.green : Color.gray)
|
||||
.frame(width: 8, height: 8)
|
||||
Text(status.label.isEmpty ? "No status" : status.label)
|
||||
.font(.body)
|
||||
}
|
||||
|
||||
if status.isInvisible {
|
||||
Text("Invisible")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
if status.isNotDisturb {
|
||||
Text("Do Not Disturb")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
if let clearedAt = status.clearedAt {
|
||||
Text("Clears: \(clearedAt.formatted(date: .abbreviated, time: .shortened))")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("No status set")
|
||||
.font(.body)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
|
||||
// Level and Progress
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("Level \(user.profile.level)")
|
||||
.font(.title3)
|
||||
.bold()
|
||||
ProgressView(value: user.profile.levelingProgress)
|
||||
.progressViewStyle(LinearProgressViewStyle())
|
||||
.frame(height: 8)
|
||||
Text("Experience: \(user.profile.experience)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
// Bio
|
||||
if let bio = user.profile.bio, !bio.isEmpty {
|
||||
Text(bio)
|
||||
.font(.body)
|
||||
.multilineTextAlignment(.center)
|
||||
.foregroundColor(.secondary)
|
||||
.frame(alignment: .leading)
|
||||
} else {
|
||||
Text("No bio available")
|
||||
.font(.body)
|
||||
.foregroundColor(.secondary)
|
||||
.frame(alignment: .leading)
|
||||
}
|
||||
|
||||
// Member since
|
||||
Text("Joined at \(user.createdAt.formatted(.dateTime.month(.abbreviated).year()))")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
.frame(alignment: .leading)
|
||||
}
|
||||
.padding()
|
||||
// Load images when user data is available
|
||||
.task(id: user.profile.picture?.id) {
|
||||
if let serverUrl = appState.serverUrl, let pictureId = user.profile.picture?.id, let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl), let token = appState.token {
|
||||
await profileImageLoader.loadImage(from: imageUrl, token: token)
|
||||
}
|
||||
}
|
||||
.task(id: user.profile.background?.id) {
|
||||
if let serverUrl = appState.serverUrl, let backgroundId = user.profile.background?.id, let imageUrl = getAttachmentUrl(for: backgroundId, serverUrl: serverUrl), let token = appState.token {
|
||||
await bannerImageLoader.loadImage(from: imageUrl, token: token)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Text("No account data")
|
||||
.padding()
|
||||
}
|
||||
}
|
||||
.navigationTitle("Account")
|
||||
.confirmationDialog("Clear Status", isPresented: $showingClearConfirmation) {
|
||||
Button("Clear Status", role: .destructive) {
|
||||
Task {
|
||||
await clearStatus()
|
||||
}
|
||||
}
|
||||
Button("Cancel", role: .cancel) {}
|
||||
} message: {
|
||||
Text("Are you sure you want to clear your status? This action cannot be undone.")
|
||||
}
|
||||
.onAppear {
|
||||
Task.detached {
|
||||
await loadUserProfile()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func loadUserProfile() async {
|
||||
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||
error = NSError(domain: "AccountView", code: 1, userInfo: [NSLocalizedDescriptionKey: "Authentication not available"])
|
||||
return
|
||||
}
|
||||
|
||||
isLoading = true
|
||||
error = nil
|
||||
|
||||
do {
|
||||
user = try await networkService.fetchUserProfile(token: token, serverUrl: serverUrl)
|
||||
status = try await networkService.fetchAccountStatus(token: token, serverUrl: serverUrl)
|
||||
} catch {
|
||||
self.error = error
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
private func clearStatus() async {
|
||||
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||
error = NSError(domain: "AccountView", code: 1, userInfo: [NSLocalizedDescriptionKey: "Authentication not available"])
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
try await networkService.clearStatus(token: token, serverUrl: serverUrl)
|
||||
// Refresh status after clearing
|
||||
status = try await networkService.fetchAccountStatus(token: token, serverUrl: serverUrl)
|
||||
} catch {
|
||||
self.error = error
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
AccountView()
|
||||
.environmentObject(AppState())
|
||||
}
|
||||
86
ios/WatchRunner Watch App/Views/ActivityListView.swift
Normal file
86
ios/WatchRunner Watch App/Views/ActivityListView.swift
Normal file
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// ActivityListView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// MARK: - Views
|
||||
|
||||
struct ActivityListView: View {
|
||||
@StateObject private var viewModel: ActivityViewModel
|
||||
@EnvironmentObject var appState: AppState
|
||||
|
||||
init(filter: String, mockActivities: [SnActivity]? = nil) {
|
||||
_viewModel = StateObject(wrappedValue: ActivityViewModel(filter: filter, mockActivities: mockActivities))
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if viewModel.isLoading {
|
||||
ProgressView()
|
||||
} else if let errorMessage = viewModel.errorMessage {
|
||||
VStack {
|
||||
Text("Error fetching data")
|
||||
.font(.headline)
|
||||
Text(errorMessage)
|
||||
.font(.caption)
|
||||
.lineLimit(nil)
|
||||
}
|
||||
.padding()
|
||||
} else if viewModel.activities.isEmpty {
|
||||
Text("No activities found.")
|
||||
} else {
|
||||
List {
|
||||
ForEach(viewModel.activities) { activity in
|
||||
switch activity.type {
|
||||
case "posts.new", "posts.new.replies":
|
||||
if case .post(let post) = activity.data {
|
||||
NavigationLink(
|
||||
destination: PostDetailView(post: post).environmentObject(appState)
|
||||
) {
|
||||
PostRowView(post: post)
|
||||
}
|
||||
}
|
||||
case "discovery":
|
||||
if case .discovery(let discoveryData) = activity.data {
|
||||
DiscoveryView(discoveryData: discoveryData)
|
||||
}
|
||||
default:
|
||||
Text("Unknown activity type: \(activity.type)")
|
||||
}
|
||||
}
|
||||
if viewModel.hasMore {
|
||||
if viewModel.isLoadingMore {
|
||||
HStack {
|
||||
Spacer()
|
||||
ProgressView()
|
||||
Spacer()
|
||||
}
|
||||
} else {
|
||||
Button("Load More") {
|
||||
Task {
|
||||
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||
await viewModel.loadMoreActivities(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
if appState.isReady, let token = appState.token, let serverUrl = appState.serverUrl {
|
||||
Task.detached {
|
||||
await viewModel.fetchActivities(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle(viewModel.filter)
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
109
ios/WatchRunner Watch App/Views/AttachmentView.swift
Normal file
109
ios/WatchRunner Watch App/Views/AttachmentView.swift
Normal file
@@ -0,0 +1,109 @@
|
||||
//
|
||||
// AttachmentImageView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import AVKit
|
||||
import AVFoundation
|
||||
|
||||
struct AttachmentView: View {
|
||||
let attachment: SnCloudFile
|
||||
@EnvironmentObject var appState: AppState
|
||||
@StateObject private var imageLoader = ImageLoader()
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if let mimeType = attachment.mimeType {
|
||||
if mimeType.starts(with: "image") {
|
||||
if let serverUrl = appState.serverUrl, let imageUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
|
||||
NavigationLink(
|
||||
destination: ImageViewer(imageUrl: imageUrl).environmentObject(appState)
|
||||
) {
|
||||
if imageLoader.isLoading {
|
||||
ProgressView()
|
||||
} else if let image = imageLoader.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: .infinity)
|
||||
.cornerRadius(8)
|
||||
} else if let errorMessage = imageLoader.errorMessage {
|
||||
Text("Failed to load attachment: \(errorMessage)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
.cornerRadius(8)
|
||||
} else {
|
||||
Text("File: \(attachment.id)")
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
} else {
|
||||
Text("Image URL not available.")
|
||||
}
|
||||
} else if mimeType.starts(with: "video") {
|
||||
if let serverUrl = appState.serverUrl, let videoUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
|
||||
NavigationLink(destination: VideoPlayerView(videoUrl: videoUrl)) {
|
||||
if imageLoader.isLoading {
|
||||
ProgressView()
|
||||
} else if let image = imageLoader.image {
|
||||
ZStack {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: .infinity)
|
||||
.cornerRadius(8)
|
||||
|
||||
Image(systemName: "play.circle.fill")
|
||||
.resizable()
|
||||
.scaledToFit()
|
||||
.frame(width: 36, height: 36)
|
||||
.foregroundColor(.white)
|
||||
.shadow(color: .black.opacity(0.6), radius: 4, x: 0, y: 2)
|
||||
}
|
||||
} else if imageLoader.errorMessage != nil {
|
||||
Image(systemName: "play.rectangle.fill")
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: .infinity)
|
||||
.foregroundColor(.gray)
|
||||
.cornerRadius(8)
|
||||
} else {
|
||||
ProgressView()
|
||||
.cornerRadius(8)
|
||||
}
|
||||
}
|
||||
.buttonStyle(PlainButtonStyle())
|
||||
} else {
|
||||
Text("Video URL not available.")
|
||||
}
|
||||
} else if mimeType.starts(with: "audio") {
|
||||
if let serverUrl = appState.serverUrl, let audioUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
|
||||
AudioPlayerView(audioUrl: audioUrl)
|
||||
} else {
|
||||
Text("Cannot play audio: URL not available.")
|
||||
}
|
||||
} else {
|
||||
Text("Unsupported media type: \(mimeType)")
|
||||
}
|
||||
} else {
|
||||
Text("File: \(attachment.id) (No MIME type)")
|
||||
}
|
||||
}
|
||||
.task(id: attachment.id) {
|
||||
if let serverUrl = appState.serverUrl, let attachmentUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl), let token = appState.token {
|
||||
if attachment.mimeType?.starts(with: "image") == true {
|
||||
await imageLoader.loadImage(from: attachmentUrl, token: token)
|
||||
}
|
||||
if attachment.mimeType?.starts(with: "video") == true {
|
||||
let thumbnailUrl = attachmentUrl
|
||||
.appending(queryItems: [URLQueryItem(name: "thumbnail", value: "true")]) // Construct thumbnail URL
|
||||
await imageLoader.loadImage(from: thumbnailUrl, token: token)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
47
ios/WatchRunner Watch App/Views/AudioPlayerView.swift
Normal file
47
ios/WatchRunner Watch App/Views/AudioPlayerView.swift
Normal file
@@ -0,0 +1,47 @@
|
||||
|
||||
//
|
||||
// AudioPlayerView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import AVFoundation
|
||||
|
||||
struct AudioPlayerView: View {
|
||||
let audioUrl: URL
|
||||
@State private var player: AVPlayer?
|
||||
@State private var isPlaying: Bool = false
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if player != nil {
|
||||
Button(action: togglePlayPause) {
|
||||
Image(systemName: isPlaying ? "pause.circle.fill" : "play.circle.fill")
|
||||
.font(.largeTitle)
|
||||
}
|
||||
.buttonStyle(.plain)
|
||||
} else {
|
||||
Text("Loading audio...")
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
player = AVPlayer(url: audioUrl)
|
||||
}
|
||||
.onDisappear {
|
||||
player?.pause()
|
||||
player = nil
|
||||
}
|
||||
}
|
||||
|
||||
private func togglePlayPause() {
|
||||
guard let player = player else { return }
|
||||
if isPlaying {
|
||||
player.pause()
|
||||
} else {
|
||||
player.play()
|
||||
}
|
||||
isPlaying.toggle()
|
||||
}
|
||||
}
|
||||
551
ios/WatchRunner Watch App/Views/ChatView.swift
Normal file
551
ios/WatchRunner Watch App/Views/ChatView.swift
Normal file
@@ -0,0 +1,551 @@
|
||||
//
|
||||
// ChatView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/30.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ChatView: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@State private var selectedTab = 0
|
||||
@State private var chatRooms: [SnChatRoom] = []
|
||||
@State private var chatInvites: [SnChatMember] = []
|
||||
@State private var isLoading = false
|
||||
@State private var error: Error?
|
||||
@State private var showingInvites = false
|
||||
|
||||
private let tabs = ["All", "Direct", "Group"]
|
||||
|
||||
var body: some View {
|
||||
TabView(selection: $selectedTab) {
|
||||
ForEach(0..<tabs.count, id: \.self) { index in
|
||||
VStack {
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
} else if error != nil {
|
||||
VStack {
|
||||
Text("Error loading chats")
|
||||
.font(.caption)
|
||||
Button("Retry") {
|
||||
Task {
|
||||
await loadChatRooms()
|
||||
}
|
||||
}
|
||||
.font(.caption2)
|
||||
}
|
||||
} else {
|
||||
ChatRoomListView(
|
||||
chatRooms: filteredChatRooms(for: index),
|
||||
selectedTab: index
|
||||
)
|
||||
}
|
||||
}
|
||||
.tabItem {
|
||||
Text(tabs[index])
|
||||
}
|
||||
.tag(index)
|
||||
}
|
||||
}
|
||||
.tabViewStyle(.page)
|
||||
.navigationTitle("Chat")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .topBarTrailing) {
|
||||
Button {
|
||||
showingInvites = true
|
||||
} label: {
|
||||
ZStack {
|
||||
Image(systemName: "envelope")
|
||||
if !chatInvites.isEmpty {
|
||||
Circle()
|
||||
.fill(Color.red)
|
||||
.frame(width: 8, height: 8)
|
||||
.offset(x: 8, y: -8)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $showingInvites) {
|
||||
ChatInvitesView(invites: $chatInvites, appState: appState)
|
||||
}
|
||||
.onAppear {
|
||||
Task.detached {
|
||||
await loadChatRooms()
|
||||
await loadChatInvites()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func filteredChatRooms(for tabIndex: Int) -> [SnChatRoom] {
|
||||
switch tabIndex {
|
||||
case 0: // All
|
||||
return chatRooms
|
||||
case 1: // Direct
|
||||
return chatRooms.filter { $0.type == 1 }
|
||||
case 2: // Group
|
||||
return chatRooms.filter { $0.type != 1 }
|
||||
default:
|
||||
return chatRooms
|
||||
}
|
||||
}
|
||||
|
||||
private func loadChatRooms() async {
|
||||
guard let token = appState.token, let serverUrl = appState.serverUrl else { return }
|
||||
|
||||
isLoading = true
|
||||
error = nil
|
||||
|
||||
do {
|
||||
let response = try await appState.networkService.fetchChatRooms(token: token, serverUrl: serverUrl)
|
||||
chatRooms = response.rooms
|
||||
} catch {
|
||||
self.error = error
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
private func loadChatInvites() async {
|
||||
guard let token = appState.token, let serverUrl = appState.serverUrl else { return }
|
||||
|
||||
do {
|
||||
let response = try await appState.networkService.fetchChatInvites(token: token, serverUrl: serverUrl)
|
||||
chatInvites = response.invites
|
||||
} catch {
|
||||
// Handle error silently for invites
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatRoomListView: View {
|
||||
let chatRooms: [SnChatRoom]
|
||||
let selectedTab: Int
|
||||
|
||||
var body: some View {
|
||||
if chatRooms.isEmpty {
|
||||
VStack {
|
||||
Image(systemName: "message")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(.secondary)
|
||||
Text("No chats yet")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
} else {
|
||||
List(chatRooms) { room in
|
||||
ChatRoomListItem(room: room)
|
||||
}
|
||||
.listStyle(.plain)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatRoomListItem: View {
|
||||
let room: SnChatRoom
|
||||
@EnvironmentObject var appState: AppState
|
||||
@StateObject private var avatarLoader = ImageLoader()
|
||||
|
||||
private var displayName: String {
|
||||
if room.type == 1, let members = room.members, !members.isEmpty {
|
||||
// For direct messages, show the other member's name
|
||||
return members[0].account.nick
|
||||
} else {
|
||||
// For group chats, show room name or fallback
|
||||
return room.name ?? "Group Chat"
|
||||
}
|
||||
}
|
||||
|
||||
private var subtitle: String {
|
||||
if room.type == 1, let members = room.members, members.count > 1 {
|
||||
// For direct messages, show member usernames
|
||||
return members.map { "@\($0.account.name)" }.joined(separator: ", ")
|
||||
} else if let description = room.description {
|
||||
// For group chats with description
|
||||
return description
|
||||
} else {
|
||||
// Fallback
|
||||
return ""
|
||||
}
|
||||
}
|
||||
|
||||
private var avatarPictureId: String? {
|
||||
if room.type == 1, let members = room.members, !members.isEmpty {
|
||||
// For direct messages, use the other member's avatar
|
||||
return members[0].account.profile.picture?.id
|
||||
} else {
|
||||
// For group chats, use room picture
|
||||
return room.picture?.id
|
||||
}
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
NavigationLink(
|
||||
destination: ChatRoomView(room: room)
|
||||
.environmentObject(appState)
|
||||
) {
|
||||
HStack {
|
||||
// Avatar using ImageLoader pattern
|
||||
Group {
|
||||
if avatarLoader.isLoading {
|
||||
ProgressView()
|
||||
.frame(width: 32, height: 32)
|
||||
} else if let image = avatarLoader.image {
|
||||
image
|
||||
.resizable()
|
||||
.frame(width: 32, height: 32)
|
||||
.clipShape(Circle())
|
||||
} else if let errorMessage = avatarLoader.errorMessage {
|
||||
// Error state - show fallback
|
||||
Circle()
|
||||
.fill(Color.gray.opacity(0.3))
|
||||
.frame(width: 32, height: 32)
|
||||
.overlay(
|
||||
Text(displayName.prefix(1).uppercased())
|
||||
.font(.system(size: 12, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
)
|
||||
} else {
|
||||
// No image available - show initial
|
||||
Circle()
|
||||
.fill(Color.gray.opacity(0.3))
|
||||
.frame(width: 32, height: 32)
|
||||
.overlay(
|
||||
Text(displayName.prefix(1).uppercased())
|
||||
.font(.system(size: 12, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
)
|
||||
}
|
||||
}
|
||||
.task(id: avatarPictureId) {
|
||||
if let serverUrl = appState.serverUrl,
|
||||
let pictureId = avatarPictureId,
|
||||
let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl),
|
||||
let token = appState.token {
|
||||
await avatarLoader.loadImage(from: imageUrl, token: token)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(displayName)
|
||||
.font(.system(size: 14, weight: .medium))
|
||||
.lineLimit(1)
|
||||
|
||||
if !subtitle.isEmpty {
|
||||
Text(subtitle)
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.secondary)
|
||||
.lineLimit(1)
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
|
||||
// Unread count badge placeholder
|
||||
// In a full implementation, this would show unread count
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatRoomView: View {
|
||||
let room: SnChatRoom
|
||||
@EnvironmentObject var appState: AppState
|
||||
@State private var messages: [SnChatMessage] = []
|
||||
@State private var isLoading = false
|
||||
@State private var error: Error?
|
||||
|
||||
var body: some View {
|
||||
VStack {
|
||||
if isLoading {
|
||||
ProgressView()
|
||||
} else if error != nil {
|
||||
VStack {
|
||||
Text("Error loading messages")
|
||||
.font(.caption)
|
||||
Button("Retry") {
|
||||
Task {
|
||||
await loadMessages()
|
||||
}
|
||||
}
|
||||
.font(.caption2)
|
||||
}
|
||||
} else if messages.isEmpty {
|
||||
VStack {
|
||||
Image(systemName: "bubble.left")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(.secondary)
|
||||
Text("No messages yet")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
} else {
|
||||
ScrollViewReader { scrollView in
|
||||
ScrollView {
|
||||
LazyVStack(alignment: .leading, spacing: 8) {
|
||||
ForEach(messages) { message in
|
||||
ChatMessageItem(message: message)
|
||||
}
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
.onAppear {
|
||||
// Scroll to bottom when messages load
|
||||
if let lastMessage = messages.last {
|
||||
scrollView.scrollTo(lastMessage.id, anchor: .bottom)
|
||||
}
|
||||
}
|
||||
.onChange(of: messages.count) { _ in
|
||||
// Scroll to bottom when new messages arrive
|
||||
if let lastMessage = messages.last {
|
||||
withAnimation {
|
||||
scrollView.scrollTo(lastMessage.id, anchor: .bottom)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle(room.name ?? "Chat")
|
||||
.task {
|
||||
await loadMessages()
|
||||
}
|
||||
}
|
||||
|
||||
private func loadMessages() async {
|
||||
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||
isLoading = false
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
let messages = try await appState.networkService.fetchChatMessages(
|
||||
chatRoomId: room.id,
|
||||
token: token,
|
||||
serverUrl: serverUrl
|
||||
)
|
||||
// Sort with newest messages first (for flipped list, newest will appear at bottom)
|
||||
self.messages = messages.sorted { $0.createdAt < $1.createdAt }
|
||||
} catch {
|
||||
print("[watchOS] Error loading messages: \(error.localizedDescription)")
|
||||
self.error = error
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatMessageItem: View {
|
||||
let message: SnChatMessage
|
||||
@EnvironmentObject var appState: AppState
|
||||
@StateObject private var avatarLoader = ImageLoader()
|
||||
|
||||
private var avatarPictureId: String? {
|
||||
message.sender.account.profile.picture?.id
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
HStack(alignment: .top, spacing: 8) {
|
||||
// Avatar
|
||||
Group {
|
||||
if avatarLoader.isLoading {
|
||||
ProgressView()
|
||||
.frame(width: 24, height: 24)
|
||||
} else if let image = avatarLoader.image {
|
||||
image
|
||||
.resizable()
|
||||
.frame(width: 24, height: 24)
|
||||
.clipShape(Circle())
|
||||
} else {
|
||||
Circle()
|
||||
.fill(Color.gray.opacity(0.3))
|
||||
.frame(width: 24, height: 24)
|
||||
.overlay(
|
||||
Text(message.sender.account.nick.prefix(1).uppercased())
|
||||
.font(.system(size: 10, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
)
|
||||
}
|
||||
}
|
||||
.task(id: avatarPictureId) {
|
||||
if let serverUrl = appState.serverUrl,
|
||||
let pictureId = avatarPictureId,
|
||||
let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl),
|
||||
let token = appState.token {
|
||||
await avatarLoader.loadImage(from: imageUrl, token: token)
|
||||
}
|
||||
}
|
||||
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack {
|
||||
Text(message.sender.account.nick)
|
||||
.font(.system(size: 12, weight: .medium))
|
||||
Spacer()
|
||||
Text(message.createdAt, style: .time)
|
||||
.font(.system(size: 10))
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
if let content = message.content {
|
||||
Text(content)
|
||||
.font(.system(size: 14))
|
||||
.lineLimit(nil)
|
||||
.fixedSize(horizontal: false, vertical: true)
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 4)
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatInvitesView: View {
|
||||
@Binding var invites: [SnChatMember]
|
||||
let appState: AppState
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
@State private var isLoading = false
|
||||
|
||||
var body: some View {
|
||||
NavigationView {
|
||||
VStack {
|
||||
if invites.isEmpty {
|
||||
VStack {
|
||||
Image(systemName: "envelope.open")
|
||||
.font(.largeTitle)
|
||||
.foregroundColor(.secondary)
|
||||
Text("No invites")
|
||||
.font(.caption)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
} else {
|
||||
List(invites) { invite in
|
||||
ChatInviteItem(invite: invite, appState: appState, invites: $invites)
|
||||
}
|
||||
.listStyle(.plain)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Invites")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct ChatInviteItem: View {
|
||||
let invite: SnChatMember
|
||||
let appState: AppState
|
||||
@Binding var invites: [SnChatMember]
|
||||
@State private var isAccepting = false
|
||||
@State private var isDeclining = false
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
HStack {
|
||||
Circle()
|
||||
.fill(Color.gray.opacity(0.3))
|
||||
.frame(width: 24, height: 24)
|
||||
.overlay(
|
||||
Text((invite.chatRoom?.name ?? "C").prefix(1).uppercased())
|
||||
.font(.system(size: 10, weight: .medium))
|
||||
.foregroundColor(.primary)
|
||||
)
|
||||
|
||||
VStack(alignment: .leading, spacing: 2) {
|
||||
Text(invite.chatRoom?.name ?? "Unknown Chat")
|
||||
.font(.system(size: 14, weight: .medium))
|
||||
.lineLimit(1)
|
||||
|
||||
HStack(spacing: 4) {
|
||||
Text(invite.role == 100 ? "Owner" : invite.role >= 50 ? "Moderator" : "Member")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
if invite.chatRoom?.type == 1 {
|
||||
Text("Direct")
|
||||
.font(.system(size: 12))
|
||||
.foregroundColor(.blue)
|
||||
.padding(.horizontal, 4)
|
||||
.padding(.vertical, 2)
|
||||
.background(Color.blue.opacity(0.1))
|
||||
.cornerRadius(4)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Spacer()
|
||||
}
|
||||
|
||||
HStack(spacing: 8) {
|
||||
Button {
|
||||
Task {
|
||||
await acceptInvite()
|
||||
}
|
||||
} label: {
|
||||
if isAccepting {
|
||||
ProgressView()
|
||||
.frame(width: 20, height: 20)
|
||||
} else {
|
||||
Image(systemName: "checkmark")
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
}
|
||||
.disabled(isAccepting || isDeclining)
|
||||
|
||||
Button {
|
||||
Task {
|
||||
await declineInvite()
|
||||
}
|
||||
} label: {
|
||||
if isDeclining {
|
||||
ProgressView()
|
||||
.frame(width: 20, height: 20)
|
||||
} else {
|
||||
Image(systemName: "xmark")
|
||||
.frame(width: 20, height: 20)
|
||||
}
|
||||
}
|
||||
.disabled(isAccepting || isDeclining)
|
||||
}
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
|
||||
private func acceptInvite() async {
|
||||
guard let token = appState.token,
|
||||
let serverUrl = appState.serverUrl,
|
||||
let chatRoomId = invite.chatRoom?.id else { return }
|
||||
|
||||
isAccepting = true
|
||||
|
||||
do {
|
||||
try await appState.networkService.acceptChatInvite(chatRoomId: chatRoomId, token: token, serverUrl: serverUrl)
|
||||
// Remove from invites list
|
||||
invites.removeAll { $0.id == invite.id }
|
||||
} catch {
|
||||
// Handle error - could show alert
|
||||
print("Failed to accept invite: \(error)")
|
||||
}
|
||||
|
||||
isAccepting = false
|
||||
}
|
||||
|
||||
private func declineInvite() async {
|
||||
guard let token = appState.token,
|
||||
let serverUrl = appState.serverUrl,
|
||||
let chatRoomId = invite.chatRoom?.id else { return }
|
||||
|
||||
isDeclining = true
|
||||
|
||||
do {
|
||||
try await appState.networkService.declineChatInvite(chatRoomId: chatRoomId, token: token, serverUrl: serverUrl)
|
||||
// Remove from invites list
|
||||
invites.removeAll { $0.id == invite.id }
|
||||
} catch {
|
||||
// Handle error - could show alert
|
||||
print("Failed to decline invite: \(error)")
|
||||
}
|
||||
|
||||
isDeclining = false
|
||||
}
|
||||
}
|
||||
53
ios/WatchRunner Watch App/Views/ComposePostView.swift
Normal file
53
ios/WatchRunner Watch App/Views/ComposePostView.swift
Normal file
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// ComposePostView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct ComposePostView: View {
|
||||
@StateObject private var viewModel = ComposePostViewModel()
|
||||
@EnvironmentObject var appState: AppState
|
||||
@Environment(\.dismiss) private var dismiss
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
Form {
|
||||
TextField("Title", text: $viewModel.title)
|
||||
TextField("Content", text: $viewModel.content)
|
||||
}
|
||||
.navigationTitle("New Post")
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .cancellationAction) {
|
||||
Button("Cancel", systemImage: "xmark") {
|
||||
dismiss()
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
}
|
||||
ToolbarItem(placement: .confirmationAction) {
|
||||
Button("Post", systemImage: "square.and.arrow.up") {
|
||||
Task {
|
||||
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||
await viewModel.createPost(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
.labelStyle(.iconOnly)
|
||||
.disabled(viewModel.isPosting)
|
||||
}
|
||||
}
|
||||
.onChange(of: viewModel.didPost) {
|
||||
if viewModel.didPost {
|
||||
dismiss()
|
||||
}
|
||||
}
|
||||
.alert("Error", isPresented: .constant(viewModel.errorMessage != nil), actions: {
|
||||
Button("OK") { viewModel.errorMessage = nil }
|
||||
}, message: {
|
||||
Text(viewModel.errorMessage ?? "")
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
110
ios/WatchRunner Watch App/Views/DiscoveryViews.swift
Normal file
110
ios/WatchRunner Watch App/Views/DiscoveryViews.swift
Normal file
@@ -0,0 +1,110 @@
|
||||
//
|
||||
// DiscoveryViews.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct DiscoveryView: View {
|
||||
let discoveryData: DiscoveryData
|
||||
|
||||
var body: some View {
|
||||
NavigationLink(destination: DiscoveryDetailView(discoveryData: discoveryData)) {
|
||||
VStack(alignment: .leading) {
|
||||
Text("Discovery")
|
||||
.font(.headline)
|
||||
Text("\(discoveryData.items.count) new items to discover")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct DiscoveryDetailView: View {
|
||||
let discoveryData: DiscoveryData
|
||||
|
||||
var body: some View {
|
||||
List(discoveryData.items) { item in
|
||||
NavigationLink(destination: destinationView(for: item)) {
|
||||
itemView(for: item)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Discovery")
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func itemView(for item: DiscoveryItem) -> some View {
|
||||
VStack(alignment: .leading) {
|
||||
switch item.data {
|
||||
case .realm(let realm):
|
||||
Text("Realm").font(.headline)
|
||||
Text(realm.name).foregroundColor(.secondary)
|
||||
case .publisher(let publisher):
|
||||
Text("Publisher").font(.headline)
|
||||
Text(publisher.name).foregroundColor(.secondary)
|
||||
case .article(let article):
|
||||
Text("Article").font(.headline)
|
||||
Text(article.title).foregroundColor(.secondary)
|
||||
case .unknown:
|
||||
Text("Unknown item")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ViewBuilder
|
||||
private func destinationView(for item: DiscoveryItem) -> some View {
|
||||
switch item.data {
|
||||
case .realm(let realm):
|
||||
RealmDetailView(realm: realm)
|
||||
case .publisher(let publisher):
|
||||
PublisherDetailView(publisher: publisher)
|
||||
case .article(let article):
|
||||
ArticleDetailView(article: article)
|
||||
case .unknown:
|
||||
Text("Detail view not available")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct RealmDetailView: View {
|
||||
let realm: SnRealm
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text(realm.name).font(.headline)
|
||||
if let description = realm.description {
|
||||
Text(description).font(.body)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Realm")
|
||||
}
|
||||
}
|
||||
|
||||
struct PublisherDetailView: View {
|
||||
let publisher: SnPublisher
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text(publisher.name).font(.headline)
|
||||
if let description = publisher.description {
|
||||
Text(description).font(.body)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Publisher")
|
||||
}
|
||||
}
|
||||
|
||||
struct ArticleDetailView: View {
|
||||
let article: SnWebArticle
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text(article.title).font(.headline)
|
||||
Text(article.url).font(.caption).foregroundColor(.secondary)
|
||||
}
|
||||
.navigationTitle("Article")
|
||||
}
|
||||
}
|
||||
62
ios/WatchRunner Watch App/Views/ExploreView.swift
Normal file
62
ios/WatchRunner Watch App/Views/ExploreView.swift
Normal file
@@ -0,0 +1,62 @@
|
||||
//
|
||||
// ExploreView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
// The main view with the TabView for filtering.
|
||||
struct ExploreView: View {
|
||||
@StateObject private var appState = AppState()
|
||||
@State private var isComposing = false
|
||||
@State private var selectedTab: String = "Explore"
|
||||
|
||||
var body: some View {
|
||||
NavigationStack {
|
||||
if appState.isReady {
|
||||
TabView(selection: $selectedTab) {
|
||||
ActivityListView(filter: "Explore")
|
||||
.tag("Explore")
|
||||
.tabItem {
|
||||
Label("Explore", systemImage: "safari")
|
||||
}
|
||||
.labelStyle(.titleOnly)
|
||||
|
||||
ActivityListView(filter: "Subscriptions")
|
||||
.tag("Subscriptions")
|
||||
.tabItem {
|
||||
Label("Subscriptions", systemImage: "star")
|
||||
}
|
||||
.labelStyle(.titleOnly)
|
||||
|
||||
ActivityListView(filter: "Friends")
|
||||
.tag("Friends")
|
||||
.tabItem {
|
||||
Label("Friends", systemImage: "person.2")
|
||||
}
|
||||
.labelStyle(.titleOnly)
|
||||
}
|
||||
.navigationTitle(selectedTab)
|
||||
.toolbar {
|
||||
ToolbarItem(placement: .primaryAction) {
|
||||
Button(action: { isComposing = true }) {
|
||||
Label("Compose", systemImage: "plus")
|
||||
}
|
||||
}
|
||||
}
|
||||
.environmentObject(appState)
|
||||
} else {
|
||||
ProgressView { Text("Connecting to phone...") }
|
||||
.onAppear {
|
||||
appState.requestData()
|
||||
}
|
||||
}
|
||||
}
|
||||
.sheet(isPresented: $isComposing) {
|
||||
ComposePostView()
|
||||
.environmentObject(appState)
|
||||
}
|
||||
}
|
||||
}
|
||||
34
ios/WatchRunner Watch App/Views/ImageViewer.swift
Normal file
34
ios/WatchRunner Watch App/Views/ImageViewer.swift
Normal file
@@ -0,0 +1,34 @@
|
||||
import SwiftUI
|
||||
|
||||
struct ImageViewer: View {
|
||||
let imageUrl: URL
|
||||
@EnvironmentObject var appState: AppState
|
||||
@StateObject private var imageLoader = ImageLoader()
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if imageLoader.isLoading {
|
||||
ProgressView()
|
||||
} else if let image = imageLoader.image {
|
||||
image
|
||||
.resizable()
|
||||
.aspectRatio(contentMode: .fit)
|
||||
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||
.scaledToFit()
|
||||
} else if let errorMessage = imageLoader.errorMessage {
|
||||
Text("Failed to load image: \(errorMessage)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
} else {
|
||||
Text("Failed to load image.")
|
||||
}
|
||||
}
|
||||
.task(id: imageUrl) {
|
||||
if let token = appState.token {
|
||||
await imageLoader.loadImage(from: imageUrl, token: token)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Image")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
198
ios/WatchRunner Watch App/Views/NotificationView.swift
Normal file
198
ios/WatchRunner Watch App/Views/NotificationView.swift
Normal file
@@ -0,0 +1,198 @@
|
||||
|
||||
//
|
||||
// NotificationView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
import Combine
|
||||
|
||||
@MainActor
|
||||
class NotificationViewModel: ObservableObject {
|
||||
@Published var notifications = [SnNotification]()
|
||||
@Published var isLoading = false
|
||||
@Published var isLoadingMore = false
|
||||
@Published var errorMessage: String?
|
||||
@Published var hasMore = false
|
||||
|
||||
private let networkService = NetworkService()
|
||||
private var hasFetched = false
|
||||
private var offset = 0
|
||||
private let pageSize = 20
|
||||
|
||||
func fetchNotifications(token: String, serverUrl: String) async {
|
||||
if hasFetched { return }
|
||||
guard !isLoading else { return }
|
||||
isLoading = true
|
||||
errorMessage = nil
|
||||
hasFetched = true
|
||||
offset = 0
|
||||
|
||||
do {
|
||||
let response = try await networkService.fetchNotifications(offset: offset, take: pageSize, token: token, serverUrl: serverUrl)
|
||||
self.notifications = response.notifications
|
||||
self.hasMore = response.hasMore
|
||||
offset += response.notifications.count
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
print("[watchOS] fetchNotifications failed with error: \(error)")
|
||||
hasFetched = false
|
||||
}
|
||||
|
||||
isLoading = false
|
||||
}
|
||||
|
||||
func loadMoreNotifications(token: String, serverUrl: String) async {
|
||||
guard !isLoadingMore && hasMore else { return }
|
||||
isLoadingMore = true
|
||||
|
||||
do {
|
||||
let response = try await networkService.fetchNotifications(offset: offset, take: pageSize, token: token, serverUrl: serverUrl)
|
||||
self.notifications.append(contentsOf: response.notifications)
|
||||
self.hasMore = response.hasMore
|
||||
offset += response.notifications.count
|
||||
} catch {
|
||||
self.errorMessage = error.localizedDescription
|
||||
print("[watchOS] loadMoreNotifications failed with error: \(error)")
|
||||
}
|
||||
|
||||
isLoadingMore = false
|
||||
}
|
||||
}
|
||||
|
||||
struct NotificationView: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@StateObject private var viewModel = NotificationViewModel()
|
||||
|
||||
var body: some View {
|
||||
Group {
|
||||
if viewModel.isLoading {
|
||||
ProgressView()
|
||||
} else if let errorMessage = viewModel.errorMessage {
|
||||
VStack {
|
||||
Text("Error")
|
||||
.font(.headline)
|
||||
Text(errorMessage)
|
||||
.font(.caption)
|
||||
Button("Retry") {
|
||||
Task {
|
||||
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||
await viewModel.fetchNotifications(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
} else if viewModel.notifications.isEmpty {
|
||||
Text("No notifications")
|
||||
} else {
|
||||
List {
|
||||
ForEach(viewModel.notifications) { notification in
|
||||
NavigationLink(destination: NotificationDetailView(notification: notification)) {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack {
|
||||
Text(notification.title)
|
||||
.font(.headline)
|
||||
Spacer()
|
||||
if notification.viewedAt == nil {
|
||||
Circle()
|
||||
.fill(Color.blue)
|
||||
.frame(width: 8, height: 8)
|
||||
}
|
||||
}
|
||||
if !notification.subtitle.isEmpty {
|
||||
Text(notification.subtitle)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
if notification.content.count > 100 {
|
||||
Text(notification.content.prefix(100) + "...")
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
.lineLimit(2)
|
||||
} else {
|
||||
Text(notification.content)
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
.lineLimit(2)
|
||||
}
|
||||
Text(notification.createdAt, style: .relative)
|
||||
.font(.caption2)
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
.padding(.vertical, 8)
|
||||
}
|
||||
}
|
||||
if viewModel.hasMore {
|
||||
if viewModel.isLoadingMore {
|
||||
HStack {
|
||||
Spacer()
|
||||
ProgressView()
|
||||
Spacer()
|
||||
}
|
||||
} else {
|
||||
Button("Load More") {
|
||||
Task {
|
||||
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||
await viewModel.loadMoreNotifications(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
.frame(maxWidth: .infinity)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.onAppear {
|
||||
if appState.isReady, let token = appState.token, let serverUrl = appState.serverUrl {
|
||||
Task.detached {
|
||||
await viewModel.fetchNotifications(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
}
|
||||
}
|
||||
.navigationTitle("Notifications")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
|
||||
struct NotificationDetailView: View {
|
||||
let notification: SnNotification
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 16) {
|
||||
Text(notification.title)
|
||||
.font(.headline)
|
||||
|
||||
if !notification.subtitle.isEmpty {
|
||||
Text(notification.subtitle)
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
}
|
||||
|
||||
Text(notification.content)
|
||||
.font(.body)
|
||||
|
||||
HStack {
|
||||
Text(notification.createdAt, style: .date)
|
||||
Text("·")
|
||||
Text(notification.createdAt, style: .time)
|
||||
}
|
||||
.font(.caption)
|
||||
.foregroundColor(.gray)
|
||||
|
||||
if notification.viewedAt == nil {
|
||||
Text("Unread")
|
||||
.font(.caption)
|
||||
.foregroundColor(.blue)
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.navigationTitle("Notification")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
}
|
||||
151
ios/WatchRunner Watch App/Views/PostViews.swift
Normal file
151
ios/WatchRunner Watch App/Views/PostViews.swift
Normal file
@@ -0,0 +1,151 @@
|
||||
//
|
||||
// PostViews.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct PostRowView: View {
|
||||
let post: SnPost
|
||||
@EnvironmentObject var appState: AppState
|
||||
@StateObject private var imageLoader = ImageLoader() // Instantiate ImageLoader
|
||||
|
||||
var body: some View {
|
||||
VStack(alignment: .leading, spacing: 4) {
|
||||
HStack {
|
||||
if imageLoader.isLoading {
|
||||
ProgressView()
|
||||
.frame(width: 24, height: 24)
|
||||
} else if let image = imageLoader.image {
|
||||
image
|
||||
.resizable()
|
||||
.frame(width: 24, height: 24)
|
||||
.clipShape(Circle())
|
||||
} else if let errorMessage = imageLoader.errorMessage {
|
||||
Text("Failed: \(errorMessage)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
.frame(width: 24, height: 24)
|
||||
} else {
|
||||
// Placeholder if no image and not loading
|
||||
Image(systemName: "person.circle.fill")
|
||||
.resizable()
|
||||
.frame(width: 24, height: 24)
|
||||
.clipShape(Circle())
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
Text(post.publisher.nick ?? post.publisher.name)
|
||||
.font(.subheadline)
|
||||
.bold()
|
||||
}
|
||||
.task(id: post.publisher.picture?.id) { // Use task(id:) to reload image when pictureId changes
|
||||
if let serverUrl = appState.serverUrl, let pictureId = post.publisher.picture?.id, let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl), let token = appState.token {
|
||||
await imageLoader.loadImage(from: imageUrl, token: token)
|
||||
}
|
||||
}
|
||||
|
||||
if let title = post.title, !title.isEmpty {
|
||||
Text(title)
|
||||
.font(.headline)
|
||||
}
|
||||
|
||||
if let content = post.content, !content.isEmpty {
|
||||
Text(content)
|
||||
.font(.body)
|
||||
}
|
||||
|
||||
if !post.attachments.isEmpty {
|
||||
AttachmentView(attachment: post.attachments[0])
|
||||
if post.attachments.count > 1 {
|
||||
HStack(spacing: 8) {
|
||||
Image(systemName: "paperclip.circle.fill")
|
||||
.frame(width: 12, height: 12)
|
||||
.foregroundStyle(.gray)
|
||||
Text("\(post.attachments.count - 1)+ attachments")
|
||||
.font(.footnote)
|
||||
.foregroundStyle(.gray)
|
||||
}
|
||||
}
|
||||
}
|
||||
}.padding(.vertical)
|
||||
}
|
||||
}
|
||||
|
||||
struct PostDetailView: View {
|
||||
let post: SnPost
|
||||
@EnvironmentObject var appState: AppState
|
||||
@StateObject private var publisherImageLoader = ImageLoader() // Instantiate ImageLoader for publisher avatar
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
HStack {
|
||||
if publisherImageLoader.isLoading {
|
||||
ProgressView()
|
||||
.frame(width: 32, height: 32)
|
||||
} else if let image = publisherImageLoader.image {
|
||||
image
|
||||
.resizable()
|
||||
.frame(width: 32, height: 32)
|
||||
.clipShape(Circle())
|
||||
} else if let errorMessage = publisherImageLoader.errorMessage {
|
||||
Text("Failed: \(errorMessage)")
|
||||
.font(.caption)
|
||||
.foregroundColor(.red)
|
||||
.frame(width: 32, height: 32)
|
||||
} else {
|
||||
Image(systemName: "person.circle.fill")
|
||||
.resizable()
|
||||
.frame(width: 32, height: 32)
|
||||
.clipShape(Circle())
|
||||
.foregroundColor(.gray)
|
||||
}
|
||||
Text("@\(post.publisher.name)")
|
||||
.font(.headline)
|
||||
}
|
||||
// Use task(id:) to reload image when pictureId changes
|
||||
.task(id: post.publisher.picture?.id) {
|
||||
if let serverUrl = appState.serverUrl, let pictureId = post.publisher.picture?.id, let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl), let token = appState.token {
|
||||
await publisherImageLoader.loadImage(from: imageUrl, token: token)
|
||||
}
|
||||
}
|
||||
|
||||
if let title = post.title, !title.isEmpty {
|
||||
Text(title)
|
||||
.font(.title2)
|
||||
.bold()
|
||||
}
|
||||
|
||||
if let content = post.content, !content.isEmpty {
|
||||
Text(content)
|
||||
.font(.body)
|
||||
}
|
||||
|
||||
if !post.attachments.isEmpty {
|
||||
Text("Attachments").font(.headline)
|
||||
ForEach(post.attachments) { attachment in
|
||||
AttachmentView(attachment: attachment)
|
||||
}
|
||||
}
|
||||
|
||||
if !post.tags.isEmpty {
|
||||
Text("Tags").font(.headline)
|
||||
FlowLayout(alignment: .leading, spacing: 4) {
|
||||
ForEach(post.tags) { tag in
|
||||
Text("#\(tag.name ?? tag.slug)")
|
||||
.font(.caption)
|
||||
.padding(.horizontal, 8)
|
||||
.padding(.vertical, 3)
|
||||
.background(Capsule().fill(Color.accentColor.opacity(0.2)))
|
||||
.cornerRadius(5)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.padding()
|
||||
}
|
||||
.navigationTitle("Post")
|
||||
}
|
||||
}
|
||||
132
ios/WatchRunner Watch App/Views/StatusCreationView.swift
Normal file
132
ios/WatchRunner Watch App/Views/StatusCreationView.swift
Normal file
@@ -0,0 +1,132 @@
|
||||
//
|
||||
// StatusCreationView.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/30.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
struct StatusCreationView: View {
|
||||
@EnvironmentObject var appState: AppState
|
||||
@Environment(\.dismiss) var dismiss
|
||||
|
||||
let initialStatus: SnAccountStatus?
|
||||
|
||||
@State private var attitude: Int
|
||||
@State private var isInvisible: Bool
|
||||
@State private var isNotDisturb: Bool
|
||||
@State private var label: String
|
||||
@State private var isSubmitting: Bool = false
|
||||
@State private var error: Error? = nil
|
||||
|
||||
private let networkService = NetworkService()
|
||||
|
||||
init(initialStatus: SnAccountStatus? = nil) {
|
||||
self.initialStatus = initialStatus
|
||||
_attitude = State(initialValue: initialStatus?.attitude ?? 1)
|
||||
_isInvisible = State(initialValue: initialStatus?.isInvisible ?? false)
|
||||
_isNotDisturb = State(initialValue: initialStatus?.isNotDisturb ?? false)
|
||||
_label = State(initialValue: initialStatus?.label ?? "")
|
||||
}
|
||||
|
||||
var body: some View {
|
||||
ScrollView {
|
||||
VStack(spacing: 16) {
|
||||
// Title
|
||||
Text("Set Status")
|
||||
.font(.headline)
|
||||
.padding(.top)
|
||||
|
||||
// Label TextField
|
||||
TextField("Status label", text: $label)
|
||||
.textFieldStyle(.automatic)
|
||||
.padding(.horizontal)
|
||||
|
||||
// Attitude Picker
|
||||
VStack(alignment: .leading, spacing: 8) {
|
||||
Text("Mood")
|
||||
.font(.subheadline)
|
||||
.foregroundColor(.secondary)
|
||||
|
||||
Picker("Attitude", selection: $attitude) {
|
||||
Text("😊 Positive").tag(0)
|
||||
Text("😐 Neutral").tag(1)
|
||||
Text("😢 Negative").tag(2)
|
||||
}
|
||||
.pickerStyle(.wheel)
|
||||
.frame(height: 80)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
|
||||
// Toggles
|
||||
VStack(spacing: 12) {
|
||||
Toggle("Invisible", isOn: $isInvisible)
|
||||
.padding(.horizontal)
|
||||
|
||||
Toggle("Do Not Disturb", isOn: $isNotDisturb)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
|
||||
// Error message
|
||||
if let error = error {
|
||||
Text("Error: \(error.localizedDescription)")
|
||||
.foregroundColor(.red)
|
||||
.font(.caption)
|
||||
.padding(.horizontal)
|
||||
}
|
||||
|
||||
// Buttons
|
||||
HStack(spacing: 12) {
|
||||
Button("Cancel") {
|
||||
dismiss()
|
||||
}
|
||||
.buttonStyle(.glass)
|
||||
|
||||
Button(isSubmitting ? "Saving..." : "Save") {
|
||||
Task {
|
||||
await submitStatus()
|
||||
}
|
||||
}
|
||||
.buttonStyle(.glassProminent)
|
||||
.disabled(isSubmitting)
|
||||
}
|
||||
.padding(.horizontal)
|
||||
.padding(.bottom)
|
||||
}
|
||||
}
|
||||
.navigationTitle("Status")
|
||||
.navigationBarTitleDisplayMode(.inline)
|
||||
}
|
||||
|
||||
private func submitStatus() async {
|
||||
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||
error = NSError(domain: "StatusCreationView", code: 1, userInfo: [NSLocalizedDescriptionKey: "Authentication not available"])
|
||||
return
|
||||
}
|
||||
|
||||
isSubmitting = true
|
||||
error = nil
|
||||
|
||||
do {
|
||||
_ = try await networkService.createOrUpdateStatus(
|
||||
attitude: attitude,
|
||||
isInvisible: isInvisible,
|
||||
isNotDisturb: isNotDisturb,
|
||||
label: label.isEmpty ? nil : label,
|
||||
token: token,
|
||||
serverUrl: serverUrl
|
||||
)
|
||||
dismiss()
|
||||
} catch {
|
||||
self.error = error
|
||||
}
|
||||
|
||||
isSubmitting = false
|
||||
}
|
||||
}
|
||||
|
||||
#Preview {
|
||||
StatusCreationView()
|
||||
.environmentObject(AppState())
|
||||
}
|
||||
12
ios/WatchRunner Watch App/Views/VideoPlayerView.swift
Normal file
12
ios/WatchRunner Watch App/Views/VideoPlayerView.swift
Normal file
@@ -0,0 +1,12 @@
|
||||
import SwiftUI
|
||||
import AVKit
|
||||
import AVFoundation
|
||||
|
||||
struct VideoPlayerView: View {
|
||||
let videoUrl: URL
|
||||
|
||||
var body: some View {
|
||||
VideoPlayer(player: AVPlayer(url: videoUrl))
|
||||
.edgesIgnoringSafeArea(.all) // Make it full screen
|
||||
}
|
||||
}
|
||||
17
ios/WatchRunner Watch App/WatchRunnerApp.swift
Normal file
17
ios/WatchRunner Watch App/WatchRunnerApp.swift
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// WatchRunnerApp.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/28.
|
||||
//
|
||||
|
||||
import SwiftUI
|
||||
|
||||
@main
|
||||
struct WatchRunner_Watch_AppApp: App {
|
||||
var body: some Scene {
|
||||
WindowGroup {
|
||||
ContentView()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
import 'package:drift/drift.dart';
|
||||
import 'package:drift/wasm.dart';
|
||||
import 'package:island/database/drift_db.dart';
|
||||
import 'package:island/talker.dart';
|
||||
|
||||
AppDatabase constructDb() {
|
||||
return AppDatabase(connectOnWeb());
|
||||
@@ -16,8 +17,8 @@ DatabaseConnection connectOnWeb() {
|
||||
driftWorkerUri: Uri.parse('drift_worker.dart.js'),
|
||||
);
|
||||
return result.resolvedExecutor;
|
||||
} catch (e) {
|
||||
print('Failed to open WASM database: $e');
|
||||
} catch (e, stackTrace) {
|
||||
talker.error('Failed to open WASM database...', e, stackTrace);
|
||||
rethrow;
|
||||
}
|
||||
}),
|
||||
|
||||
@@ -120,13 +120,24 @@ void main() async {
|
||||
windowButtonVisibility: true,
|
||||
);
|
||||
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||
final env = Platform.environment;
|
||||
final isWayland = env.containsKey('WAYLAND_DISPLAY');
|
||||
|
||||
if (isWayland) {
|
||||
try {
|
||||
await windowManager.setAsFrameless();
|
||||
} catch (e) {
|
||||
debugPrint('[Wayland] setAsFrameless failed: $e');
|
||||
}
|
||||
}
|
||||
await windowManager.setMinimumSize(defaultSize);
|
||||
await windowManager.show();
|
||||
await windowManager.focus();
|
||||
final opacity = prefs.getDouble(kAppWindowOpacity) ?? 1.0;
|
||||
await windowManager.setOpacity(opacity);
|
||||
talker.info(
|
||||
"[SplashScreen] Desktop window is ready with size: ${initialSize.width}x${initialSize.height}",
|
||||
"[SplashScreen] Desktop window is ready with size: ${initialSize.width}x${initialSize.height}"
|
||||
"${isWayland ? " (Wayland frameless fix applied)" : ""}",
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
@@ -55,6 +55,19 @@ class ProfileLinkConverter
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class UsernameColor with _$UsernameColor {
|
||||
const factory UsernameColor({
|
||||
@Default('plain') String type,
|
||||
String? value,
|
||||
String? direction,
|
||||
List<String>? colors,
|
||||
}) = _UsernameColor;
|
||||
|
||||
factory UsernameColor.fromJson(Map<String, dynamic> json) =>
|
||||
_$UsernameColorFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnAccountProfile with _$SnAccountProfile {
|
||||
const factory SnAccountProfile({
|
||||
@@ -79,6 +92,7 @@ sealed class SnAccountProfile with _$SnAccountProfile {
|
||||
required SnCloudFile? picture,
|
||||
required SnCloudFile? background,
|
||||
required SnVerificationMark? verification,
|
||||
UsernameColor? usernameColor,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
|
||||
@@ -622,10 +622,284 @@ as String,
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$UsernameColor {
|
||||
|
||||
String get type; String? get value; String? get direction; List<String>? get colors;
|
||||
/// Create a copy of UsernameColor
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$UsernameColorCopyWith<UsernameColor> get copyWith => _$UsernameColorCopyWithImpl<UsernameColor>(this as UsernameColor, _$identity);
|
||||
|
||||
/// Serializes this UsernameColor to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is UsernameColor&&(identical(other.type, type) || other.type == type)&&(identical(other.value, value) || other.value == value)&&(identical(other.direction, direction) || other.direction == direction)&&const DeepCollectionEquality().equals(other.colors, colors));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,type,value,direction,const DeepCollectionEquality().hash(colors));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'UsernameColor(type: $type, value: $value, direction: $direction, colors: $colors)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $UsernameColorCopyWith<$Res> {
|
||||
factory $UsernameColorCopyWith(UsernameColor value, $Res Function(UsernameColor) _then) = _$UsernameColorCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String type, String? value, String? direction, List<String>? colors
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$UsernameColorCopyWithImpl<$Res>
|
||||
implements $UsernameColorCopyWith<$Res> {
|
||||
_$UsernameColorCopyWithImpl(this._self, this._then);
|
||||
|
||||
final UsernameColor _self;
|
||||
final $Res Function(UsernameColor) _then;
|
||||
|
||||
/// Create a copy of UsernameColor
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? value = freezed,Object? direction = freezed,Object? colors = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String,value: freezed == value ? _self.value : value // ignore: cast_nullable_to_non_nullable
|
||||
as String?,direction: freezed == direction ? _self.direction : direction // ignore: cast_nullable_to_non_nullable
|
||||
as String?,colors: freezed == colors ? _self.colors : colors // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [UsernameColor].
|
||||
extension UsernameColorPatterns on UsernameColor {
|
||||
/// 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( _UsernameColor value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _UsernameColor() 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( _UsernameColor value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _UsernameColor():
|
||||
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( _UsernameColor value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _UsernameColor() 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 type, String? value, String? direction, List<String>? colors)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _UsernameColor() when $default != null:
|
||||
return $default(_that.type,_that.value,_that.direction,_that.colors);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 type, String? value, String? direction, List<String>? colors) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _UsernameColor():
|
||||
return $default(_that.type,_that.value,_that.direction,_that.colors);}
|
||||
}
|
||||
/// 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 type, String? value, String? direction, List<String>? colors)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _UsernameColor() when $default != null:
|
||||
return $default(_that.type,_that.value,_that.direction,_that.colors);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _UsernameColor implements UsernameColor {
|
||||
const _UsernameColor({this.type = 'plain', this.value, this.direction, final List<String>? colors}): _colors = colors;
|
||||
factory _UsernameColor.fromJson(Map<String, dynamic> json) => _$UsernameColorFromJson(json);
|
||||
|
||||
@override@JsonKey() final String type;
|
||||
@override final String? value;
|
||||
@override final String? direction;
|
||||
final List<String>? _colors;
|
||||
@override List<String>? get colors {
|
||||
final value = _colors;
|
||||
if (value == null) return null;
|
||||
if (_colors is EqualUnmodifiableListView) return _colors;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of UsernameColor
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$UsernameColorCopyWith<_UsernameColor> get copyWith => __$UsernameColorCopyWithImpl<_UsernameColor>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$UsernameColorToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _UsernameColor&&(identical(other.type, type) || other.type == type)&&(identical(other.value, value) || other.value == value)&&(identical(other.direction, direction) || other.direction == direction)&&const DeepCollectionEquality().equals(other._colors, _colors));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,type,value,direction,const DeepCollectionEquality().hash(_colors));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'UsernameColor(type: $type, value: $value, direction: $direction, colors: $colors)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$UsernameColorCopyWith<$Res> implements $UsernameColorCopyWith<$Res> {
|
||||
factory _$UsernameColorCopyWith(_UsernameColor value, $Res Function(_UsernameColor) _then) = __$UsernameColorCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String type, String? value, String? direction, List<String>? colors
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$UsernameColorCopyWithImpl<$Res>
|
||||
implements _$UsernameColorCopyWith<$Res> {
|
||||
__$UsernameColorCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _UsernameColor _self;
|
||||
final $Res Function(_UsernameColor) _then;
|
||||
|
||||
/// Create a copy of UsernameColor
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? value = freezed,Object? direction = freezed,Object? colors = freezed,}) {
|
||||
return _then(_UsernameColor(
|
||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String,value: freezed == value ? _self.value : value // ignore: cast_nullable_to_non_nullable
|
||||
as String?,direction: freezed == direction ? _self.direction : direction // ignore: cast_nullable_to_non_nullable
|
||||
as String?,colors: freezed == colors ? _self._colors : colors // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnAccountProfile {
|
||||
|
||||
String get id; String get firstName; String get middleName; String get lastName; String get bio; String get gender; String get pronouns; String get location; String get timeZone; DateTime? get birthday;@ProfileLinkConverter() List<ProfileLink> get links; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get socialCredits; int get socialCreditsLevel; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; String get firstName; String get middleName; String get lastName; String get bio; String get gender; String get pronouns; String get location; String get timeZone; DateTime? get birthday;@ProfileLinkConverter() List<ProfileLink> get links; DateTime? get lastSeenAt; SnAccountBadge? get activeBadge; int get experience; int get level; double get socialCredits; int get socialCreditsLevel; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; UsernameColor? get usernameColor; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -638,16 +912,16 @@ $SnAccountProfileCopyWith<SnAccountProfile> get copyWith => _$SnAccountProfileCo
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other.links, links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(identical(other.socialCreditsLevel, socialCreditsLevel) || other.socialCreditsLevel == socialCreditsLevel)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other.links, links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(identical(other.socialCreditsLevel, socialCreditsLevel) || other.socialCreditsLevel == socialCreditsLevel)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.usernameColor, usernameColor) || other.usernameColor == usernameColor)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(links),lastSeenAt,activeBadge,experience,level,socialCredits,socialCreditsLevel,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(links),lastSeenAt,activeBadge,experience,level,socialCredits,socialCreditsLevel,levelingProgress,picture,background,verification,usernameColor,createdAt,updatedAt,deletedAt]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, socialCredits: $socialCredits, socialCreditsLevel: $socialCreditsLevel, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, socialCredits: $socialCredits, socialCreditsLevel: $socialCreditsLevel, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, usernameColor: $usernameColor, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -658,11 +932,11 @@ abstract mixin class $SnAccountProfileCopyWith<$Res> {
|
||||
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, UsernameColor? usernameColor, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
$SnAccountBadgeCopyWith<$Res>? get activeBadge;$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;
|
||||
$SnAccountBadgeCopyWith<$Res>? get activeBadge;$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;$UsernameColorCopyWith<$Res>? get usernameColor;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -675,7 +949,7 @@ class _$SnAccountProfileCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? socialCredits = null,Object? socialCreditsLevel = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? socialCredits = null,Object? socialCreditsLevel = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? usernameColor = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
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
|
||||
@@ -698,7 +972,8 @@ as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : lev
|
||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||
as SnVerificationMark?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as SnVerificationMark?,usernameColor: freezed == usernameColor ? _self.usernameColor : usernameColor // ignore: cast_nullable_to_non_nullable
|
||||
as UsernameColor?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
@@ -752,6 +1027,18 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
|
||||
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||
return _then(_self.copyWith(verification: value));
|
||||
});
|
||||
}/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$UsernameColorCopyWith<$Res>? get usernameColor {
|
||||
if (_self.usernameColor == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $UsernameColorCopyWith<$Res>(_self.usernameColor!, (value) {
|
||||
return _then(_self.copyWith(usernameColor: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -831,10 +1118,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, UsernameColor? usernameColor, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountProfile() when $default != null:
|
||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.usernameColor,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -852,10 +1139,10 @@ return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.b
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, UsernameColor? usernameColor, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountProfile():
|
||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.usernameColor,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -869,10 +1156,10 @@ return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.b
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday, @ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, UsernameColor? usernameColor, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountProfile() when $default != null:
|
||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.bio,_that.gender,_that.pronouns,_that.location,_that.timeZone,_that.birthday,_that.links,_that.lastSeenAt,_that.activeBadge,_that.experience,_that.level,_that.socialCredits,_that.socialCreditsLevel,_that.levelingProgress,_that.picture,_that.background,_that.verification,_that.usernameColor,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -884,7 +1171,7 @@ return $default(_that.id,_that.firstName,_that.middleName,_that.lastName,_that.b
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAccountProfile implements SnAccountProfile {
|
||||
const _SnAccountProfile({required this.id, this.firstName = '', this.middleName = '', this.lastName = '', this.bio = '', this.gender = '', this.pronouns = '', this.location = '', this.timeZone = '', this.birthday, @ProfileLinkConverter() final List<ProfileLink> links = const [], this.lastSeenAt, this.activeBadge, required this.experience, required this.level, this.socialCredits = 100, this.socialCreditsLevel = 0, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.createdAt, required this.updatedAt, required this.deletedAt}): _links = links;
|
||||
const _SnAccountProfile({required this.id, this.firstName = '', this.middleName = '', this.lastName = '', this.bio = '', this.gender = '', this.pronouns = '', this.location = '', this.timeZone = '', this.birthday, @ProfileLinkConverter() final List<ProfileLink> links = const [], this.lastSeenAt, this.activeBadge, required this.experience, required this.level, this.socialCredits = 100, this.socialCreditsLevel = 0, required this.levelingProgress, required this.picture, required this.background, required this.verification, this.usernameColor, required this.createdAt, required this.updatedAt, required this.deletedAt}): _links = links;
|
||||
factory _SnAccountProfile.fromJson(Map<String, dynamic> json) => _$SnAccountProfileFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -914,6 +1201,7 @@ class _SnAccountProfile implements SnAccountProfile {
|
||||
@override final SnCloudFile? picture;
|
||||
@override final SnCloudFile? background;
|
||||
@override final SnVerificationMark? verification;
|
||||
@override final UsernameColor? usernameColor;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
@@ -931,16 +1219,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other._links, _links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(identical(other.socialCreditsLevel, socialCreditsLevel) || other.socialCreditsLevel == socialCreditsLevel)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.gender, gender) || other.gender == gender)&&(identical(other.pronouns, pronouns) || other.pronouns == pronouns)&&(identical(other.location, location) || other.location == location)&&(identical(other.timeZone, timeZone) || other.timeZone == timeZone)&&(identical(other.birthday, birthday) || other.birthday == birthday)&&const DeepCollectionEquality().equals(other._links, _links)&&(identical(other.lastSeenAt, lastSeenAt) || other.lastSeenAt == lastSeenAt)&&(identical(other.activeBadge, activeBadge) || other.activeBadge == activeBadge)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(identical(other.socialCreditsLevel, socialCreditsLevel) || other.socialCreditsLevel == socialCreditsLevel)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.usernameColor, usernameColor) || other.usernameColor == usernameColor)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(_links),lastSeenAt,activeBadge,experience,level,socialCredits,socialCreditsLevel,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,firstName,middleName,lastName,bio,gender,pronouns,location,timeZone,birthday,const DeepCollectionEquality().hash(_links),lastSeenAt,activeBadge,experience,level,socialCredits,socialCreditsLevel,levelingProgress,picture,background,verification,usernameColor,createdAt,updatedAt,deletedAt]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, socialCredits: $socialCredits, socialCreditsLevel: $socialCreditsLevel, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, gender: $gender, pronouns: $pronouns, location: $location, timeZone: $timeZone, birthday: $birthday, links: $links, lastSeenAt: $lastSeenAt, activeBadge: $activeBadge, experience: $experience, level: $level, socialCredits: $socialCredits, socialCreditsLevel: $socialCreditsLevel, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, usernameColor: $usernameColor, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -951,11 +1239,11 @@ abstract mixin class _$SnAccountProfileCopyWith<$Res> implements $SnAccountProfi
|
||||
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String firstName, String middleName, String lastName, String bio, String gender, String pronouns, String location, String timeZone, DateTime? birthday,@ProfileLinkConverter() List<ProfileLink> links, DateTime? lastSeenAt, SnAccountBadge? activeBadge, int experience, int level, double socialCredits, int socialCreditsLevel, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, UsernameColor? usernameColor, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@override $SnAccountBadgeCopyWith<$Res>? get activeBadge;@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;
|
||||
@override $SnAccountBadgeCopyWith<$Res>? get activeBadge;@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;@override $UsernameColorCopyWith<$Res>? get usernameColor;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -968,7 +1256,7 @@ class __$SnAccountProfileCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? socialCredits = null,Object? socialCreditsLevel = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = null,Object? middleName = null,Object? lastName = null,Object? bio = null,Object? gender = null,Object? pronouns = null,Object? location = null,Object? timeZone = null,Object? birthday = freezed,Object? links = null,Object? lastSeenAt = freezed,Object? activeBadge = freezed,Object? experience = null,Object? level = null,Object? socialCredits = null,Object? socialCreditsLevel = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? usernameColor = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnAccountProfile(
|
||||
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
|
||||
@@ -991,7 +1279,8 @@ as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : lev
|
||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||
as SnVerificationMark?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as SnVerificationMark?,usernameColor: freezed == usernameColor ? _self.usernameColor : usernameColor // ignore: cast_nullable_to_non_nullable
|
||||
as UsernameColor?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
@@ -1046,6 +1335,18 @@ $SnVerificationMarkCopyWith<$Res>? get verification {
|
||||
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||
return _then(_self.copyWith(verification: value));
|
||||
});
|
||||
}/// Create a copy of SnAccountProfile
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$UsernameColorCopyWith<$Res>? get usernameColor {
|
||||
if (_self.usernameColor == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $UsernameColorCopyWith<$Res>(_self.usernameColor!, (value) {
|
||||
return _then(_self.copyWith(usernameColor: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -63,6 +63,23 @@ _ProfileLink _$ProfileLinkFromJson(Map<String, dynamic> json) =>
|
||||
Map<String, dynamic> _$ProfileLinkToJson(_ProfileLink instance) =>
|
||||
<String, dynamic>{'name': instance.name, 'url': instance.url};
|
||||
|
||||
_UsernameColor _$UsernameColorFromJson(Map<String, dynamic> json) =>
|
||||
_UsernameColor(
|
||||
type: json['type'] as String? ?? 'plain',
|
||||
value: json['value'] as String?,
|
||||
direction: json['direction'] as String?,
|
||||
colors:
|
||||
(json['colors'] as List<dynamic>?)?.map((e) => e as String).toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$UsernameColorToJson(_UsernameColor instance) =>
|
||||
<String, dynamic>{
|
||||
'type': instance.type,
|
||||
'value': instance.value,
|
||||
'direction': instance.direction,
|
||||
'colors': instance.colors,
|
||||
};
|
||||
|
||||
_SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
||||
_SnAccountProfile(
|
||||
id: json['id'] as String,
|
||||
@@ -113,6 +130,12 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
||||
: SnVerificationMark.fromJson(
|
||||
json['verification'] as Map<String, dynamic>,
|
||||
),
|
||||
usernameColor:
|
||||
json['username_color'] == null
|
||||
? null
|
||||
: UsernameColor.fromJson(
|
||||
json['username_color'] as Map<String, dynamic>,
|
||||
),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
@@ -144,6 +167,7 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
||||
'picture': instance.picture?.toJson(),
|
||||
'background': instance.background?.toJson(),
|
||||
'verification': instance.verification?.toJson(),
|
||||
'username_color': instance.usernameColor?.toJson(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
|
||||
16
lib/models/autocomplete_response.dart
Normal file
16
lib/models/autocomplete_response.dart
Normal file
@@ -0,0 +1,16 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'autocomplete_response.freezed.dart';
|
||||
part 'autocomplete_response.g.dart';
|
||||
|
||||
@freezed
|
||||
sealed class AutocompleteSuggestion with _$AutocompleteSuggestion {
|
||||
const factory AutocompleteSuggestion({
|
||||
required String type,
|
||||
required String keyword,
|
||||
required dynamic data,
|
||||
}) = _AutocompleteSuggestion;
|
||||
|
||||
factory AutocompleteSuggestion.fromJson(Map<String, dynamic> json) =>
|
||||
_$AutocompleteSuggestionFromJson(json);
|
||||
}
|
||||
277
lib/models/autocomplete_response.freezed.dart
Normal file
277
lib/models/autocomplete_response.freezed.dart
Normal file
@@ -0,0 +1,277 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'autocomplete_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$AutocompleteSuggestion {
|
||||
|
||||
String get type; String get keyword; dynamic get data;
|
||||
/// Create a copy of AutocompleteSuggestion
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$AutocompleteSuggestionCopyWith<AutocompleteSuggestion> get copyWith => _$AutocompleteSuggestionCopyWithImpl<AutocompleteSuggestion>(this as AutocompleteSuggestion, _$identity);
|
||||
|
||||
/// Serializes this AutocompleteSuggestion to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AutocompleteSuggestion&&(identical(other.type, type) || other.type == type)&&(identical(other.keyword, keyword) || other.keyword == keyword)&&const DeepCollectionEquality().equals(other.data, data));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,type,keyword,const DeepCollectionEquality().hash(data));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AutocompleteSuggestion(type: $type, keyword: $keyword, data: $data)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $AutocompleteSuggestionCopyWith<$Res> {
|
||||
factory $AutocompleteSuggestionCopyWith(AutocompleteSuggestion value, $Res Function(AutocompleteSuggestion) _then) = _$AutocompleteSuggestionCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String type, String keyword, dynamic data
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$AutocompleteSuggestionCopyWithImpl<$Res>
|
||||
implements $AutocompleteSuggestionCopyWith<$Res> {
|
||||
_$AutocompleteSuggestionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final AutocompleteSuggestion _self;
|
||||
final $Res Function(AutocompleteSuggestion) _then;
|
||||
|
||||
/// Create a copy of AutocompleteSuggestion
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? keyword = null,Object? data = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String,keyword: null == keyword ? _self.keyword : keyword // ignore: cast_nullable_to_non_nullable
|
||||
as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [AutocompleteSuggestion].
|
||||
extension AutocompleteSuggestionPatterns on AutocompleteSuggestion {
|
||||
/// 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( _AutocompleteSuggestion value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AutocompleteSuggestion() 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( _AutocompleteSuggestion value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AutocompleteSuggestion():
|
||||
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( _AutocompleteSuggestion value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _AutocompleteSuggestion() 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 type, String keyword, dynamic data)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AutocompleteSuggestion() when $default != null:
|
||||
return $default(_that.type,_that.keyword,_that.data);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 type, String keyword, dynamic data) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AutocompleteSuggestion():
|
||||
return $default(_that.type,_that.keyword,_that.data);}
|
||||
}
|
||||
/// 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 type, String keyword, dynamic data)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AutocompleteSuggestion() when $default != null:
|
||||
return $default(_that.type,_that.keyword,_that.data);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _AutocompleteSuggestion implements AutocompleteSuggestion {
|
||||
const _AutocompleteSuggestion({required this.type, required this.keyword, required this.data});
|
||||
factory _AutocompleteSuggestion.fromJson(Map<String, dynamic> json) => _$AutocompleteSuggestionFromJson(json);
|
||||
|
||||
@override final String type;
|
||||
@override final String keyword;
|
||||
@override final dynamic data;
|
||||
|
||||
/// Create a copy of AutocompleteSuggestion
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$AutocompleteSuggestionCopyWith<_AutocompleteSuggestion> get copyWith => __$AutocompleteSuggestionCopyWithImpl<_AutocompleteSuggestion>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$AutocompleteSuggestionToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AutocompleteSuggestion&&(identical(other.type, type) || other.type == type)&&(identical(other.keyword, keyword) || other.keyword == keyword)&&const DeepCollectionEquality().equals(other.data, data));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,type,keyword,const DeepCollectionEquality().hash(data));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AutocompleteSuggestion(type: $type, keyword: $keyword, data: $data)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$AutocompleteSuggestionCopyWith<$Res> implements $AutocompleteSuggestionCopyWith<$Res> {
|
||||
factory _$AutocompleteSuggestionCopyWith(_AutocompleteSuggestion value, $Res Function(_AutocompleteSuggestion) _then) = __$AutocompleteSuggestionCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String type, String keyword, dynamic data
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$AutocompleteSuggestionCopyWithImpl<$Res>
|
||||
implements _$AutocompleteSuggestionCopyWith<$Res> {
|
||||
__$AutocompleteSuggestionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _AutocompleteSuggestion _self;
|
||||
final $Res Function(_AutocompleteSuggestion) _then;
|
||||
|
||||
/// Create a copy of AutocompleteSuggestion
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? keyword = null,Object? data = freezed,}) {
|
||||
return _then(_AutocompleteSuggestion(
|
||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String,keyword: null == keyword ? _self.keyword : keyword // ignore: cast_nullable_to_non_nullable
|
||||
as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
23
lib/models/autocomplete_response.g.dart
Normal file
23
lib/models/autocomplete_response.g.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'autocomplete_response.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_AutocompleteSuggestion _$AutocompleteSuggestionFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _AutocompleteSuggestion(
|
||||
type: json['type'] as String,
|
||||
keyword: json['keyword'] as String,
|
||||
data: json['data'],
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$AutocompleteSuggestionToJson(
|
||||
_AutocompleteSuggestion instance,
|
||||
) => <String, dynamic>{
|
||||
'type': instance.type,
|
||||
'keyword': instance.keyword,
|
||||
'data': instance.data,
|
||||
};
|
||||
26
lib/models/heatmap.dart
Normal file
26
lib/models/heatmap.dart
Normal file
@@ -0,0 +1,26 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'heatmap.freezed.dart';
|
||||
part 'heatmap.g.dart';
|
||||
|
||||
@freezed
|
||||
sealed class SnHeatmap with _$SnHeatmap {
|
||||
const factory SnHeatmap({
|
||||
required String unit,
|
||||
@JsonKey(name: 'period_start') required DateTime periodStart,
|
||||
@JsonKey(name: 'period_end') required DateTime periodEnd,
|
||||
required List<SnHeatmapItem> items,
|
||||
}) = _SnHeatmap;
|
||||
|
||||
factory SnHeatmap.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnHeatmapFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnHeatmapItem with _$SnHeatmapItem {
|
||||
const factory SnHeatmapItem({required DateTime date, required int count}) =
|
||||
_SnHeatmapItem;
|
||||
|
||||
factory SnHeatmapItem.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnHeatmapItemFromJson(json);
|
||||
}
|
||||
546
lib/models/heatmap.freezed.dart
Normal file
546
lib/models/heatmap.freezed.dart
Normal file
@@ -0,0 +1,546 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
// coverage:ignore-file
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||
|
||||
part of 'heatmap.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnHeatmap {
|
||||
|
||||
String get unit;@JsonKey(name: 'period_start') DateTime get periodStart;@JsonKey(name: 'period_end') DateTime get periodEnd; List<SnHeatmapItem> get items;
|
||||
/// Create a copy of SnHeatmap
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnHeatmapCopyWith<SnHeatmap> get copyWith => _$SnHeatmapCopyWithImpl<SnHeatmap>(this as SnHeatmap, _$identity);
|
||||
|
||||
/// Serializes this SnHeatmap to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnHeatmap&&(identical(other.unit, unit) || other.unit == unit)&&(identical(other.periodStart, periodStart) || other.periodStart == periodStart)&&(identical(other.periodEnd, periodEnd) || other.periodEnd == periodEnd)&&const DeepCollectionEquality().equals(other.items, items));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,unit,periodStart,periodEnd,const DeepCollectionEquality().hash(items));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnHeatmap(unit: $unit, periodStart: $periodStart, periodEnd: $periodEnd, items: $items)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnHeatmapCopyWith<$Res> {
|
||||
factory $SnHeatmapCopyWith(SnHeatmap value, $Res Function(SnHeatmap) _then) = _$SnHeatmapCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String unit,@JsonKey(name: 'period_start') DateTime periodStart,@JsonKey(name: 'period_end') DateTime periodEnd, List<SnHeatmapItem> items
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnHeatmapCopyWithImpl<$Res>
|
||||
implements $SnHeatmapCopyWith<$Res> {
|
||||
_$SnHeatmapCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnHeatmap _self;
|
||||
final $Res Function(SnHeatmap) _then;
|
||||
|
||||
/// Create a copy of SnHeatmap
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? unit = null,Object? periodStart = null,Object? periodEnd = null,Object? items = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
unit: null == unit ? _self.unit : unit // ignore: cast_nullable_to_non_nullable
|
||||
as String,periodStart: null == periodStart ? _self.periodStart : periodStart // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,periodEnd: null == periodEnd ? _self.periodEnd : periodEnd // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,items: null == items ? _self.items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnHeatmapItem>,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnHeatmap].
|
||||
extension SnHeatmapPatterns on SnHeatmap {
|
||||
/// 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( _SnHeatmap value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmap() 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( _SnHeatmap value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmap():
|
||||
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( _SnHeatmap value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmap() 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 unit, @JsonKey(name: 'period_start') DateTime periodStart, @JsonKey(name: 'period_end') DateTime periodEnd, List<SnHeatmapItem> items)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmap() when $default != null:
|
||||
return $default(_that.unit,_that.periodStart,_that.periodEnd,_that.items);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 unit, @JsonKey(name: 'period_start') DateTime periodStart, @JsonKey(name: 'period_end') DateTime periodEnd, List<SnHeatmapItem> items) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmap():
|
||||
return $default(_that.unit,_that.periodStart,_that.periodEnd,_that.items);}
|
||||
}
|
||||
/// 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 unit, @JsonKey(name: 'period_start') DateTime periodStart, @JsonKey(name: 'period_end') DateTime periodEnd, List<SnHeatmapItem> items)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmap() when $default != null:
|
||||
return $default(_that.unit,_that.periodStart,_that.periodEnd,_that.items);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnHeatmap implements SnHeatmap {
|
||||
const _SnHeatmap({required this.unit, @JsonKey(name: 'period_start') required this.periodStart, @JsonKey(name: 'period_end') required this.periodEnd, required final List<SnHeatmapItem> items}): _items = items;
|
||||
factory _SnHeatmap.fromJson(Map<String, dynamic> json) => _$SnHeatmapFromJson(json);
|
||||
|
||||
@override final String unit;
|
||||
@override@JsonKey(name: 'period_start') final DateTime periodStart;
|
||||
@override@JsonKey(name: 'period_end') final DateTime periodEnd;
|
||||
final List<SnHeatmapItem> _items;
|
||||
@override List<SnHeatmapItem> get items {
|
||||
if (_items is EqualUnmodifiableListView) return _items;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_items);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of SnHeatmap
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnHeatmapCopyWith<_SnHeatmap> get copyWith => __$SnHeatmapCopyWithImpl<_SnHeatmap>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnHeatmapToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnHeatmap&&(identical(other.unit, unit) || other.unit == unit)&&(identical(other.periodStart, periodStart) || other.periodStart == periodStart)&&(identical(other.periodEnd, periodEnd) || other.periodEnd == periodEnd)&&const DeepCollectionEquality().equals(other._items, _items));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,unit,periodStart,periodEnd,const DeepCollectionEquality().hash(_items));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnHeatmap(unit: $unit, periodStart: $periodStart, periodEnd: $periodEnd, items: $items)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnHeatmapCopyWith<$Res> implements $SnHeatmapCopyWith<$Res> {
|
||||
factory _$SnHeatmapCopyWith(_SnHeatmap value, $Res Function(_SnHeatmap) _then) = __$SnHeatmapCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String unit,@JsonKey(name: 'period_start') DateTime periodStart,@JsonKey(name: 'period_end') DateTime periodEnd, List<SnHeatmapItem> items
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnHeatmapCopyWithImpl<$Res>
|
||||
implements _$SnHeatmapCopyWith<$Res> {
|
||||
__$SnHeatmapCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnHeatmap _self;
|
||||
final $Res Function(_SnHeatmap) _then;
|
||||
|
||||
/// Create a copy of SnHeatmap
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? unit = null,Object? periodStart = null,Object? periodEnd = null,Object? items = null,}) {
|
||||
return _then(_SnHeatmap(
|
||||
unit: null == unit ? _self.unit : unit // ignore: cast_nullable_to_non_nullable
|
||||
as String,periodStart: null == periodStart ? _self.periodStart : periodStart // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,periodEnd: null == periodEnd ? _self.periodEnd : periodEnd // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,items: null == items ? _self._items : items // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnHeatmapItem>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnHeatmapItem {
|
||||
|
||||
DateTime get date; int get count;
|
||||
/// Create a copy of SnHeatmapItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnHeatmapItemCopyWith<SnHeatmapItem> get copyWith => _$SnHeatmapItemCopyWithImpl<SnHeatmapItem>(this as SnHeatmapItem, _$identity);
|
||||
|
||||
/// Serializes this SnHeatmapItem to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnHeatmapItem&&(identical(other.date, date) || other.date == date)&&(identical(other.count, count) || other.count == count));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,date,count);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnHeatmapItem(date: $date, count: $count)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnHeatmapItemCopyWith<$Res> {
|
||||
factory $SnHeatmapItemCopyWith(SnHeatmapItem value, $Res Function(SnHeatmapItem) _then) = _$SnHeatmapItemCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
DateTime date, int count
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnHeatmapItemCopyWithImpl<$Res>
|
||||
implements $SnHeatmapItemCopyWith<$Res> {
|
||||
_$SnHeatmapItemCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnHeatmapItem _self;
|
||||
final $Res Function(SnHeatmapItem) _then;
|
||||
|
||||
/// Create a copy of SnHeatmapItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? count = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,count: null == count ? _self.count : count // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnHeatmapItem].
|
||||
extension SnHeatmapItemPatterns on SnHeatmapItem {
|
||||
/// 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( _SnHeatmapItem value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmapItem() 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( _SnHeatmapItem value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmapItem():
|
||||
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( _SnHeatmapItem value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmapItem() when $default != null:
|
||||
return $default(_that);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
/// A variant of `when` that fallback to an `orElse` callback.
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return orElse();
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, int count)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmapItem() when $default != null:
|
||||
return $default(_that.date,_that.count);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
}
|
||||
/// A `switch`-like method, using callbacks.
|
||||
///
|
||||
/// As opposed to `map`, this offers destructuring.
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case Subclass2(:final field2):
|
||||
/// return ...;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, int count) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmapItem():
|
||||
return $default(_that.date,_that.count);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
/// It is equivalent to doing:
|
||||
/// ```dart
|
||||
/// switch (sealedClass) {
|
||||
/// case Subclass(:final field):
|
||||
/// return ...;
|
||||
/// case _:
|
||||
/// return null;
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, int count)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnHeatmapItem() when $default != null:
|
||||
return $default(_that.date,_that.count);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnHeatmapItem implements SnHeatmapItem {
|
||||
const _SnHeatmapItem({required this.date, required this.count});
|
||||
factory _SnHeatmapItem.fromJson(Map<String, dynamic> json) => _$SnHeatmapItemFromJson(json);
|
||||
|
||||
@override final DateTime date;
|
||||
@override final int count;
|
||||
|
||||
/// Create a copy of SnHeatmapItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnHeatmapItemCopyWith<_SnHeatmapItem> get copyWith => __$SnHeatmapItemCopyWithImpl<_SnHeatmapItem>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnHeatmapItemToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnHeatmapItem&&(identical(other.date, date) || other.date == date)&&(identical(other.count, count) || other.count == count));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,date,count);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnHeatmapItem(date: $date, count: $count)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnHeatmapItemCopyWith<$Res> implements $SnHeatmapItemCopyWith<$Res> {
|
||||
factory _$SnHeatmapItemCopyWith(_SnHeatmapItem value, $Res Function(_SnHeatmapItem) _then) = __$SnHeatmapItemCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
DateTime date, int count
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnHeatmapItemCopyWithImpl<$Res>
|
||||
implements _$SnHeatmapItemCopyWith<$Res> {
|
||||
__$SnHeatmapItemCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnHeatmapItem _self;
|
||||
final $Res Function(_SnHeatmapItem) _then;
|
||||
|
||||
/// Create a copy of SnHeatmapItem
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? date = null,Object? count = null,}) {
|
||||
return _then(_SnHeatmapItem(
|
||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,count: null == count ? _self.count : count // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
37
lib/models/heatmap.g.dart
Normal file
37
lib/models/heatmap.g.dart
Normal file
@@ -0,0 +1,37 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'heatmap.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_SnHeatmap _$SnHeatmapFromJson(Map<String, dynamic> json) => _SnHeatmap(
|
||||
unit: json['unit'] as String,
|
||||
periodStart: DateTime.parse(json['period_start'] as String),
|
||||
periodEnd: DateTime.parse(json['period_end'] as String),
|
||||
items:
|
||||
(json['items'] as List<dynamic>)
|
||||
.map((e) => SnHeatmapItem.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnHeatmapToJson(_SnHeatmap instance) =>
|
||||
<String, dynamic>{
|
||||
'unit': instance.unit,
|
||||
'period_start': instance.periodStart.toIso8601String(),
|
||||
'period_end': instance.periodEnd.toIso8601String(),
|
||||
'items': instance.items.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
_SnHeatmapItem _$SnHeatmapItemFromJson(Map<String, dynamic> json) =>
|
||||
_SnHeatmapItem(
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
count: (json['count'] as num).toInt(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnHeatmapItemToJson(_SnHeatmapItem instance) =>
|
||||
<String, dynamic>{
|
||||
'date': instance.date.toIso8601String(),
|
||||
'count': instance.count,
|
||||
};
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/models/post_category.dart';
|
||||
import 'package:island/models/post_tag.dart';
|
||||
@@ -46,9 +47,12 @@ sealed class SnPost with _$SnPost {
|
||||
@Default([]) List<SnPostTag> tags,
|
||||
@Default([]) List<SnPostCategory> categories,
|
||||
@Default([]) List<dynamic> collections,
|
||||
@Default([]) List<SnPostFeaturedRecord> featuredRecords,
|
||||
@Default(null) DateTime? createdAt,
|
||||
@Default(null) DateTime? updatedAt,
|
||||
DateTime? deletedAt,
|
||||
@Default(false) bool repliedGone,
|
||||
@Default(false) bool forwardedGone,
|
||||
@Default(false) bool isTruncated,
|
||||
}) = _SnPost;
|
||||
|
||||
@@ -142,3 +146,37 @@ sealed class SnPostAward with _$SnPostAward {
|
||||
factory SnPostAward.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnPostAwardFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnPostReaction with _$SnPostReaction {
|
||||
const factory SnPostReaction({
|
||||
required String id,
|
||||
required String symbol,
|
||||
required int attitude,
|
||||
required String postId,
|
||||
required String accountId,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
@Default(null) SnAccount? account,
|
||||
DateTime? deletedAt,
|
||||
}) = _SnPostReaction;
|
||||
|
||||
factory SnPostReaction.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnPostReactionFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnPostFeaturedRecord with _$SnPostFeaturedRecord {
|
||||
const factory SnPostFeaturedRecord({
|
||||
required String id,
|
||||
required String postId,
|
||||
required DateTime? featuredAt,
|
||||
required int socialCredits,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) = _SnPostFeaturedRecord;
|
||||
|
||||
factory SnPostFeaturedRecord.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnPostFeaturedRecordFromJson(json);
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SnPost {
|
||||
|
||||
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; SnPostEmbedView? get embedView; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int get awardedScore; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
|
||||
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; SnPostEmbedView? get embedView; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int get awardedScore; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; List<SnPostFeaturedRecord> get featuredRecords; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get repliedGone; bool get forwardedGone; bool get isTruncated;
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -28,16 +28,16 @@ $SnPostCopyWith<SnPost> get copyWith => _$SnPostCopyWithImpl<SnPost>(this as SnP
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&const DeepCollectionEquality().equals(other.featuredRecords, featuredRecords)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.repliedGone, repliedGone) || other.repliedGone == repliedGone)&&(identical(other.forwardedGone, forwardedGone) || other.forwardedGone == forwardedGone)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),const DeepCollectionEquality().hash(featuredRecords),createdAt,updatedAt,deletedAt,repliedGone,forwardedGone,isTruncated]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, featuredRecords: $featuredRecords, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, repliedGone: $repliedGone, forwardedGone: $forwardedGone, isTruncated: $isTruncated)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract mixin class $SnPostCopyWith<$Res> {
|
||||
factory $SnPostCopyWith(SnPost value, $Res Function(SnPost) _then) = _$SnPostCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, List<SnPostFeaturedRecord> featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, bool isTruncated
|
||||
});
|
||||
|
||||
|
||||
@@ -65,7 +65,7 @@ class _$SnPostCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? featuredRecords = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? repliedGone = null,Object? forwardedGone = null,Object? isTruncated = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
@@ -102,10 +102,13 @@ as Map<String, bool>,reactions: null == reactions ? _self.reactions : reactions
|
||||
as List<dynamic>,tags: null == tags ? _self.tags : tags // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPostTag>,categories: null == categories ? _self.categories : categories // 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>,featuredRecords: null == featuredRecords ? _self.featuredRecords : featuredRecords // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPostFeaturedRecord>,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?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,repliedGone: null == repliedGone ? _self.repliedGone : repliedGone // ignore: cast_nullable_to_non_nullable
|
||||
as bool,forwardedGone: null == forwardedGone ? _self.forwardedGone : forwardedGone // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
@@ -257,10 +260,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, List<SnPostFeaturedRecord> featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPost() when $default != null:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.repliedGone,_that.forwardedGone,_that.isTruncated);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -278,10 +281,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, List<SnPostFeaturedRecord> featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, bool isTruncated) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPost():
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.repliedGone,_that.forwardedGone,_that.isTruncated);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -295,10 +298,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, List<SnPostFeaturedRecord> featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, bool isTruncated)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPost() when $default != null:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.embedView,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.awardedScore,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.featuredRecords,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.repliedGone,_that.forwardedGone,_that.isTruncated);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -310,7 +313,7 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPost implements SnPost {
|
||||
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.embedView, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.awardedScore = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
||||
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.embedView, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.awardedScore = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], final List<SnPostFeaturedRecord> featuredRecords = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.repliedGone = false, this.forwardedGone = false, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections,_featuredRecords = featuredRecords;
|
||||
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -398,9 +401,18 @@ class _SnPost implements SnPost {
|
||||
return EqualUnmodifiableListView(_collections);
|
||||
}
|
||||
|
||||
final List<SnPostFeaturedRecord> _featuredRecords;
|
||||
@override@JsonKey() List<SnPostFeaturedRecord> get featuredRecords {
|
||||
if (_featuredRecords is EqualUnmodifiableListView) return _featuredRecords;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_featuredRecords);
|
||||
}
|
||||
|
||||
@override@JsonKey() final DateTime? createdAt;
|
||||
@override@JsonKey() final DateTime? updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
@override@JsonKey() final bool repliedGone;
|
||||
@override@JsonKey() final bool forwardedGone;
|
||||
@override@JsonKey() final bool isTruncated;
|
||||
|
||||
/// Create a copy of SnPost
|
||||
@@ -416,16 +428,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.embedView, embedView) || other.embedView == embedView)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.awardedScore, awardedScore) || other.awardedScore == awardedScore)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&const DeepCollectionEquality().equals(other._featuredRecords, _featuredRecords)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.repliedGone, repliedGone) || other.repliedGone == repliedGone)&&(identical(other.forwardedGone, forwardedGone) || other.forwardedGone == forwardedGone)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),embedView,viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,awardedScore,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),const DeepCollectionEquality().hash(_featuredRecords),createdAt,updatedAt,deletedAt,repliedGone,forwardedGone,isTruncated]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, embedView: $embedView, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, awardedScore: $awardedScore, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, featuredRecords: $featuredRecords, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, repliedGone: $repliedGone, forwardedGone: $forwardedGone, isTruncated: $isTruncated)';
|
||||
}
|
||||
|
||||
|
||||
@@ -436,7 +448,7 @@ abstract mixin class _$SnPostCopyWith<$Res> implements $SnPostCopyWith<$Res> {
|
||||
factory _$SnPostCopyWith(_SnPost value, $Res Function(_SnPost) _then) = __$SnPostCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, SnPostEmbedView? embedView, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int awardedScore, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, List<SnPostFeaturedRecord> featuredRecords, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool repliedGone, bool forwardedGone, bool isTruncated
|
||||
});
|
||||
|
||||
|
||||
@@ -453,7 +465,7 @@ class __$SnPostCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? embedView = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? awardedScore = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? featuredRecords = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? repliedGone = null,Object? forwardedGone = null,Object? isTruncated = null,}) {
|
||||
return _then(_SnPost(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,title: freezed == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
@@ -490,10 +502,13 @@ as Map<String, bool>,reactions: null == reactions ? _self._reactions : reactions
|
||||
as List<dynamic>,tags: null == tags ? _self._tags : tags // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPostTag>,categories: null == categories ? _self._categories : categories // 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>,featuredRecords: null == featuredRecords ? _self._featuredRecords : featuredRecords // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPostFeaturedRecord>,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?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,repliedGone: null == repliedGone ? _self.repliedGone : repliedGone // ignore: cast_nullable_to_non_nullable
|
||||
as bool,forwardedGone: null == forwardedGone ? _self.forwardedGone : forwardedGone // ignore: cast_nullable_to_non_nullable
|
||||
as bool,isTruncated: null == isTruncated ? _self.isTruncated : isTruncated // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
@@ -1898,6 +1913,586 @@ as DateTime?,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnPostReaction {
|
||||
|
||||
String get id; String get symbol; int get attitude; String get postId; String get accountId; DateTime get createdAt; DateTime get updatedAt; SnAccount? get account; DateTime? get deletedAt;
|
||||
/// Create a copy of SnPostReaction
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostReactionCopyWith<SnPostReaction> get copyWith => _$SnPostReactionCopyWithImpl<SnPostReaction>(this as SnPostReaction, _$identity);
|
||||
|
||||
/// Serializes this SnPostReaction to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostReaction&&(identical(other.id, id) || other.id == id)&&(identical(other.symbol, symbol) || other.symbol == symbol)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.postId, postId) || other.postId == postId)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.account, account) || other.account == account)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,symbol,attitude,postId,accountId,createdAt,updatedAt,account,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostReaction(id: $id, symbol: $symbol, attitude: $attitude, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, account: $account, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnPostReactionCopyWith<$Res> {
|
||||
factory $SnPostReactionCopyWith(SnPostReaction value, $Res Function(SnPostReaction) _then) = _$SnPostReactionCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String symbol, int attitude, String postId, String accountId, DateTime createdAt, DateTime updatedAt, SnAccount? account, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
$SnAccountCopyWith<$Res>? get account;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnPostReactionCopyWithImpl<$Res>
|
||||
implements $SnPostReactionCopyWith<$Res> {
|
||||
_$SnPostReactionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnPostReaction _self;
|
||||
final $Res Function(SnPostReaction) _then;
|
||||
|
||||
/// Create a copy of SnPostReaction
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? symbol = null,Object? attitude = null,Object? postId = null,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? account = freezed,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,symbol: null == symbol ? _self.symbol : symbol // ignore: cast_nullable_to_non_nullable
|
||||
as String,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
|
||||
as int,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable
|
||||
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnPostReaction
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnPostReaction].
|
||||
extension SnPostReactionPatterns on SnPostReaction {
|
||||
/// 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( _SnPostReaction value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostReaction() 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( _SnPostReaction value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostReaction():
|
||||
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( _SnPostReaction value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostReaction() 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 symbol, int attitude, String postId, String accountId, DateTime createdAt, DateTime updatedAt, SnAccount? account, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostReaction() when $default != null:
|
||||
return $default(_that.id,_that.symbol,_that.attitude,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.account,_that.deletedAt);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 symbol, int attitude, String postId, String accountId, DateTime createdAt, DateTime updatedAt, SnAccount? account, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostReaction():
|
||||
return $default(_that.id,_that.symbol,_that.attitude,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.account,_that.deletedAt);}
|
||||
}
|
||||
/// 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 symbol, int attitude, String postId, String accountId, DateTime createdAt, DateTime updatedAt, SnAccount? account, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostReaction() when $default != null:
|
||||
return $default(_that.id,_that.symbol,_that.attitude,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.account,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPostReaction implements SnPostReaction {
|
||||
const _SnPostReaction({required this.id, required this.symbol, required this.attitude, required this.postId, required this.accountId, required this.createdAt, required this.updatedAt, this.account = null, this.deletedAt});
|
||||
factory _SnPostReaction.fromJson(Map<String, dynamic> json) => _$SnPostReactionFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String symbol;
|
||||
@override final int attitude;
|
||||
@override final String postId;
|
||||
@override final String accountId;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override@JsonKey() final SnAccount? account;
|
||||
@override final DateTime? deletedAt;
|
||||
|
||||
/// Create a copy of SnPostReaction
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnPostReactionCopyWith<_SnPostReaction> get copyWith => __$SnPostReactionCopyWithImpl<_SnPostReaction>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnPostReactionToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostReaction&&(identical(other.id, id) || other.id == id)&&(identical(other.symbol, symbol) || other.symbol == symbol)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.postId, postId) || other.postId == postId)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.account, account) || other.account == account)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,symbol,attitude,postId,accountId,createdAt,updatedAt,account,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostReaction(id: $id, symbol: $symbol, attitude: $attitude, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, account: $account, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnPostReactionCopyWith<$Res> implements $SnPostReactionCopyWith<$Res> {
|
||||
factory _$SnPostReactionCopyWith(_SnPostReaction value, $Res Function(_SnPostReaction) _then) = __$SnPostReactionCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String symbol, int attitude, String postId, String accountId, DateTime createdAt, DateTime updatedAt, SnAccount? account, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@override $SnAccountCopyWith<$Res>? get account;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnPostReactionCopyWithImpl<$Res>
|
||||
implements _$SnPostReactionCopyWith<$Res> {
|
||||
__$SnPostReactionCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnPostReaction _self;
|
||||
final $Res Function(_SnPostReaction) _then;
|
||||
|
||||
/// Create a copy of SnPostReaction
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? symbol = null,Object? attitude = null,Object? postId = null,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? account = freezed,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnPostReaction(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,symbol: null == symbol ? _self.symbol : symbol // ignore: cast_nullable_to_non_nullable
|
||||
as String,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
|
||||
as int,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable
|
||||
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnPostReaction
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnPostFeaturedRecord {
|
||||
|
||||
String get id; String get postId; DateTime? get featuredAt; int get socialCredits; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnPostFeaturedRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostFeaturedRecordCopyWith<SnPostFeaturedRecord> get copyWith => _$SnPostFeaturedRecordCopyWithImpl<SnPostFeaturedRecord>(this as SnPostFeaturedRecord, _$identity);
|
||||
|
||||
/// Serializes this SnPostFeaturedRecord to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostFeaturedRecord&&(identical(other.id, id) || other.id == id)&&(identical(other.postId, postId) || other.postId == postId)&&(identical(other.featuredAt, featuredAt) || other.featuredAt == featuredAt)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,postId,featuredAt,socialCredits,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostFeaturedRecord(id: $id, postId: $postId, featuredAt: $featuredAt, socialCredits: $socialCredits, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnPostFeaturedRecordCopyWith<$Res> {
|
||||
factory $SnPostFeaturedRecordCopyWith(SnPostFeaturedRecord value, $Res Function(SnPostFeaturedRecord) _then) = _$SnPostFeaturedRecordCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String postId, DateTime? featuredAt, int socialCredits, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnPostFeaturedRecordCopyWithImpl<$Res>
|
||||
implements $SnPostFeaturedRecordCopyWith<$Res> {
|
||||
_$SnPostFeaturedRecordCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnPostFeaturedRecord _self;
|
||||
final $Res Function(SnPostFeaturedRecord) _then;
|
||||
|
||||
/// Create a copy of SnPostFeaturedRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? postId = null,Object? featuredAt = freezed,Object? socialCredits = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable
|
||||
as String,featuredAt: freezed == featuredAt ? _self.featuredAt : featuredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,socialCredits: null == socialCredits ? _self.socialCredits : socialCredits // ignore: cast_nullable_to_non_nullable
|
||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnPostFeaturedRecord].
|
||||
extension SnPostFeaturedRecordPatterns on SnPostFeaturedRecord {
|
||||
/// 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( _SnPostFeaturedRecord value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostFeaturedRecord() 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( _SnPostFeaturedRecord value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostFeaturedRecord():
|
||||
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( _SnPostFeaturedRecord value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostFeaturedRecord() 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 postId, DateTime? featuredAt, int socialCredits, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostFeaturedRecord() when $default != null:
|
||||
return $default(_that.id,_that.postId,_that.featuredAt,_that.socialCredits,_that.createdAt,_that.updatedAt,_that.deletedAt);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 postId, DateTime? featuredAt, int socialCredits, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostFeaturedRecord():
|
||||
return $default(_that.id,_that.postId,_that.featuredAt,_that.socialCredits,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
}
|
||||
/// 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 postId, DateTime? featuredAt, int socialCredits, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostFeaturedRecord() when $default != null:
|
||||
return $default(_that.id,_that.postId,_that.featuredAt,_that.socialCredits,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPostFeaturedRecord implements SnPostFeaturedRecord {
|
||||
const _SnPostFeaturedRecord({required this.id, required this.postId, required this.featuredAt, required this.socialCredits, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||
factory _SnPostFeaturedRecord.fromJson(Map<String, dynamic> json) => _$SnPostFeaturedRecordFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String postId;
|
||||
@override final DateTime? featuredAt;
|
||||
@override final int socialCredits;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
|
||||
/// Create a copy of SnPostFeaturedRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnPostFeaturedRecordCopyWith<_SnPostFeaturedRecord> get copyWith => __$SnPostFeaturedRecordCopyWithImpl<_SnPostFeaturedRecord>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnPostFeaturedRecordToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostFeaturedRecord&&(identical(other.id, id) || other.id == id)&&(identical(other.postId, postId) || other.postId == postId)&&(identical(other.featuredAt, featuredAt) || other.featuredAt == featuredAt)&&(identical(other.socialCredits, socialCredits) || other.socialCredits == socialCredits)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,postId,featuredAt,socialCredits,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostFeaturedRecord(id: $id, postId: $postId, featuredAt: $featuredAt, socialCredits: $socialCredits, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnPostFeaturedRecordCopyWith<$Res> implements $SnPostFeaturedRecordCopyWith<$Res> {
|
||||
factory _$SnPostFeaturedRecordCopyWith(_SnPostFeaturedRecord value, $Res Function(_SnPostFeaturedRecord) _then) = __$SnPostFeaturedRecordCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String postId, DateTime? featuredAt, int socialCredits, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnPostFeaturedRecordCopyWithImpl<$Res>
|
||||
implements _$SnPostFeaturedRecordCopyWith<$Res> {
|
||||
__$SnPostFeaturedRecordCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnPostFeaturedRecord _self;
|
||||
final $Res Function(_SnPostFeaturedRecord) _then;
|
||||
|
||||
/// Create a copy of SnPostFeaturedRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? postId = null,Object? featuredAt = freezed,Object? socialCredits = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnPostFeaturedRecord(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,postId: null == postId ? _self.postId : postId // ignore: cast_nullable_to_non_nullable
|
||||
as String,featuredAt: freezed == featuredAt ? _self.featuredAt : featuredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,socialCredits: null == socialCredits ? _self.socialCredits : socialCredits // ignore: cast_nullable_to_non_nullable
|
||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
|
||||
@@ -85,6 +85,11 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
.toList() ??
|
||||
const [],
|
||||
collections: json['collections'] as List<dynamic>? ?? const [],
|
||||
featuredRecords:
|
||||
(json['featured_records'] as List<dynamic>?)
|
||||
?.map((e) => SnPostFeaturedRecord.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
createdAt:
|
||||
json['created_at'] == null
|
||||
? null
|
||||
@@ -97,6 +102,8 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
repliedGone: json['replied_gone'] as bool? ?? false,
|
||||
forwardedGone: json['forwarded_gone'] as bool? ?? false,
|
||||
isTruncated: json['is_truncated'] as bool? ?? false,
|
||||
);
|
||||
|
||||
@@ -136,9 +143,12 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
||||
'tags': instance.tags.map((e) => e.toJson()).toList(),
|
||||
'categories': instance.categories.map((e) => e.toJson()).toList(),
|
||||
'collections': instance.collections,
|
||||
'featured_records': instance.featuredRecords.map((e) => e.toJson()).toList(),
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
'replied_gone': instance.repliedGone,
|
||||
'forwarded_gone': instance.forwardedGone,
|
||||
'is_truncated': instance.isTruncated,
|
||||
};
|
||||
|
||||
@@ -230,3 +240,65 @@ Map<String, dynamic> _$SnPostAwardToJson(_SnPostAward instance) =>
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
_SnPostReaction _$SnPostReactionFromJson(Map<String, dynamic> json) =>
|
||||
_SnPostReaction(
|
||||
id: json['id'] as String,
|
||||
symbol: json['symbol'] as String,
|
||||
attitude: (json['attitude'] as num).toInt(),
|
||||
postId: json['post_id'] as String,
|
||||
accountId: json['account_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
account:
|
||||
json['account'] == null
|
||||
? null
|
||||
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPostReactionToJson(_SnPostReaction instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'symbol': instance.symbol,
|
||||
'attitude': instance.attitude,
|
||||
'post_id': instance.postId,
|
||||
'account_id': instance.accountId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'account': instance.account?.toJson(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
_SnPostFeaturedRecord _$SnPostFeaturedRecordFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _SnPostFeaturedRecord(
|
||||
id: json['id'] as String,
|
||||
postId: json['post_id'] as String,
|
||||
featuredAt:
|
||||
json['featured_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['featured_at'] as String),
|
||||
socialCredits: (json['social_credits'] as num).toInt(),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPostFeaturedRecordToJson(
|
||||
_SnPostFeaturedRecord instance,
|
||||
) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'post_id': instance.postId,
|
||||
'featured_at': instance.featuredAt?.toIso8601String(),
|
||||
'social_credits': instance.socialCredits,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
@@ -10,7 +10,6 @@ sealed class SnSticker with _$SnSticker {
|
||||
const factory SnSticker({
|
||||
required String id,
|
||||
required String slug,
|
||||
required String imageId,
|
||||
required SnCloudFile image,
|
||||
required String packId,
|
||||
required SnStickerPack? pack,
|
||||
|
||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SnSticker {
|
||||
|
||||
String get id; String get slug; String get imageId; SnCloudFile get image; String get packId; SnStickerPack? get pack; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; String get slug; SnCloudFile get image; String get packId; SnStickerPack? get pack; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnSticker
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -28,16 +28,16 @@ $SnStickerCopyWith<SnSticker> get copyWith => _$SnStickerCopyWithImpl<SnSticker>
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnSticker&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.imageId, imageId) || other.imageId == imageId)&&(identical(other.image, image) || other.image == image)&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.pack, pack) || other.pack == pack)&&(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 SnSticker&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.image, image) || other.image == image)&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.pack, pack) || other.pack == pack)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,imageId,image,packId,pack,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,image,packId,pack,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnSticker(id: $id, slug: $slug, imageId: $imageId, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnSticker(id: $id, slug: $slug, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract mixin class $SnStickerCopyWith<$Res> {
|
||||
factory $SnStickerCopyWith(SnSticker value, $Res Function(SnSticker) _then) = _$SnStickerCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String slug, String imageId, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@@ -65,11 +65,10 @@ class _$SnStickerCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnSticker
|
||||
/// 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? imageId = null,Object? image = null,Object? packId = null,Object? pack = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? image = null,Object? packId = null,Object? pack = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
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,imageId: null == imageId ? _self.imageId : imageId // ignore: cast_nullable_to_non_nullable
|
||||
as String,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
|
||||
as SnCloudFile,packId: null == packId ? _self.packId : packId // ignore: cast_nullable_to_non_nullable
|
||||
as String,pack: freezed == pack ? _self.pack : pack // ignore: cast_nullable_to_non_nullable
|
||||
@@ -179,10 +178,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String imageId, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnSticker() when $default != null:
|
||||
return $default(_that.id,_that.slug,_that.imageId,_that.image,_that.packId,_that.pack,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.slug,_that.image,_that.packId,_that.pack,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -200,10 +199,10 @@ return $default(_that.id,_that.slug,_that.imageId,_that.image,_that.packId,_that
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String imageId, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnSticker():
|
||||
return $default(_that.id,_that.slug,_that.imageId,_that.image,_that.packId,_that.pack,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
return $default(_that.id,_that.slug,_that.image,_that.packId,_that.pack,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -217,10 +216,10 @@ return $default(_that.id,_that.slug,_that.imageId,_that.image,_that.packId,_that
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String imageId, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnSticker() when $default != null:
|
||||
return $default(_that.id,_that.slug,_that.imageId,_that.image,_that.packId,_that.pack,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.slug,_that.image,_that.packId,_that.pack,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -232,12 +231,11 @@ return $default(_that.id,_that.slug,_that.imageId,_that.image,_that.packId,_that
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnSticker implements SnSticker {
|
||||
const _SnSticker({required this.id, required this.slug, required this.imageId, required this.image, required this.packId, required this.pack, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||
const _SnSticker({required this.id, required this.slug, required this.image, required this.packId, required this.pack, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||
factory _SnSticker.fromJson(Map<String, dynamic> json) => _$SnStickerFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String slug;
|
||||
@override final String imageId;
|
||||
@override final SnCloudFile image;
|
||||
@override final String packId;
|
||||
@override final SnStickerPack? pack;
|
||||
@@ -258,16 +256,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnSticker&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.imageId, imageId) || other.imageId == imageId)&&(identical(other.image, image) || other.image == image)&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.pack, pack) || other.pack == pack)&&(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 _SnSticker&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.image, image) || other.image == image)&&(identical(other.packId, packId) || other.packId == packId)&&(identical(other.pack, pack) || other.pack == pack)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,imageId,image,packId,pack,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,image,packId,pack,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnSticker(id: $id, slug: $slug, imageId: $imageId, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnSticker(id: $id, slug: $slug, image: $image, packId: $packId, pack: $pack, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -278,7 +276,7 @@ abstract mixin class _$SnStickerCopyWith<$Res> implements $SnStickerCopyWith<$Re
|
||||
factory _$SnStickerCopyWith(_SnSticker value, $Res Function(_SnSticker) _then) = __$SnStickerCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String slug, String imageId, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String slug, SnCloudFile image, String packId, SnStickerPack? pack, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@@ -295,11 +293,10 @@ class __$SnStickerCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnSticker
|
||||
/// 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? imageId = null,Object? image = null,Object? packId = null,Object? pack = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? image = null,Object? packId = null,Object? pack = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnSticker(
|
||||
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,imageId: null == imageId ? _self.imageId : imageId // ignore: cast_nullable_to_non_nullable
|
||||
as String,image: null == image ? _self.image : image // ignore: cast_nullable_to_non_nullable
|
||||
as SnCloudFile,packId: null == packId ? _self.packId : packId // ignore: cast_nullable_to_non_nullable
|
||||
as String,pack: freezed == pack ? _self.pack : pack // ignore: cast_nullable_to_non_nullable
|
||||
|
||||
@@ -9,7 +9,6 @@ part of 'sticker.dart';
|
||||
_SnSticker _$SnStickerFromJson(Map<String, dynamic> json) => _SnSticker(
|
||||
id: json['id'] as String,
|
||||
slug: json['slug'] as String,
|
||||
imageId: json['image_id'] as String,
|
||||
image: SnCloudFile.fromJson(json['image'] as Map<String, dynamic>),
|
||||
packId: json['pack_id'] as String,
|
||||
pack:
|
||||
@@ -28,7 +27,6 @@ Map<String, dynamic> _$SnStickerToJson(_SnSticker instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'slug': instance.slug,
|
||||
'image_id': instance.imageId,
|
||||
'image': instance.image.toJson(),
|
||||
'pack_id': instance.packId,
|
||||
'pack': instance.pack?.toJson(),
|
||||
|
||||
116
lib/models/thought.dart
Normal file
116
lib/models/thought.dart
Normal file
@@ -0,0 +1,116 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
|
||||
part 'thought.freezed.dart';
|
||||
part 'thought.g.dart';
|
||||
|
||||
enum ThinkingThoughtRole {
|
||||
assistant(0),
|
||||
user(1);
|
||||
|
||||
const ThinkingThoughtRole(this.value);
|
||||
final int value;
|
||||
|
||||
static ThinkingThoughtRole fromValue(int value) {
|
||||
return values.firstWhere((e) => e.value == value);
|
||||
}
|
||||
}
|
||||
|
||||
class ThinkingThoughtRoleConverter
|
||||
implements JsonConverter<ThinkingThoughtRole, int> {
|
||||
const ThinkingThoughtRoleConverter();
|
||||
|
||||
@override
|
||||
ThinkingThoughtRole fromJson(int json) => ThinkingThoughtRole.fromValue(json);
|
||||
|
||||
@override
|
||||
int toJson(ThinkingThoughtRole object) => object.value;
|
||||
}
|
||||
|
||||
class ThinkingChunkTypeConverter
|
||||
implements JsonConverter<ThinkingChunkType, int> {
|
||||
const ThinkingChunkTypeConverter();
|
||||
|
||||
@override
|
||||
ThinkingChunkType fromJson(int json) => ThinkingChunkType.fromValue(json);
|
||||
|
||||
@override
|
||||
int toJson(ThinkingChunkType object) => object.value;
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class StreamThinkingRequest with _$StreamThinkingRequest {
|
||||
const factory StreamThinkingRequest({
|
||||
required String userMessage,
|
||||
String? sequenceId,
|
||||
@Default([]) List<String> accpetProposals,
|
||||
List<String>? attachedPosts,
|
||||
List<Map<String, dynamic>>? attachedMessages,
|
||||
}) = _StreamThinkingRequest;
|
||||
|
||||
factory StreamThinkingRequest.fromJson(Map<String, dynamic> json) =>
|
||||
_$StreamThinkingRequestFromJson(json);
|
||||
}
|
||||
|
||||
enum ThinkingChunkType {
|
||||
text(0),
|
||||
reasoning(1),
|
||||
functionCall(2),
|
||||
unknown(3);
|
||||
|
||||
const ThinkingChunkType(this.value);
|
||||
final int value;
|
||||
|
||||
static ThinkingChunkType fromValue(int value) {
|
||||
return values.firstWhere((e) => e.value == value);
|
||||
}
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnThinkingChunk with _$SnThinkingChunk {
|
||||
const factory SnThinkingChunk({
|
||||
@ThinkingChunkTypeConverter() required ThinkingChunkType type,
|
||||
Map<String, dynamic>? data,
|
||||
}) = _SnThinkingChunk;
|
||||
|
||||
factory SnThinkingChunk.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnThinkingChunkFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnThinkingSequence with _$SnThinkingSequence {
|
||||
const factory SnThinkingSequence({
|
||||
required String id,
|
||||
String? topic,
|
||||
@Default(0) int totalToken,
|
||||
@Default(0) int paidToken,
|
||||
required String accountId,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
DateTime? deletedAt,
|
||||
}) = _SnThinkingSequence;
|
||||
|
||||
factory SnThinkingSequence.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnThinkingSequenceFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnThinkingThought with _$SnThinkingThought {
|
||||
const factory SnThinkingThought({
|
||||
required String id,
|
||||
String? content,
|
||||
@Default([]) List<SnCloudFile> files,
|
||||
@Default([]) List<SnThinkingChunk> chunks,
|
||||
@ThinkingThoughtRoleConverter() required ThinkingThoughtRole role,
|
||||
int? tokenCount,
|
||||
String? modelName,
|
||||
required String sequenceId,
|
||||
SnThinkingSequence? sequence,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
DateTime? deletedAt,
|
||||
}) = _SnThinkingThought;
|
||||
|
||||
factory SnThinkingThought.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnThinkingThoughtFromJson(json);
|
||||
}
|
||||
1177
lib/models/thought.freezed.dart
Normal file
1177
lib/models/thought.freezed.dart
Normal file
File diff suppressed because it is too large
Load Diff
128
lib/models/thought.g.dart
Normal file
128
lib/models/thought.g.dart
Normal file
@@ -0,0 +1,128 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'thought.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_StreamThinkingRequest _$StreamThinkingRequestFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _StreamThinkingRequest(
|
||||
userMessage: json['user_message'] as String,
|
||||
sequenceId: json['sequence_id'] as String?,
|
||||
accpetProposals:
|
||||
(json['accpet_proposals'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
const [],
|
||||
attachedPosts:
|
||||
(json['attached_posts'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList(),
|
||||
attachedMessages:
|
||||
(json['attached_messages'] as List<dynamic>?)
|
||||
?.map((e) => e as Map<String, dynamic>)
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$StreamThinkingRequestToJson(
|
||||
_StreamThinkingRequest instance,
|
||||
) => <String, dynamic>{
|
||||
'user_message': instance.userMessage,
|
||||
'sequence_id': instance.sequenceId,
|
||||
'accpet_proposals': instance.accpetProposals,
|
||||
'attached_posts': instance.attachedPosts,
|
||||
'attached_messages': instance.attachedMessages,
|
||||
};
|
||||
|
||||
_SnThinkingChunk _$SnThinkingChunkFromJson(Map<String, dynamic> json) =>
|
||||
_SnThinkingChunk(
|
||||
type: const ThinkingChunkTypeConverter().fromJson(
|
||||
(json['type'] as num).toInt(),
|
||||
),
|
||||
data: json['data'] as Map<String, dynamic>?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnThinkingChunkToJson(_SnThinkingChunk instance) =>
|
||||
<String, dynamic>{
|
||||
'type': const ThinkingChunkTypeConverter().toJson(instance.type),
|
||||
'data': instance.data,
|
||||
};
|
||||
|
||||
_SnThinkingSequence _$SnThinkingSequenceFromJson(Map<String, dynamic> json) =>
|
||||
_SnThinkingSequence(
|
||||
id: json['id'] as String,
|
||||
topic: json['topic'] as String?,
|
||||
totalToken: (json['total_token'] as num?)?.toInt() ?? 0,
|
||||
paidToken: (json['paid_token'] as num?)?.toInt() ?? 0,
|
||||
accountId: json['account_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnThinkingSequenceToJson(_SnThinkingSequence instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'topic': instance.topic,
|
||||
'total_token': instance.totalToken,
|
||||
'paid_token': instance.paidToken,
|
||||
'account_id': instance.accountId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
_SnThinkingThought _$SnThinkingThoughtFromJson(Map<String, dynamic> json) =>
|
||||
_SnThinkingThought(
|
||||
id: json['id'] as String,
|
||||
content: json['content'] as String?,
|
||||
files:
|
||||
(json['files'] as List<dynamic>?)
|
||||
?.map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
chunks:
|
||||
(json['chunks'] as List<dynamic>?)
|
||||
?.map((e) => SnThinkingChunk.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
role: const ThinkingThoughtRoleConverter().fromJson(
|
||||
(json['role'] as num).toInt(),
|
||||
),
|
||||
tokenCount: (json['token_count'] as num?)?.toInt(),
|
||||
modelName: json['model_name'] as String?,
|
||||
sequenceId: json['sequence_id'] as String,
|
||||
sequence:
|
||||
json['sequence'] == null
|
||||
? null
|
||||
: SnThinkingSequence.fromJson(
|
||||
json['sequence'] as Map<String, dynamic>,
|
||||
),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnThinkingThoughtToJson(_SnThinkingThought instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'content': instance.content,
|
||||
'files': instance.files.map((e) => e.toJson()).toList(),
|
||||
'chunks': instance.chunks.map((e) => e.toJson()).toList(),
|
||||
'role': const ThinkingThoughtRoleConverter().toJson(instance.role),
|
||||
'token_count': instance.tokenCount,
|
||||
'model_name': instance.modelName,
|
||||
'sequence_id': instance.sequenceId,
|
||||
'sequence': instance.sequence?.toJson(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
@@ -211,3 +211,44 @@ sealed class SnWalletFundRecipient with _$SnWalletFundRecipient {
|
||||
factory SnWalletFundRecipient.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnWalletFundRecipientFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnLotteryTicket with _$SnLotteryTicket {
|
||||
const factory SnLotteryTicket({
|
||||
required String id,
|
||||
required String accountId,
|
||||
required SnAccount? account,
|
||||
required List<int> regionOneNumbers,
|
||||
required int regionTwoNumber,
|
||||
required int multiplier,
|
||||
required int drawStatus,
|
||||
required DateTime? drawDate,
|
||||
required List<int>? matchedRegionOneNumbers,
|
||||
required int? matchedRegionTwoNumber,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) = _SnLotteryTicket;
|
||||
|
||||
factory SnLotteryTicket.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnLotteryTicketFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnLotteryRecord with _$SnLotteryRecord {
|
||||
const factory SnLotteryRecord({
|
||||
required String id,
|
||||
required DateTime drawDate,
|
||||
required List<int> winningRegionOneNumbers,
|
||||
required int winningRegionTwoNumber,
|
||||
required int totalTickets,
|
||||
required int totalPrizesAwarded,
|
||||
required double totalPrizeAmount,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) = _SnLotteryRecord;
|
||||
|
||||
factory SnLotteryRecord.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnLotteryRecordFromJson(json);
|
||||
}
|
||||
|
||||
@@ -3184,4 +3184,625 @@ $SnAccountCopyWith<$Res>? get recipientAccount {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnLotteryTicket {
|
||||
|
||||
String get id; String get accountId; SnAccount? get account; List<int> get regionOneNumbers; int get regionTwoNumber; int get multiplier; int get drawStatus; DateTime? get drawDate; List<int>? get matchedRegionOneNumbers; int? get matchedRegionTwoNumber; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnLotteryTicket
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnLotteryTicketCopyWith<SnLotteryTicket> get copyWith => _$SnLotteryTicketCopyWithImpl<SnLotteryTicket>(this as SnLotteryTicket, _$identity);
|
||||
|
||||
/// Serializes this SnLotteryTicket to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnLotteryTicket&&(identical(other.id, id) || other.id == id)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&const DeepCollectionEquality().equals(other.regionOneNumbers, regionOneNumbers)&&(identical(other.regionTwoNumber, regionTwoNumber) || other.regionTwoNumber == regionTwoNumber)&&(identical(other.multiplier, multiplier) || other.multiplier == multiplier)&&(identical(other.drawStatus, drawStatus) || other.drawStatus == drawStatus)&&(identical(other.drawDate, drawDate) || other.drawDate == drawDate)&&const DeepCollectionEquality().equals(other.matchedRegionOneNumbers, matchedRegionOneNumbers)&&(identical(other.matchedRegionTwoNumber, matchedRegionTwoNumber) || other.matchedRegionTwoNumber == matchedRegionTwoNumber)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,accountId,account,const DeepCollectionEquality().hash(regionOneNumbers),regionTwoNumber,multiplier,drawStatus,drawDate,const DeepCollectionEquality().hash(matchedRegionOneNumbers),matchedRegionTwoNumber,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnLotteryTicket(id: $id, accountId: $accountId, account: $account, regionOneNumbers: $regionOneNumbers, regionTwoNumber: $regionTwoNumber, multiplier: $multiplier, drawStatus: $drawStatus, drawDate: $drawDate, matchedRegionOneNumbers: $matchedRegionOneNumbers, matchedRegionTwoNumber: $matchedRegionTwoNumber, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnLotteryTicketCopyWith<$Res> {
|
||||
factory $SnLotteryTicketCopyWith(SnLotteryTicket value, $Res Function(SnLotteryTicket) _then) = _$SnLotteryTicketCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String accountId, SnAccount? account, List<int> regionOneNumbers, int regionTwoNumber, int multiplier, int drawStatus, DateTime? drawDate, List<int>? matchedRegionOneNumbers, int? matchedRegionTwoNumber, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
$SnAccountCopyWith<$Res>? get account;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnLotteryTicketCopyWithImpl<$Res>
|
||||
implements $SnLotteryTicketCopyWith<$Res> {
|
||||
_$SnLotteryTicketCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnLotteryTicket _self;
|
||||
final $Res Function(SnLotteryTicket) _then;
|
||||
|
||||
/// Create a copy of SnLotteryTicket
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? accountId = null,Object? account = freezed,Object? regionOneNumbers = null,Object? regionTwoNumber = null,Object? multiplier = null,Object? drawStatus = null,Object? drawDate = freezed,Object? matchedRegionOneNumbers = freezed,Object? matchedRegionTwoNumber = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,regionOneNumbers: null == regionOneNumbers ? _self.regionOneNumbers : regionOneNumbers // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>,regionTwoNumber: null == regionTwoNumber ? _self.regionTwoNumber : regionTwoNumber // ignore: cast_nullable_to_non_nullable
|
||||
as int,multiplier: null == multiplier ? _self.multiplier : multiplier // ignore: cast_nullable_to_non_nullable
|
||||
as int,drawStatus: null == drawStatus ? _self.drawStatus : drawStatus // ignore: cast_nullable_to_non_nullable
|
||||
as int,drawDate: freezed == drawDate ? _self.drawDate : drawDate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,matchedRegionOneNumbers: freezed == matchedRegionOneNumbers ? _self.matchedRegionOneNumbers : matchedRegionOneNumbers // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>?,matchedRegionTwoNumber: freezed == matchedRegionTwoNumber ? _self.matchedRegionTwoNumber : matchedRegionTwoNumber // ignore: cast_nullable_to_non_nullable
|
||||
as int?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnLotteryTicket
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnLotteryTicket].
|
||||
extension SnLotteryTicketPatterns on SnLotteryTicket {
|
||||
/// 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( _SnLotteryTicket value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryTicket() 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( _SnLotteryTicket value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryTicket():
|
||||
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( _SnLotteryTicket value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryTicket() 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 accountId, SnAccount? account, List<int> regionOneNumbers, int regionTwoNumber, int multiplier, int drawStatus, DateTime? drawDate, List<int>? matchedRegionOneNumbers, int? matchedRegionTwoNumber, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryTicket() when $default != null:
|
||||
return $default(_that.id,_that.accountId,_that.account,_that.regionOneNumbers,_that.regionTwoNumber,_that.multiplier,_that.drawStatus,_that.drawDate,_that.matchedRegionOneNumbers,_that.matchedRegionTwoNumber,_that.createdAt,_that.updatedAt,_that.deletedAt);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 accountId, SnAccount? account, List<int> regionOneNumbers, int regionTwoNumber, int multiplier, int drawStatus, DateTime? drawDate, List<int>? matchedRegionOneNumbers, int? matchedRegionTwoNumber, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryTicket():
|
||||
return $default(_that.id,_that.accountId,_that.account,_that.regionOneNumbers,_that.regionTwoNumber,_that.multiplier,_that.drawStatus,_that.drawDate,_that.matchedRegionOneNumbers,_that.matchedRegionTwoNumber,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
}
|
||||
/// 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 accountId, SnAccount? account, List<int> regionOneNumbers, int regionTwoNumber, int multiplier, int drawStatus, DateTime? drawDate, List<int>? matchedRegionOneNumbers, int? matchedRegionTwoNumber, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryTicket() when $default != null:
|
||||
return $default(_that.id,_that.accountId,_that.account,_that.regionOneNumbers,_that.regionTwoNumber,_that.multiplier,_that.drawStatus,_that.drawDate,_that.matchedRegionOneNumbers,_that.matchedRegionTwoNumber,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnLotteryTicket implements SnLotteryTicket {
|
||||
const _SnLotteryTicket({required this.id, required this.accountId, required this.account, required final List<int> regionOneNumbers, required this.regionTwoNumber, required this.multiplier, required this.drawStatus, required this.drawDate, required final List<int>? matchedRegionOneNumbers, required this.matchedRegionTwoNumber, required this.createdAt, required this.updatedAt, required this.deletedAt}): _regionOneNumbers = regionOneNumbers,_matchedRegionOneNumbers = matchedRegionOneNumbers;
|
||||
factory _SnLotteryTicket.fromJson(Map<String, dynamic> json) => _$SnLotteryTicketFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String accountId;
|
||||
@override final SnAccount? account;
|
||||
final List<int> _regionOneNumbers;
|
||||
@override List<int> get regionOneNumbers {
|
||||
if (_regionOneNumbers is EqualUnmodifiableListView) return _regionOneNumbers;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_regionOneNumbers);
|
||||
}
|
||||
|
||||
@override final int regionTwoNumber;
|
||||
@override final int multiplier;
|
||||
@override final int drawStatus;
|
||||
@override final DateTime? drawDate;
|
||||
final List<int>? _matchedRegionOneNumbers;
|
||||
@override List<int>? get matchedRegionOneNumbers {
|
||||
final value = _matchedRegionOneNumbers;
|
||||
if (value == null) return null;
|
||||
if (_matchedRegionOneNumbers is EqualUnmodifiableListView) return _matchedRegionOneNumbers;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(value);
|
||||
}
|
||||
|
||||
@override final int? matchedRegionTwoNumber;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
|
||||
/// Create a copy of SnLotteryTicket
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnLotteryTicketCopyWith<_SnLotteryTicket> get copyWith => __$SnLotteryTicketCopyWithImpl<_SnLotteryTicket>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnLotteryTicketToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnLotteryTicket&&(identical(other.id, id) || other.id == id)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&const DeepCollectionEquality().equals(other._regionOneNumbers, _regionOneNumbers)&&(identical(other.regionTwoNumber, regionTwoNumber) || other.regionTwoNumber == regionTwoNumber)&&(identical(other.multiplier, multiplier) || other.multiplier == multiplier)&&(identical(other.drawStatus, drawStatus) || other.drawStatus == drawStatus)&&(identical(other.drawDate, drawDate) || other.drawDate == drawDate)&&const DeepCollectionEquality().equals(other._matchedRegionOneNumbers, _matchedRegionOneNumbers)&&(identical(other.matchedRegionTwoNumber, matchedRegionTwoNumber) || other.matchedRegionTwoNumber == matchedRegionTwoNumber)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,accountId,account,const DeepCollectionEquality().hash(_regionOneNumbers),regionTwoNumber,multiplier,drawStatus,drawDate,const DeepCollectionEquality().hash(_matchedRegionOneNumbers),matchedRegionTwoNumber,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnLotteryTicket(id: $id, accountId: $accountId, account: $account, regionOneNumbers: $regionOneNumbers, regionTwoNumber: $regionTwoNumber, multiplier: $multiplier, drawStatus: $drawStatus, drawDate: $drawDate, matchedRegionOneNumbers: $matchedRegionOneNumbers, matchedRegionTwoNumber: $matchedRegionTwoNumber, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnLotteryTicketCopyWith<$Res> implements $SnLotteryTicketCopyWith<$Res> {
|
||||
factory _$SnLotteryTicketCopyWith(_SnLotteryTicket value, $Res Function(_SnLotteryTicket) _then) = __$SnLotteryTicketCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String accountId, SnAccount? account, List<int> regionOneNumbers, int regionTwoNumber, int multiplier, int drawStatus, DateTime? drawDate, List<int>? matchedRegionOneNumbers, int? matchedRegionTwoNumber, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@override $SnAccountCopyWith<$Res>? get account;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnLotteryTicketCopyWithImpl<$Res>
|
||||
implements _$SnLotteryTicketCopyWith<$Res> {
|
||||
__$SnLotteryTicketCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnLotteryTicket _self;
|
||||
final $Res Function(_SnLotteryTicket) _then;
|
||||
|
||||
/// Create a copy of SnLotteryTicket
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? accountId = null,Object? account = freezed,Object? regionOneNumbers = null,Object? regionTwoNumber = null,Object? multiplier = null,Object? drawStatus = null,Object? drawDate = freezed,Object? matchedRegionOneNumbers = freezed,Object? matchedRegionTwoNumber = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnLotteryTicket(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,regionOneNumbers: null == regionOneNumbers ? _self._regionOneNumbers : regionOneNumbers // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>,regionTwoNumber: null == regionTwoNumber ? _self.regionTwoNumber : regionTwoNumber // ignore: cast_nullable_to_non_nullable
|
||||
as int,multiplier: null == multiplier ? _self.multiplier : multiplier // ignore: cast_nullable_to_non_nullable
|
||||
as int,drawStatus: null == drawStatus ? _self.drawStatus : drawStatus // ignore: cast_nullable_to_non_nullable
|
||||
as int,drawDate: freezed == drawDate ? _self.drawDate : drawDate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,matchedRegionOneNumbers: freezed == matchedRegionOneNumbers ? _self._matchedRegionOneNumbers : matchedRegionOneNumbers // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>?,matchedRegionTwoNumber: freezed == matchedRegionTwoNumber ? _self.matchedRegionTwoNumber : matchedRegionTwoNumber // ignore: cast_nullable_to_non_nullable
|
||||
as int?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnLotteryTicket
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountCopyWith<$Res>? get account {
|
||||
if (_self.account == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnLotteryRecord {
|
||||
|
||||
String get id; DateTime get drawDate; List<int> get winningRegionOneNumbers; int get winningRegionTwoNumber; int get totalTickets; int get totalPrizesAwarded; double get totalPrizeAmount; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnLotteryRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnLotteryRecordCopyWith<SnLotteryRecord> get copyWith => _$SnLotteryRecordCopyWithImpl<SnLotteryRecord>(this as SnLotteryRecord, _$identity);
|
||||
|
||||
/// Serializes this SnLotteryRecord to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnLotteryRecord&&(identical(other.id, id) || other.id == id)&&(identical(other.drawDate, drawDate) || other.drawDate == drawDate)&&const DeepCollectionEquality().equals(other.winningRegionOneNumbers, winningRegionOneNumbers)&&(identical(other.winningRegionTwoNumber, winningRegionTwoNumber) || other.winningRegionTwoNumber == winningRegionTwoNumber)&&(identical(other.totalTickets, totalTickets) || other.totalTickets == totalTickets)&&(identical(other.totalPrizesAwarded, totalPrizesAwarded) || other.totalPrizesAwarded == totalPrizesAwarded)&&(identical(other.totalPrizeAmount, totalPrizeAmount) || other.totalPrizeAmount == totalPrizeAmount)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,drawDate,const DeepCollectionEquality().hash(winningRegionOneNumbers),winningRegionTwoNumber,totalTickets,totalPrizesAwarded,totalPrizeAmount,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnLotteryRecord(id: $id, drawDate: $drawDate, winningRegionOneNumbers: $winningRegionOneNumbers, winningRegionTwoNumber: $winningRegionTwoNumber, totalTickets: $totalTickets, totalPrizesAwarded: $totalPrizesAwarded, totalPrizeAmount: $totalPrizeAmount, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnLotteryRecordCopyWith<$Res> {
|
||||
factory $SnLotteryRecordCopyWith(SnLotteryRecord value, $Res Function(SnLotteryRecord) _then) = _$SnLotteryRecordCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, DateTime drawDate, List<int> winningRegionOneNumbers, int winningRegionTwoNumber, int totalTickets, int totalPrizesAwarded, double totalPrizeAmount, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnLotteryRecordCopyWithImpl<$Res>
|
||||
implements $SnLotteryRecordCopyWith<$Res> {
|
||||
_$SnLotteryRecordCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnLotteryRecord _self;
|
||||
final $Res Function(SnLotteryRecord) _then;
|
||||
|
||||
/// Create a copy of SnLotteryRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? drawDate = null,Object? winningRegionOneNumbers = null,Object? winningRegionTwoNumber = null,Object? totalTickets = null,Object? totalPrizesAwarded = null,Object? totalPrizeAmount = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,drawDate: null == drawDate ? _self.drawDate : drawDate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,winningRegionOneNumbers: null == winningRegionOneNumbers ? _self.winningRegionOneNumbers : winningRegionOneNumbers // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>,winningRegionTwoNumber: null == winningRegionTwoNumber ? _self.winningRegionTwoNumber : winningRegionTwoNumber // ignore: cast_nullable_to_non_nullable
|
||||
as int,totalTickets: null == totalTickets ? _self.totalTickets : totalTickets // ignore: cast_nullable_to_non_nullable
|
||||
as int,totalPrizesAwarded: null == totalPrizesAwarded ? _self.totalPrizesAwarded : totalPrizesAwarded // ignore: cast_nullable_to_non_nullable
|
||||
as int,totalPrizeAmount: null == totalPrizeAmount ? _self.totalPrizeAmount : totalPrizeAmount // ignore: cast_nullable_to_non_nullable
|
||||
as double,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnLotteryRecord].
|
||||
extension SnLotteryRecordPatterns on SnLotteryRecord {
|
||||
/// 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( _SnLotteryRecord value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryRecord() 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( _SnLotteryRecord value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryRecord():
|
||||
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( _SnLotteryRecord value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryRecord() 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, DateTime drawDate, List<int> winningRegionOneNumbers, int winningRegionTwoNumber, int totalTickets, int totalPrizesAwarded, double totalPrizeAmount, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryRecord() when $default != null:
|
||||
return $default(_that.id,_that.drawDate,_that.winningRegionOneNumbers,_that.winningRegionTwoNumber,_that.totalTickets,_that.totalPrizesAwarded,_that.totalPrizeAmount,_that.createdAt,_that.updatedAt,_that.deletedAt);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, DateTime drawDate, List<int> winningRegionOneNumbers, int winningRegionTwoNumber, int totalTickets, int totalPrizesAwarded, double totalPrizeAmount, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryRecord():
|
||||
return $default(_that.id,_that.drawDate,_that.winningRegionOneNumbers,_that.winningRegionTwoNumber,_that.totalTickets,_that.totalPrizesAwarded,_that.totalPrizeAmount,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
}
|
||||
/// 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, DateTime drawDate, List<int> winningRegionOneNumbers, int winningRegionTwoNumber, int totalTickets, int totalPrizesAwarded, double totalPrizeAmount, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnLotteryRecord() when $default != null:
|
||||
return $default(_that.id,_that.drawDate,_that.winningRegionOneNumbers,_that.winningRegionTwoNumber,_that.totalTickets,_that.totalPrizesAwarded,_that.totalPrizeAmount,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnLotteryRecord implements SnLotteryRecord {
|
||||
const _SnLotteryRecord({required this.id, required this.drawDate, required final List<int> winningRegionOneNumbers, required this.winningRegionTwoNumber, required this.totalTickets, required this.totalPrizesAwarded, required this.totalPrizeAmount, required this.createdAt, required this.updatedAt, required this.deletedAt}): _winningRegionOneNumbers = winningRegionOneNumbers;
|
||||
factory _SnLotteryRecord.fromJson(Map<String, dynamic> json) => _$SnLotteryRecordFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final DateTime drawDate;
|
||||
final List<int> _winningRegionOneNumbers;
|
||||
@override List<int> get winningRegionOneNumbers {
|
||||
if (_winningRegionOneNumbers is EqualUnmodifiableListView) return _winningRegionOneNumbers;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_winningRegionOneNumbers);
|
||||
}
|
||||
|
||||
@override final int winningRegionTwoNumber;
|
||||
@override final int totalTickets;
|
||||
@override final int totalPrizesAwarded;
|
||||
@override final double totalPrizeAmount;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
|
||||
/// Create a copy of SnLotteryRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnLotteryRecordCopyWith<_SnLotteryRecord> get copyWith => __$SnLotteryRecordCopyWithImpl<_SnLotteryRecord>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnLotteryRecordToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnLotteryRecord&&(identical(other.id, id) || other.id == id)&&(identical(other.drawDate, drawDate) || other.drawDate == drawDate)&&const DeepCollectionEquality().equals(other._winningRegionOneNumbers, _winningRegionOneNumbers)&&(identical(other.winningRegionTwoNumber, winningRegionTwoNumber) || other.winningRegionTwoNumber == winningRegionTwoNumber)&&(identical(other.totalTickets, totalTickets) || other.totalTickets == totalTickets)&&(identical(other.totalPrizesAwarded, totalPrizesAwarded) || other.totalPrizesAwarded == totalPrizesAwarded)&&(identical(other.totalPrizeAmount, totalPrizeAmount) || other.totalPrizeAmount == totalPrizeAmount)&&(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)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,drawDate,const DeepCollectionEquality().hash(_winningRegionOneNumbers),winningRegionTwoNumber,totalTickets,totalPrizesAwarded,totalPrizeAmount,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnLotteryRecord(id: $id, drawDate: $drawDate, winningRegionOneNumbers: $winningRegionOneNumbers, winningRegionTwoNumber: $winningRegionTwoNumber, totalTickets: $totalTickets, totalPrizesAwarded: $totalPrizesAwarded, totalPrizeAmount: $totalPrizeAmount, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnLotteryRecordCopyWith<$Res> implements $SnLotteryRecordCopyWith<$Res> {
|
||||
factory _$SnLotteryRecordCopyWith(_SnLotteryRecord value, $Res Function(_SnLotteryRecord) _then) = __$SnLotteryRecordCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, DateTime drawDate, List<int> winningRegionOneNumbers, int winningRegionTwoNumber, int totalTickets, int totalPrizesAwarded, double totalPrizeAmount, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnLotteryRecordCopyWithImpl<$Res>
|
||||
implements _$SnLotteryRecordCopyWith<$Res> {
|
||||
__$SnLotteryRecordCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnLotteryRecord _self;
|
||||
final $Res Function(_SnLotteryRecord) _then;
|
||||
|
||||
/// Create a copy of SnLotteryRecord
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? drawDate = null,Object? winningRegionOneNumbers = null,Object? winningRegionTwoNumber = null,Object? totalTickets = null,Object? totalPrizesAwarded = null,Object? totalPrizeAmount = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnLotteryRecord(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,drawDate: null == drawDate ? _self.drawDate : drawDate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,winningRegionOneNumbers: null == winningRegionOneNumbers ? _self._winningRegionOneNumbers : winningRegionOneNumbers // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>,winningRegionTwoNumber: null == winningRegionTwoNumber ? _self.winningRegionTwoNumber : winningRegionTwoNumber // ignore: cast_nullable_to_non_nullable
|
||||
as int,totalTickets: null == totalTickets ? _self.totalTickets : totalTickets // ignore: cast_nullable_to_non_nullable
|
||||
as int,totalPrizesAwarded: null == totalPrizesAwarded ? _self.totalPrizesAwarded : totalPrizesAwarded // ignore: cast_nullable_to_non_nullable
|
||||
as int,totalPrizeAmount: null == totalPrizeAmount ? _self.totalPrizeAmount : totalPrizeAmount // ignore: cast_nullable_to_non_nullable
|
||||
as double,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
|
||||
@@ -414,3 +414,88 @@ Map<String, dynamic> _$SnWalletFundRecipientToJson(
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
_SnLotteryTicket _$SnLotteryTicketFromJson(Map<String, dynamic> json) =>
|
||||
_SnLotteryTicket(
|
||||
id: json['id'] as String,
|
||||
accountId: json['account_id'] as String,
|
||||
account:
|
||||
json['account'] == null
|
||||
? null
|
||||
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||
regionOneNumbers:
|
||||
(json['region_one_numbers'] as List<dynamic>)
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
regionTwoNumber: (json['region_two_number'] as num).toInt(),
|
||||
multiplier: (json['multiplier'] as num).toInt(),
|
||||
drawStatus: (json['draw_status'] as num).toInt(),
|
||||
drawDate:
|
||||
json['draw_date'] == null
|
||||
? null
|
||||
: DateTime.parse(json['draw_date'] as String),
|
||||
matchedRegionOneNumbers:
|
||||
(json['matched_region_one_numbers'] as List<dynamic>?)
|
||||
?.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
matchedRegionTwoNumber:
|
||||
(json['matched_region_two_number'] as num?)?.toInt(),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnLotteryTicketToJson(_SnLotteryTicket instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'account_id': instance.accountId,
|
||||
'account': instance.account?.toJson(),
|
||||
'region_one_numbers': instance.regionOneNumbers,
|
||||
'region_two_number': instance.regionTwoNumber,
|
||||
'multiplier': instance.multiplier,
|
||||
'draw_status': instance.drawStatus,
|
||||
'draw_date': instance.drawDate?.toIso8601String(),
|
||||
'matched_region_one_numbers': instance.matchedRegionOneNumbers,
|
||||
'matched_region_two_number': instance.matchedRegionTwoNumber,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
_SnLotteryRecord _$SnLotteryRecordFromJson(Map<String, dynamic> json) =>
|
||||
_SnLotteryRecord(
|
||||
id: json['id'] as String,
|
||||
drawDate: DateTime.parse(json['draw_date'] as String),
|
||||
winningRegionOneNumbers:
|
||||
(json['winning_region_one_numbers'] as List<dynamic>)
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
winningRegionTwoNumber:
|
||||
(json['winning_region_two_number'] as num).toInt(),
|
||||
totalTickets: (json['total_tickets'] as num).toInt(),
|
||||
totalPrizesAwarded: (json['total_prizes_awarded'] as num).toInt(),
|
||||
totalPrizeAmount: (json['total_prize_amount'] as num).toDouble(),
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnLotteryRecordToJson(_SnLotteryRecord instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'draw_date': instance.drawDate.toIso8601String(),
|
||||
'winning_region_one_numbers': instance.winningRegionOneNumbers,
|
||||
'winning_region_two_number': instance.winningRegionTwoNumber,
|
||||
'total_tickets': instance.totalTickets,
|
||||
'total_prizes_awarded': instance.totalPrizesAwarded,
|
||||
'total_prize_amount': instance.totalPrizeAmount,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
@@ -433,7 +433,7 @@ Future<void> setRemoteActivityStatus(
|
||||
) async {
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.post(
|
||||
'/id/accounts/me/statuses',
|
||||
'/pass/accounts/me/statuses',
|
||||
data: {
|
||||
'is_invisible': false,
|
||||
'is_not_disturb': false,
|
||||
@@ -448,7 +448,7 @@ Future<void> setRemoteActivityStatus(
|
||||
Future<void> unsetRemoteActivityStatus(Ref ref, String appId) async {
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.delete(
|
||||
'/id/accounts/me/statuses',
|
||||
'/pass/accounts/me/statuses',
|
||||
queryParameters: {'app': appId},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -118,14 +118,18 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
Future<List<LocalChatMessage>> _getCachedMessages({
|
||||
int offset = 0,
|
||||
int take = 20,
|
||||
String? searchQuery,
|
||||
bool? withLinks,
|
||||
bool? withAttachments,
|
||||
}) async {
|
||||
talker.log('Getting cached messages from offset $offset, take $take');
|
||||
final List<LocalChatMessage> dbMessages;
|
||||
if (_searchQuery != null && _searchQuery!.isNotEmpty) {
|
||||
|
||||
if (searchQuery != null && searchQuery.isNotEmpty) {
|
||||
dbMessages = await _database.searchMessages(
|
||||
_roomId,
|
||||
_searchQuery ?? '',
|
||||
withAttachments: _withAttachments,
|
||||
searchQuery,
|
||||
withAttachments: withAttachments,
|
||||
);
|
||||
} else {
|
||||
final chatMessagesFromDb = await _database.getMessagesForRoom(
|
||||
@@ -139,11 +143,18 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
|
||||
List<LocalChatMessage> filteredMessages = dbMessages;
|
||||
|
||||
if (_withLinks == true) {
|
||||
if (withLinks == true) {
|
||||
filteredMessages =
|
||||
filteredMessages.where((msg) => _hasLink(msg)).toList();
|
||||
}
|
||||
|
||||
if (withAttachments == true) {
|
||||
filteredMessages =
|
||||
filteredMessages
|
||||
.where((msg) => msg.toRemoteMessage().attachments.isNotEmpty)
|
||||
.toList();
|
||||
}
|
||||
|
||||
final dbLocalMessages = filteredMessages;
|
||||
|
||||
// Always ensure unique messages to prevent duplicate keys
|
||||
@@ -177,6 +188,51 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
return uniqueMessages;
|
||||
}
|
||||
|
||||
/// Get all messages without search filters for jump operations
|
||||
Future<List<LocalChatMessage>> _getAllMessagesForJump({
|
||||
int offset = 0,
|
||||
int take = 20,
|
||||
}) async {
|
||||
talker.log('Getting all messages for jump from offset $offset, take $take');
|
||||
final chatMessagesFromDb = await _database.getMessagesForRoom(
|
||||
_roomId,
|
||||
offset: offset,
|
||||
limit: take,
|
||||
);
|
||||
final dbMessages =
|
||||
chatMessagesFromDb.map(_database.companionToMessage).toList();
|
||||
|
||||
// Always ensure unique messages to prevent duplicate keys
|
||||
final uniqueMessages = <LocalChatMessage>[];
|
||||
final seenIds = <String>{};
|
||||
for (final message in dbMessages) {
|
||||
if (seenIds.add(message.id)) {
|
||||
uniqueMessages.add(message);
|
||||
}
|
||||
}
|
||||
|
||||
if (offset == 0) {
|
||||
final pendingForRoom =
|
||||
_pendingMessages.values
|
||||
.where((msg) => msg.roomId == _roomId)
|
||||
.toList();
|
||||
|
||||
final allMessages = [...pendingForRoom, ...uniqueMessages];
|
||||
_sortMessages(allMessages);
|
||||
|
||||
final finalUniqueMessages = <LocalChatMessage>[];
|
||||
final finalSeenIds = <String>{};
|
||||
for (final message in allMessages) {
|
||||
if (finalSeenIds.add(message.id)) {
|
||||
finalUniqueMessages.add(message);
|
||||
}
|
||||
}
|
||||
return finalUniqueMessages;
|
||||
}
|
||||
|
||||
return uniqueMessages;
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> _fetchAndCacheMessages({
|
||||
int offset = 0,
|
||||
int take = 20,
|
||||
@@ -264,16 +320,6 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
final response = MessageSyncResponse.fromJson(resp.data);
|
||||
talker.log('Sync response: ${response.messages.length} changes');
|
||||
for (final message in response.messages) {
|
||||
switch (message.type) {
|
||||
case "messages.update":
|
||||
case "messages.update.links":
|
||||
await receiveMessageUpdate(message);
|
||||
break;
|
||||
case "messages.delete":
|
||||
await receiveMessageDeletion(message.id.toString());
|
||||
break;
|
||||
}
|
||||
// Still need receive the message to show the history actions
|
||||
await receiveMessage(message);
|
||||
}
|
||||
} catch (err, stackTrace) {
|
||||
@@ -309,6 +355,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
final localMessages = await _getCachedMessages(
|
||||
offset: offset,
|
||||
take: take,
|
||||
searchQuery: _searchQuery,
|
||||
withLinks: _withLinks,
|
||||
withAttachments: _withAttachments,
|
||||
);
|
||||
|
||||
if (localMessages.isNotEmpty) {
|
||||
@@ -324,6 +373,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
final localMessages = await _getCachedMessages(
|
||||
offset: offset,
|
||||
take: take,
|
||||
searchQuery: _searchQuery,
|
||||
withLinks: _withLinks,
|
||||
withAttachments: _withAttachments,
|
||||
);
|
||||
|
||||
if (localMessages.isNotEmpty) {
|
||||
@@ -339,7 +391,13 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
syncMessages();
|
||||
}
|
||||
|
||||
final messages = await _getCachedMessages(offset: 0, take: _pageSize);
|
||||
final messages = await _getCachedMessages(
|
||||
offset: 0,
|
||||
take: _pageSize,
|
||||
searchQuery: _searchQuery,
|
||||
withLinks: _withLinks,
|
||||
withAttachments: _withAttachments,
|
||||
);
|
||||
|
||||
_hasMore = messages.length == _pageSize;
|
||||
|
||||
@@ -571,6 +629,13 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
|
||||
Future<void> receiveMessage(SnChatMessage remoteMessage) async {
|
||||
if (remoteMessage.chatRoomId != _roomId) return;
|
||||
|
||||
// Block message receiving during jumps to prevent list resets
|
||||
if (_isJumping) {
|
||||
talker.log('Blocking message receive during jump operation');
|
||||
return;
|
||||
}
|
||||
|
||||
talker.log('Received new message ${remoteMessage.id}');
|
||||
|
||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
||||
@@ -616,6 +681,13 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
|
||||
Future<void> receiveMessageUpdate(SnChatMessage remoteMessage) async {
|
||||
if (remoteMessage.chatRoomId != _roomId) return;
|
||||
|
||||
// Block message updates during jumps to prevent list resets
|
||||
if (_isJumping) {
|
||||
talker.log('Blocking message update during jump operation');
|
||||
return;
|
||||
}
|
||||
|
||||
talker.log('Received message update ${remoteMessage.id}');
|
||||
|
||||
final targetId = remoteMessage.meta['message_id'] ?? remoteMessage.id;
|
||||
@@ -623,6 +695,8 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
remoteMessage.copyWith(
|
||||
id: targetId,
|
||||
meta: Map.of(remoteMessage.meta)..remove('message_id'),
|
||||
type: 'text',
|
||||
editedAt: remoteMessage.createdAt,
|
||||
),
|
||||
MessageStatus.sent,
|
||||
);
|
||||
@@ -639,6 +713,12 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
}
|
||||
|
||||
Future<void> receiveMessageDeletion(String messageId) async {
|
||||
// Block message deletions during jumps to prevent list resets
|
||||
if (_isJumping) {
|
||||
talker.log('Blocking message deletion during jump operation');
|
||||
return;
|
||||
}
|
||||
|
||||
talker.log('Received message deletion $messageId');
|
||||
_pendingMessages.remove(messageId);
|
||||
|
||||
@@ -677,13 +757,34 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
|
||||
Future<void> deleteMessage(String messageId) async {
|
||||
talker.log('Deleting message $messageId');
|
||||
|
||||
// Fetch message to check its status before attempting server delete
|
||||
final message = await fetchMessageById(messageId);
|
||||
if (message == null) {
|
||||
talker.log('Message $messageId not found for deletion');
|
||||
return;
|
||||
}
|
||||
|
||||
// Skip server delete for failed messages (never successfully sent)
|
||||
if (message.status == MessageStatus.failed) {
|
||||
talker.log('Skipping server delete for failed message $messageId');
|
||||
// For failed messages, remove them completely from the active list
|
||||
_pendingMessages.remove(messageId);
|
||||
await _database.deleteMessage(messageId);
|
||||
|
||||
final currentMessages = state.value ?? [];
|
||||
final newMessages =
|
||||
currentMessages.where((m) => m.id != messageId).toList();
|
||||
state = AsyncValue.data(newMessages);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await _apiClient.delete('/sphere/chat/$_roomId/messages/$messageId');
|
||||
await receiveMessageDeletion(messageId);
|
||||
} catch (err, stackTrace) {
|
||||
talker.log(
|
||||
'Error deleting message $messageId',
|
||||
|
||||
exception: err,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
@@ -691,6 +792,44 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
/// Get search results without updating shared state
|
||||
Future<List<LocalChatMessage>> getSearchResults(
|
||||
String query, {
|
||||
bool? withLinks,
|
||||
bool? withAttachments,
|
||||
}) async {
|
||||
final trimmedQuery = query.trim();
|
||||
final hasFilters = [withLinks, withAttachments].any((e) => e == true);
|
||||
|
||||
if (trimmedQuery.isEmpty && !hasFilters) {
|
||||
return [];
|
||||
}
|
||||
|
||||
talker.log(
|
||||
'Getting search results for query: $trimmedQuery, filters: links=$withLinks, attachments=$withAttachments',
|
||||
);
|
||||
|
||||
try {
|
||||
// When filtering without query, get more messages to ensure we find all matches
|
||||
final take = (trimmedQuery.isEmpty && hasFilters) ? 1000 : 50;
|
||||
final messages = await _getCachedMessages(
|
||||
offset: 0,
|
||||
take: take,
|
||||
searchQuery: trimmedQuery.isNotEmpty ? trimmedQuery : null,
|
||||
withLinks: withLinks,
|
||||
withAttachments: withAttachments,
|
||||
); // Limit initial search results
|
||||
return messages;
|
||||
} catch (e, stackTrace) {
|
||||
talker.log(
|
||||
'Error getting search results',
|
||||
exception: e,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> searchMessages(
|
||||
String query, {
|
||||
bool? withLinks,
|
||||
@@ -712,6 +851,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
final messages = await _getCachedMessages(
|
||||
offset: 0,
|
||||
take: 50,
|
||||
searchQuery: _searchQuery,
|
||||
withLinks: _withLinks,
|
||||
withAttachments: _withAttachments,
|
||||
); // Limit initial search results
|
||||
state = AsyncValue.data(messages);
|
||||
} catch (e, stackTrace) {
|
||||
@@ -791,10 +933,11 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
}
|
||||
|
||||
talker.log(
|
||||
'Message $messageId not in current state, loading messages around it',
|
||||
'Message $messageId not in current state, calculating position and loading messages around it',
|
||||
);
|
||||
|
||||
// Count messages newer than this one
|
||||
// Count messages newer than the target message to calculate optimal offset
|
||||
// Use full message list (not filtered by search) for accurate position calculation
|
||||
final query = _database.customSelect(
|
||||
'SELECT COUNT(*) as count FROM chat_messages WHERE room_id = ? AND created_at > ?',
|
||||
variables: [
|
||||
@@ -806,13 +949,17 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
final result = await query.getSingle();
|
||||
final newerCount = result.read<int>('count');
|
||||
|
||||
// Load messages around this position
|
||||
// Calculate offset to position target message in the middle of the loaded chunk
|
||||
const chunkSize = 100; // Load 100 messages around the target
|
||||
final offset =
|
||||
(newerCount - _pageSize ~/ 2).clamp(0, double.infinity).toInt();
|
||||
talker.log('Loading messages with offset $offset, take $_pageSize');
|
||||
final loadedMessages = await _getCachedMessages(
|
||||
(newerCount - chunkSize ~/ 2).clamp(0, double.infinity).toInt();
|
||||
talker.log(
|
||||
'Calculated offset $offset for target message (newer: $newerCount, chunk: $chunkSize)',
|
||||
);
|
||||
// Use full message list (not filtered by search) for jump operations
|
||||
final loadedMessages = await _getAllMessagesForJump(
|
||||
offset: offset,
|
||||
take: _pageSize,
|
||||
take: chunkSize,
|
||||
);
|
||||
|
||||
// Check if loaded messages are already in current state
|
||||
@@ -839,10 +986,31 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
);
|
||||
}
|
||||
|
||||
// Wait a bit for the UI to rebuild with new messages
|
||||
await Future.delayed(const Duration(milliseconds: 100));
|
||||
|
||||
final finalIndex = (state.value ?? []).indexWhere(
|
||||
(m) => m.id == messageId,
|
||||
);
|
||||
talker.log('Final index for message $messageId is $finalIndex');
|
||||
|
||||
// Verify the message is actually in the list before returning
|
||||
if (finalIndex == -1) {
|
||||
talker.log(
|
||||
'Message $messageId still not found after loading, trying direct fetch',
|
||||
);
|
||||
// Try to fetch and add the specific message if it's still not found
|
||||
final directMessage = await fetchMessageById(messageId);
|
||||
if (directMessage != null) {
|
||||
final currentList = state.value ?? [];
|
||||
final updatedList = [...currentList, directMessage];
|
||||
await _updateStateSafely(updatedList);
|
||||
final newIndex = updatedList.indexWhere((m) => m.id == messageId);
|
||||
talker.log('Added message directly, new index: $newIndex');
|
||||
return newIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return finalIndex;
|
||||
} finally {
|
||||
_isJumping = false;
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'messages_notifier.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$messagesNotifierHash() => r'70acac63c720987d8b1688500e3735f1c2d16fdc';
|
||||
String _$messagesNotifierHash() => r'6adefd9152cdd686c2a863964993f24c42d405b5';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
||||
@@ -34,6 +34,8 @@ const kAppDefaultPoolId = 'app_default_pool_id';
|
||||
const kAppMessageDisplayStyle = 'app_message_display_style';
|
||||
const kAppThemeMode = 'app_theme_mode';
|
||||
const kMaterialYouToggleStoreKey = 'app_theme_material_you';
|
||||
const kAppDisableAnimation = 'app_disable_animation';
|
||||
const kAppFabPosition = 'app_fab_position';
|
||||
const kFeaturedPostsCollapsedId =
|
||||
'featured_posts_collapsed_id'; // Key for storing the ID of the collapsed featured post
|
||||
|
||||
@@ -96,6 +98,8 @@ sealed class AppSettings with _$AppSettings {
|
||||
required String messageDisplayStyle,
|
||||
required String? themeMode,
|
||||
required bool useMaterial3,
|
||||
required bool disableAnimation,
|
||||
required String fabPosition,
|
||||
}) = _AppSettings;
|
||||
}
|
||||
|
||||
@@ -122,6 +126,8 @@ class AppSettingsNotifier extends _$AppSettingsNotifier {
|
||||
messageDisplayStyle: prefs.getString(kAppMessageDisplayStyle) ?? 'bubble',
|
||||
themeMode: prefs.getString(kAppThemeMode) ?? 'system',
|
||||
useMaterial3: prefs.getBool(kMaterialYouToggleStoreKey) ?? true,
|
||||
disableAnimation: prefs.getBool(kAppDisableAnimation) ?? false,
|
||||
fabPosition: prefs.getString(kAppFabPosition) ?? 'center',
|
||||
);
|
||||
}
|
||||
|
||||
@@ -273,6 +279,18 @@ class AppSettingsNotifier extends _$AppSettingsNotifier {
|
||||
}
|
||||
state = state.copyWith(customColors: value);
|
||||
}
|
||||
|
||||
void setDisableAnimation(bool value) {
|
||||
final prefs = ref.read(sharedPreferencesProvider);
|
||||
prefs.setBool(kAppDisableAnimation, value);
|
||||
state = state.copyWith(disableAnimation: value);
|
||||
}
|
||||
|
||||
void setFabPosition(String value) {
|
||||
final prefs = ref.read(sharedPreferencesProvider);
|
||||
prefs.setString(kAppFabPosition, value);
|
||||
state = state.copyWith(fabPosition: value);
|
||||
}
|
||||
}
|
||||
|
||||
final updateInfoProvider =
|
||||
|
||||
@@ -290,7 +290,7 @@ mixin _$AppSettings {
|
||||
ThemeColors? get customColors; Size? get windowSize;// The window size for desktop platforms
|
||||
double get windowOpacity;// The window opacity for desktop platforms
|
||||
double get cardTransparency;// The card background opacity
|
||||
String? get defaultPoolId; String get messageDisplayStyle; String? get themeMode; bool get useMaterial3;
|
||||
String? get defaultPoolId; String get messageDisplayStyle; String? get themeMode; bool get useMaterial3; bool get disableAnimation; String get fabPosition;
|
||||
/// Create a copy of AppSettings
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -301,16 +301,16 @@ $AppSettingsCopyWith<AppSettings> get copyWith => _$AppSettingsCopyWithImpl<AppS
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.customColors, customColors) || other.customColors == customColors)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)&&(identical(other.windowOpacity, windowOpacity) || other.windowOpacity == windowOpacity)&&(identical(other.cardTransparency, cardTransparency) || other.cardTransparency == cardTransparency)&&(identical(other.defaultPoolId, defaultPoolId) || other.defaultPoolId == defaultPoolId)&&(identical(other.messageDisplayStyle, messageDisplayStyle) || other.messageDisplayStyle == messageDisplayStyle)&&(identical(other.themeMode, themeMode) || other.themeMode == themeMode)&&(identical(other.useMaterial3, useMaterial3) || other.useMaterial3 == useMaterial3));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.customColors, customColors) || other.customColors == customColors)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)&&(identical(other.windowOpacity, windowOpacity) || other.windowOpacity == windowOpacity)&&(identical(other.cardTransparency, cardTransparency) || other.cardTransparency == cardTransparency)&&(identical(other.defaultPoolId, defaultPoolId) || other.defaultPoolId == defaultPoolId)&&(identical(other.messageDisplayStyle, messageDisplayStyle) || other.messageDisplayStyle == messageDisplayStyle)&&(identical(other.themeMode, themeMode) || other.themeMode == themeMode)&&(identical(other.useMaterial3, useMaterial3) || other.useMaterial3 == useMaterial3)&&(identical(other.disableAnimation, disableAnimation) || other.disableAnimation == disableAnimation)&&(identical(other.fabPosition, fabPosition) || other.fabPosition == fabPosition));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3);
|
||||
int get hashCode => Object.hashAll([runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3,disableAnimation,fabPosition]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3)';
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3, disableAnimation: $disableAnimation, fabPosition: $fabPosition)';
|
||||
}
|
||||
|
||||
|
||||
@@ -321,7 +321,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> {
|
||||
factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3
|
||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition
|
||||
});
|
||||
|
||||
|
||||
@@ -338,7 +338,7 @@ class _$AppSettingsCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of AppSettings
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? useMaterial3 = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? useMaterial3 = null,Object? disableAnimation = null,Object? fabPosition = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
||||
as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable
|
||||
@@ -357,7 +357,9 @@ as double,defaultPoolId: freezed == defaultPoolId ? _self.defaultPoolId : defaul
|
||||
as String?,messageDisplayStyle: null == messageDisplayStyle ? _self.messageDisplayStyle : messageDisplayStyle // ignore: cast_nullable_to_non_nullable
|
||||
as String,themeMode: freezed == themeMode ? _self.themeMode : themeMode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,useMaterial3: null == useMaterial3 ? _self.useMaterial3 : useMaterial3 // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
as bool,disableAnimation: null == disableAnimation ? _self.disableAnimation : disableAnimation // ignore: cast_nullable_to_non_nullable
|
||||
as bool,fabPosition: null == fabPosition ? _self.fabPosition : fabPosition // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
/// Create a copy of AppSettings
|
||||
@@ -451,10 +453,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AppSettings() when $default != null:
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3);case _:
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -472,10 +474,10 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AppSettings():
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3);}
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -489,10 +491,10 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AppSettings() when $default != null:
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3);case _:
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.customColors,_that.windowSize,_that.windowOpacity,_that.cardTransparency,_that.defaultPoolId,_that.messageDisplayStyle,_that.themeMode,_that.useMaterial3,_that.disableAnimation,_that.fabPosition);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -504,7 +506,7 @@ return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_tha
|
||||
|
||||
|
||||
class _AppSettings implements AppSettings {
|
||||
const _AppSettings({required this.autoTranslate, required this.dataSavingMode, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.customFonts, required this.appColorScheme, required this.customColors, required this.windowSize, required this.windowOpacity, required this.cardTransparency, required this.defaultPoolId, required this.messageDisplayStyle, required this.themeMode, required this.useMaterial3});
|
||||
const _AppSettings({required this.autoTranslate, required this.dataSavingMode, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.showBackgroundImage, required this.customFonts, required this.appColorScheme, required this.customColors, required this.windowSize, required this.windowOpacity, required this.cardTransparency, required this.defaultPoolId, required this.messageDisplayStyle, required this.themeMode, required this.useMaterial3, required this.disableAnimation, required this.fabPosition});
|
||||
|
||||
|
||||
@override final bool autoTranslate;
|
||||
@@ -528,6 +530,8 @@ class _AppSettings implements AppSettings {
|
||||
@override final String messageDisplayStyle;
|
||||
@override final String? themeMode;
|
||||
@override final bool useMaterial3;
|
||||
@override final bool disableAnimation;
|
||||
@override final String fabPosition;
|
||||
|
||||
/// Create a copy of AppSettings
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -539,16 +543,16 @@ _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.customColors, customColors) || other.customColors == customColors)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)&&(identical(other.windowOpacity, windowOpacity) || other.windowOpacity == windowOpacity)&&(identical(other.cardTransparency, cardTransparency) || other.cardTransparency == cardTransparency)&&(identical(other.defaultPoolId, defaultPoolId) || other.defaultPoolId == defaultPoolId)&&(identical(other.messageDisplayStyle, messageDisplayStyle) || other.messageDisplayStyle == messageDisplayStyle)&&(identical(other.themeMode, themeMode) || other.themeMode == themeMode)&&(identical(other.useMaterial3, useMaterial3) || other.useMaterial3 == useMaterial3));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.dataSavingMode, dataSavingMode) || other.dataSavingMode == dataSavingMode)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.showBackgroundImage, showBackgroundImage) || other.showBackgroundImage == showBackgroundImage)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.customColors, customColors) || other.customColors == customColors)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize)&&(identical(other.windowOpacity, windowOpacity) || other.windowOpacity == windowOpacity)&&(identical(other.cardTransparency, cardTransparency) || other.cardTransparency == cardTransparency)&&(identical(other.defaultPoolId, defaultPoolId) || other.defaultPoolId == defaultPoolId)&&(identical(other.messageDisplayStyle, messageDisplayStyle) || other.messageDisplayStyle == messageDisplayStyle)&&(identical(other.themeMode, themeMode) || other.themeMode == themeMode)&&(identical(other.useMaterial3, useMaterial3) || other.useMaterial3 == useMaterial3)&&(identical(other.disableAnimation, disableAnimation) || other.disableAnimation == disableAnimation)&&(identical(other.fabPosition, fabPosition) || other.fabPosition == fabPosition));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3);
|
||||
int get hashCode => Object.hashAll([runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,customColors,windowSize,windowOpacity,cardTransparency,defaultPoolId,messageDisplayStyle,themeMode,useMaterial3,disableAnimation,fabPosition]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3)';
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, customColors: $customColors, windowSize: $windowSize, windowOpacity: $windowOpacity, cardTransparency: $cardTransparency, defaultPoolId: $defaultPoolId, messageDisplayStyle: $messageDisplayStyle, themeMode: $themeMode, useMaterial3: $useMaterial3, disableAnimation: $disableAnimation, fabPosition: $fabPosition)';
|
||||
}
|
||||
|
||||
|
||||
@@ -559,7 +563,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith
|
||||
factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3
|
||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, ThemeColors? customColors, Size? windowSize, double windowOpacity, double cardTransparency, String? defaultPoolId, String messageDisplayStyle, String? themeMode, bool useMaterial3, bool disableAnimation, String fabPosition
|
||||
});
|
||||
|
||||
|
||||
@@ -576,7 +580,7 @@ class __$AppSettingsCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of AppSettings
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? useMaterial3 = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? dataSavingMode = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? showBackgroundImage = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? customColors = freezed,Object? windowSize = freezed,Object? windowOpacity = null,Object? cardTransparency = null,Object? defaultPoolId = freezed,Object? messageDisplayStyle = null,Object? themeMode = freezed,Object? useMaterial3 = null,Object? disableAnimation = null,Object? fabPosition = null,}) {
|
||||
return _then(_AppSettings(
|
||||
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
||||
as bool,dataSavingMode: null == dataSavingMode ? _self.dataSavingMode : dataSavingMode // ignore: cast_nullable_to_non_nullable
|
||||
@@ -595,7 +599,9 @@ as double,defaultPoolId: freezed == defaultPoolId ? _self.defaultPoolId : defaul
|
||||
as String?,messageDisplayStyle: null == messageDisplayStyle ? _self.messageDisplayStyle : messageDisplayStyle // ignore: cast_nullable_to_non_nullable
|
||||
as String,themeMode: freezed == themeMode ? _self.themeMode : themeMode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,useMaterial3: null == useMaterial3 ? _self.useMaterial3 : useMaterial3 // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
as bool,disableAnimation: null == disableAnimation ? _self.disableAnimation : disableAnimation // ignore: cast_nullable_to_non_nullable
|
||||
as bool,fabPosition: null == fabPosition ? _self.fabPosition : fabPosition // ignore: cast_nullable_to_non_nullable
|
||||
as String,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -30,7 +30,7 @@ Map<String, dynamic> _$ThemeColorsToJson(_ThemeColors instance) =>
|
||||
// **************************************************************************
|
||||
|
||||
String _$appSettingsNotifierHash() =>
|
||||
r'3ba2cdce76f3c4fed84f4108341c88a0a971bf3a';
|
||||
r'22b695f2023e3251db3296858acd701f7211d757';
|
||||
|
||||
/// See also [AppSettingsNotifier].
|
||||
@ProviderFor(AppSettingsNotifier)
|
||||
|
||||
@@ -44,7 +44,7 @@ Future<List<SnEventCalendarEntry>> eventCalendar(
|
||||
) async {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.get(
|
||||
'/id/accounts/${query.uname ?? 'me'}/calendar',
|
||||
'/pass/accounts/${query.uname ?? 'me'}/calendar',
|
||||
queryParameters: {'year': query.year, 'month': query.month},
|
||||
);
|
||||
return resp.data
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'event_calendar.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$eventCalendarHash() => r'72232fc044ac3c99b855dca37ff2f06a64be0afb';
|
||||
String _$eventCalendarHash() => r'3a33581c28bcd44bc5eb3abdb770171b4d275a5d';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
||||
@@ -2,6 +2,7 @@ import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
|
||||
import 'package:dio_smart_retry/dio_smart_retry.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
@@ -109,6 +110,16 @@ final apiClientProvider = Provider<Dio>((ref) {
|
||||
printResponseData: false,
|
||||
),
|
||||
),
|
||||
RetryInterceptor(
|
||||
dio: dio,
|
||||
retries: 3,
|
||||
retryDelays: const [
|
||||
Duration(milliseconds: 300),
|
||||
Duration(milliseconds: 500),
|
||||
Duration(milliseconds: 1000),
|
||||
],
|
||||
retryEvaluator: (err, _) => err.requestOptions.method == 'GET',
|
||||
),
|
||||
]);
|
||||
|
||||
return dio;
|
||||
|
||||
@@ -88,6 +88,7 @@ ThemeData createAppTheme(Brightness brightness, AppSettings settings) {
|
||||
color: colorScheme.surfaceContainer.withOpacity(
|
||||
settings.cardTransparency,
|
||||
),
|
||||
elevation: settings.cardTransparency < 1 ? 0 : null,
|
||||
),
|
||||
pageTransitionsTheme: PageTransitionsTheme(
|
||||
builders: {
|
||||
|
||||
@@ -26,7 +26,7 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
||||
}
|
||||
try {
|
||||
final client = _ref.read(apiClientProvider);
|
||||
final response = await client.get('/id/accounts/me');
|
||||
final response = await client.get('/pass/accounts/me');
|
||||
final user = SnAccount.fromJson(response.data);
|
||||
state = AsyncValue.data(user);
|
||||
|
||||
|
||||
462
lib/route.dart
462
lib/route.dart
@@ -10,13 +10,11 @@ import 'package:island/screens/developers/app_detail.dart';
|
||||
import 'package:island/screens/developers/bot_detail.dart';
|
||||
import 'package:island/screens/developers/edit_app.dart';
|
||||
import 'package:island/screens/developers/edit_bot.dart';
|
||||
import 'package:island/screens/developers/new_app.dart';
|
||||
import 'package:island/screens/developers/hub.dart';
|
||||
import 'package:island/screens/developers/new_app.dart';
|
||||
import 'package:island/screens/developers/new_bot.dart';
|
||||
import 'package:island/screens/developers/projects.dart';
|
||||
import 'package:island/screens/developers/edit_project.dart';
|
||||
import 'package:island/screens/developers/new_project.dart';
|
||||
import 'package:island/screens/developers/project_detail.dart';
|
||||
import 'package:island/screens/discovery/articles.dart';
|
||||
import 'package:island/screens/files/file_list.dart';
|
||||
import 'package:island/screens/posts/post_categories_list.dart';
|
||||
@@ -27,7 +25,6 @@ import 'package:island/screens/tabs.dart';
|
||||
import 'package:island/screens/explore.dart';
|
||||
import 'package:island/screens/discovery/article_detail.dart';
|
||||
import 'package:island/screens/account.dart';
|
||||
import 'package:island/screens/notification.dart';
|
||||
import 'package:island/screens/wallet.dart';
|
||||
import 'package:island/screens/account/relationship.dart';
|
||||
import 'package:island/screens/account/profile.dart';
|
||||
@@ -40,10 +37,10 @@ import 'package:island/screens/chat/room.dart';
|
||||
import 'package:island/screens/chat/room_detail.dart';
|
||||
import 'package:island/screens/chat/call.dart';
|
||||
import 'package:island/screens/chat/search_messages.dart';
|
||||
import 'package:island/screens/thought/think.dart';
|
||||
import 'package:island/screens/creators/hub.dart';
|
||||
import 'package:island/screens/creators/posts/post_manage_list.dart';
|
||||
import 'package:island/screens/creators/stickers/stickers.dart';
|
||||
import 'package:island/screens/creators/stickers/pack_detail.dart';
|
||||
import 'package:island/screens/stickers/sticker_marketplace.dart';
|
||||
import 'package:island/screens/stickers/pack_detail.dart';
|
||||
import 'package:island/screens/discovery/feeds/feed_marketplace.dart';
|
||||
@@ -51,7 +48,6 @@ import 'package:island/screens/discovery/feeds/feed_detail.dart';
|
||||
import 'package:island/screens/creators/poll/poll_list.dart';
|
||||
import 'package:island/screens/creators/publishers_form.dart';
|
||||
import 'package:island/screens/creators/webfeed/webfeed_list.dart';
|
||||
import 'package:island/screens/creators/webfeed/webfeed_edit.dart';
|
||||
import 'package:island/screens/poll/poll_editor.dart';
|
||||
import 'package:island/screens/posts/compose.dart';
|
||||
import 'package:island/screens/posts/post_detail.dart';
|
||||
@@ -62,7 +58,6 @@ import 'package:island/screens/settings.dart';
|
||||
import 'package:island/screens/realm/realms.dart';
|
||||
import 'package:island/screens/realm/realm_form.dart';
|
||||
import 'package:island/screens/realm/realm_detail.dart';
|
||||
import 'package:island/screens/account/event_calendar.dart';
|
||||
import 'package:island/screens/discovery/realms.dart';
|
||||
import 'package:island/screens/reports/report_detail.dart';
|
||||
import 'package:island/screens/reports/report_list.dart';
|
||||
@@ -137,269 +132,16 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
return CallScreen(roomId: id);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'thought',
|
||||
path: '/thought',
|
||||
builder: (context, state) => const ThoughtScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'logs',
|
||||
path: '/logs',
|
||||
builder: (context, state) => TalkerScreen(talker: talker),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'accountCalendar',
|
||||
path: '/account/:name/calendar',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return EventCalanderScreen(name: name);
|
||||
},
|
||||
),
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) => CreatorHubShellScreen(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'creatorHub',
|
||||
path: '/creators',
|
||||
builder: (context, state) => const CreatorHubScreen(),
|
||||
),
|
||||
// Web Feed Routes
|
||||
GoRoute(
|
||||
name: 'creatorFeeds',
|
||||
path: '/creators/:name/feeds',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return WebFeedListScreen(pubName: name);
|
||||
},
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'creatorFeedNew',
|
||||
path: 'new',
|
||||
builder: (context, state) {
|
||||
return WebFeedNewScreen(
|
||||
pubName: state.pathParameters['name']!,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorFeedEdit',
|
||||
path: ':feedId',
|
||||
builder: (context, state) {
|
||||
return WebFeedEditScreen(
|
||||
pubName: state.pathParameters['name']!,
|
||||
feedId: state.pathParameters['feedId'],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorPosts',
|
||||
path: '/creators/:name/posts',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return CreatorPostListScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
// Poll list route
|
||||
GoRoute(
|
||||
name: 'creatorPolls',
|
||||
path: '/creators/:name/polls',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return CreatorPollListScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
// Poll routes
|
||||
GoRoute(
|
||||
name: 'creatorPollNew',
|
||||
path: '/creators/:name/polls/new',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
// initialPollId left null for create; initialPublisher prefilled
|
||||
return PollEditorScreen(initialPublisher: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorPollEdit',
|
||||
path: '/creators/:name/polls/:id/edit',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
final id = state.pathParameters['id']!;
|
||||
return PollEditorScreen(
|
||||
initialPollId: id,
|
||||
initialPublisher: name,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorStickers',
|
||||
path: '/creators/:name/stickers',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return StickersScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorStickerPackNew',
|
||||
path: '/creators/:name/stickers/new',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return NewStickerPacksScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorStickerPackEdit',
|
||||
path: '/creators/:name/stickers/:packId/edit',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
final packId = state.pathParameters['packId']!;
|
||||
return EditStickerPacksScreen(pubName: name, packId: packId);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorStickerPackDetail',
|
||||
path: '/creators/:name/stickers/:packId',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
final packId = state.pathParameters['packId']!;
|
||||
return StickerPackDetailScreen(pubName: name, id: packId);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorStickerNew',
|
||||
path: '/creators/:name/stickers/:packId/new',
|
||||
builder: (context, state) {
|
||||
final packId = state.pathParameters['packId']!;
|
||||
return NewStickersScreen(packId: packId);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorStickerEdit',
|
||||
path: '/creators/:name/stickers/:packId/:id/edit',
|
||||
builder: (context, state) {
|
||||
final packId = state.pathParameters['packId']!;
|
||||
final id = state.pathParameters['id']!;
|
||||
return EditStickersScreen(id: id, packId: packId);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorNew',
|
||||
path: '/creators/new',
|
||||
builder: (context, state) => const NewPublisherScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorEdit',
|
||||
path: '/creators/:name/edit',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return EditPublisherScreen(name: name);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) =>
|
||||
DeveloperHubShellScreen(child: child),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'developerHub',
|
||||
path: '/developers',
|
||||
builder: (context, state) => const DeveloperHubScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerProjects',
|
||||
path: '/developers/:name/projects',
|
||||
builder:
|
||||
(context, state) => DevProjectsScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerProjectNew',
|
||||
path: '/developers/:name/projects/new',
|
||||
builder:
|
||||
(context, state) => NewProjectScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerProjectEdit',
|
||||
path: '/developers/:name/projects/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditProjectScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
id: state.pathParameters['id']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerProjectDetail',
|
||||
path: '/developers/:name/projects/:projectId',
|
||||
builder:
|
||||
(context, state) => ProjectDetailScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'developerAppNew',
|
||||
path: 'apps/new',
|
||||
builder:
|
||||
(context, state) => NewCustomAppScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerAppEdit',
|
||||
path: 'apps/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditAppScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
id: state.pathParameters['id']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerAppDetail',
|
||||
path: 'apps/:appId',
|
||||
builder:
|
||||
(context, state) => AppDetailScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
appId: state.pathParameters['appId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotNew',
|
||||
path: 'bots/new',
|
||||
builder:
|
||||
(context, state) => NewBotScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotDetail',
|
||||
path: 'bots/:botId',
|
||||
builder:
|
||||
(context, state) => BotDetailScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
botId: state.pathParameters['botId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotEdit',
|
||||
path: 'bots/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditBotScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
id: state.pathParameters['id']!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// Web articles
|
||||
GoRoute(
|
||||
@@ -655,11 +397,6 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
name: 'notifications',
|
||||
path: '/account/notifications',
|
||||
builder: (context, state) => const NotificationScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'wallet',
|
||||
path: '/account/wallet',
|
||||
@@ -708,12 +445,195 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
|
||||
GoRoute(
|
||||
name: 'accountProfile',
|
||||
path: '/account/:name',
|
||||
path: '/accounts/:name',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return AccountProfileScreen(name: name);
|
||||
},
|
||||
),
|
||||
// Creator hub tab
|
||||
GoRoute(
|
||||
name: 'creatorHub',
|
||||
path: '/creators',
|
||||
builder: (context, state) => const CreatorHubScreen(),
|
||||
routes: [
|
||||
// Web Feed Routes
|
||||
GoRoute(
|
||||
name: 'creatorFeeds',
|
||||
path: ':name/feeds',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return WebFeedListScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorPosts',
|
||||
path: ':name/posts',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return CreatorPostListScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
// Poll list route
|
||||
GoRoute(
|
||||
name: 'creatorPolls',
|
||||
path: ':name/polls',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return CreatorPollListScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
// Poll routes
|
||||
GoRoute(
|
||||
name: 'creatorPollNew',
|
||||
path: ':name/polls/new',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
// initialPollId left null for create; initialPublisher prefilled
|
||||
return PollEditorScreen(initialPublisher: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorPollEdit',
|
||||
path: ':name/polls/:id/edit',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
final id = state.pathParameters['id']!;
|
||||
return PollEditorScreen(
|
||||
initialPollId: id,
|
||||
initialPublisher: name,
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorStickers',
|
||||
path: ':name/stickers',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return StickersScreen(pubName: name);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorNew',
|
||||
path: 'new',
|
||||
builder: (context, state) => const NewPublisherScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'creatorEdit',
|
||||
path: ':name/edit',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
return EditPublisherScreen(name: name);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
// Developer hub tab
|
||||
GoRoute(
|
||||
name: 'developerHub',
|
||||
path: '/developers',
|
||||
builder:
|
||||
(context, state) => DeveloperHubScreen(
|
||||
initialPublisherName:
|
||||
state.uri.queryParameters['publisher'],
|
||||
initialProjectId: state.uri.queryParameters['project'],
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'developerProjectNew',
|
||||
path: ':name/projects/new',
|
||||
builder:
|
||||
(context, state) => NewProjectScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerProjectEdit',
|
||||
path: ':name/projects/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditProjectScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
id: state.pathParameters['id']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerProjectDetail',
|
||||
path: ':name/projects/:projectId',
|
||||
builder: (context, state) {
|
||||
final name = state.pathParameters['name']!;
|
||||
final projectId = state.pathParameters['projectId']!;
|
||||
// Redirect to hub with project selected
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
context.go(
|
||||
'/developers?publisher=$name&project=$projectId',
|
||||
);
|
||||
});
|
||||
return const SizedBox.shrink(); // Temporary placeholder
|
||||
},
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'developerAppNew',
|
||||
path: 'apps/new',
|
||||
builder:
|
||||
(context, state) => NewCustomAppScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerAppEdit',
|
||||
path: 'apps/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditAppScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
id: state.pathParameters['id']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerAppDetail',
|
||||
path: 'apps/:appId',
|
||||
builder:
|
||||
(context, state) => AppDetailScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
appId: state.pathParameters['appId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotNew',
|
||||
path: 'bots/new',
|
||||
builder:
|
||||
(context, state) => NewBotScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotDetail',
|
||||
path: 'bots/:botId',
|
||||
builder:
|
||||
(context, state) => BotDetailScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
botId: state.pathParameters['botId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotEdit',
|
||||
path: 'bots/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditBotScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
id: state.pathParameters['id']!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
|
||||
@@ -149,7 +149,8 @@ class AccountScreen extends HookConsumerWidget {
|
||||
context.pushNamed('leveling');
|
||||
},
|
||||
).padding(horizontal: 12),
|
||||
const SizedBox.shrink(),
|
||||
if (!isWideScreen(context)) const SizedBox.shrink(),
|
||||
if (!isWideScreen(context))
|
||||
Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
@@ -175,7 +176,7 @@ class AccountScreen extends HookConsumerWidget {
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12),
|
||||
onTap: () {
|
||||
context.pushNamed('creatorHub');
|
||||
context.goNamed('creatorHub');
|
||||
},
|
||||
),
|
||||
).height(140),
|
||||
@@ -202,7 +203,7 @@ class AccountScreen extends HookConsumerWidget {
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12),
|
||||
onTap: () {
|
||||
context.pushNamed('developerHub');
|
||||
context.goNamed('developerHub');
|
||||
},
|
||||
),
|
||||
).height(140),
|
||||
@@ -210,71 +211,62 @@ class AccountScreen extends HookConsumerWidget {
|
||||
],
|
||||
).padding(horizontal: 12),
|
||||
const SizedBox.shrink(),
|
||||
Row(
|
||||
SingleChildScrollView(
|
||||
scrollDirection: Axis.horizontal,
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Card(
|
||||
Card(
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(Symbols.settings, size: 28).padding(bottom: 8),
|
||||
Text('appSettings').tr().fontSize(16).bold(),
|
||||
Icon(Symbols.settings, size: 20),
|
||||
Text('appSettings').tr().fontSize(13).bold(),
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12),
|
||||
onTap: () {
|
||||
context.pushNamed('settings');
|
||||
},
|
||||
),
|
||||
).height(120),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
Card(
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.person_edit,
|
||||
size: 28,
|
||||
).padding(bottom: 8),
|
||||
Text('updateYourProfile').tr().fontSize(16).bold(),
|
||||
Icon(Symbols.person_edit, size: 20),
|
||||
Text('updateYourProfile').tr().fontSize(13).bold(),
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12),
|
||||
onTap: () {
|
||||
context.pushNamed('profileUpdate');
|
||||
},
|
||||
),
|
||||
).height(120),
|
||||
),
|
||||
Expanded(
|
||||
child: Card(
|
||||
Card(
|
||||
margin: EdgeInsets.zero,
|
||||
child: InkWell(
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
child: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Icon(
|
||||
Symbols.manage_accounts,
|
||||
size: 28,
|
||||
).padding(bottom: 8),
|
||||
Text('accountSettings').tr().fontSize(16).bold(),
|
||||
Icon(Symbols.manage_accounts, size: 20),
|
||||
Text('accountSettings').tr().fontSize(13).bold(),
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12),
|
||||
onTap: () {
|
||||
context.pushNamed('accountSettings');
|
||||
},
|
||||
),
|
||||
).height(120),
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 12),
|
||||
).height(48),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.notifications),
|
||||
@@ -290,7 +282,12 @@ class AccountScreen extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
context.pushNamed('notifications');
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
useRootNavigator: true,
|
||||
builder: (context) => const NotificationSheet(),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
@@ -386,7 +383,7 @@ class AccountScreen extends HookConsumerWidget {
|
||||
onTap: () async {
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
showLoadingModal(context);
|
||||
await apiClient.delete('/id/accounts/me/sessions/current');
|
||||
await apiClient.delete('/pass/accounts/me/sessions/current');
|
||||
if (!context.mounted) return;
|
||||
hideLoadingModal(context);
|
||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||
|
||||
@@ -14,7 +14,7 @@ part 'credits.g.dart';
|
||||
@riverpod
|
||||
Future<double> socialCredits(Ref ref) async {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final response = await client.get('/id/accounts/me/credits');
|
||||
final response = await client.get('/pass/accounts/me/credits');
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to load social credits');
|
||||
}
|
||||
@@ -39,7 +39,7 @@ class SocialCreditHistoryNotifier extends _$SocialCreditHistoryNotifier
|
||||
final queryParams = {'offset': offset, 'take': _pageSize};
|
||||
|
||||
final response = await client.get(
|
||||
'/id/accounts/me/credits/history',
|
||||
'/pass/accounts/me/credits/history',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'credits.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$socialCreditsHash() => r'2599844e892127ee4d315caced5c10e4dbaea142';
|
||||
String _$socialCreditsHash() => r'a0284583e94bc97285c689ac2bc018536932da69';
|
||||
|
||||
/// See also [socialCredits].
|
||||
@ProviderFor(socialCredits)
|
||||
@@ -25,7 +25,7 @@ final socialCreditsProvider = AutoDisposeFutureProvider<double>.internal(
|
||||
// ignore: unused_element
|
||||
typedef SocialCreditsRef = AutoDisposeFutureProviderRef<double>;
|
||||
String _$socialCreditHistoryNotifierHash() =>
|
||||
r'950db020754160f835c64cedf3fa2175e61e4d64';
|
||||
r'3e87af246cc5dc72a1f3a87b81d1c87169bdfb5b';
|
||||
|
||||
/// See also [SocialCreditHistoryNotifier].
|
||||
@ProviderFor(SocialCreditHistoryNotifier)
|
||||
|
||||
@@ -34,7 +34,7 @@ class LevelingHistoryNotifier extends _$LevelingHistoryNotifier
|
||||
final queryParams = {'offset': offset, 'take': _pageSize};
|
||||
|
||||
final response = await client.get(
|
||||
'/id/accounts/me/leveling',
|
||||
'/pass/accounts/me/leveling',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
|
||||
@@ -7,7 +7,7 @@ part of 'leveling.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$levelingHistoryNotifierHash() =>
|
||||
r'e795f9b7911c9e50f15c095ea237cb0e87bf1e89';
|
||||
r'de51012e1590ac46388b6f3f2050b21cb96698d1';
|
||||
|
||||
/// See also [LevelingHistoryNotifier].
|
||||
@ProviderFor(LevelingHistoryNotifier)
|
||||
|
||||
@@ -28,14 +28,14 @@ part 'account_settings.g.dart';
|
||||
@riverpod
|
||||
Future<List<SnAuthFactor>> authFactors(Ref ref) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final res = await client.get('/id/accounts/me/factors');
|
||||
final res = await client.get('/pass/accounts/me/factors');
|
||||
return res.data.map<SnAuthFactor>((e) => SnAuthFactor.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Future<List<SnContactMethod>> contactMethods(Ref ref) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final resp = await client.get('/id/accounts/me/contacts');
|
||||
final resp = await client.get('/pass/accounts/me/contacts');
|
||||
return resp.data
|
||||
.map<SnContactMethod>((e) => SnContactMethod.fromJson(e))
|
||||
.toList();
|
||||
@@ -44,7 +44,7 @@ Future<List<SnContactMethod>> contactMethods(Ref ref) async {
|
||||
@riverpod
|
||||
Future<List<SnAccountConnection>> accountConnections(Ref ref) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final resp = await client.get('/id/accounts/me/connections');
|
||||
final resp = await client.get('/pass/accounts/me/connections');
|
||||
return resp.data
|
||||
.map<SnAccountConnection>((e) => SnAccountConnection.fromJson(e))
|
||||
.toList();
|
||||
@@ -67,7 +67,7 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete('/id/accounts/me');
|
||||
await client.delete('/pass/accounts/me');
|
||||
if (context.mounted) {
|
||||
showSnackBar('accountDeletionSent'.tr());
|
||||
}
|
||||
@@ -93,7 +93,7 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
||||
final userInfo = ref.read(userInfoProvider);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post(
|
||||
'/id/accounts/recovery/password',
|
||||
'/pass/accounts/recovery/password',
|
||||
data: {'account': userInfo.value!.name, 'captcha_token': captchaTk},
|
||||
);
|
||||
if (context.mounted) {
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'account_settings.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$authFactorsHash() => r'24fe2f7b375b019d87fc3b85cbedbe857f399c0f';
|
||||
String _$authFactorsHash() => r'ed87d7dbd421fef0a5620416727c3dc598c97ef5';
|
||||
|
||||
/// See also [authFactors].
|
||||
@ProviderFor(authFactors)
|
||||
@@ -25,7 +25,7 @@ final authFactorsProvider =
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef AuthFactorsRef = AutoDisposeFutureProviderRef<List<SnAuthFactor>>;
|
||||
String _$contactMethodsHash() => r'76a1a93f61c51c44b32b4821f5112d58406155f0';
|
||||
String _$contactMethodsHash() => r'1d3d03e9ffbf36126236558ead22cb7d88bb9cb2';
|
||||
|
||||
/// See also [contactMethods].
|
||||
@ProviderFor(contactMethods)
|
||||
@@ -45,7 +45,7 @@ final contactMethodsProvider =
|
||||
// ignore: unused_element
|
||||
typedef ContactMethodsRef = AutoDisposeFutureProviderRef<List<SnContactMethod>>;
|
||||
String _$accountConnectionsHash() =>
|
||||
r'9f69e7f23e3e53c528d38b93d76f0c9efc9a83db';
|
||||
r'33c10b98962ede6c428d4028c0d5f2f12ff0eb22';
|
||||
|
||||
/// See also [accountConnections].
|
||||
@ProviderFor(accountConnections)
|
||||
|
||||
@@ -14,6 +14,7 @@ import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/services/file.dart';
|
||||
import 'package:island/services/file_uploader.dart';
|
||||
import 'package:island/services/timezone.dart';
|
||||
import 'package:island/widgets/account/account_name.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
@@ -24,6 +25,17 @@ const kServerSupportedLanguages = {'en-US': 'en-us', 'zh-CN': 'zh-hans'};
|
||||
const kServerSupportedRegions = ['US', 'JP', 'CN'];
|
||||
|
||||
class UpdateProfileScreen extends HookConsumerWidget {
|
||||
bool _isValidHexColor(String color) {
|
||||
if (!color.startsWith('#')) return false;
|
||||
if (color.length != 7) return false; // #RRGGBB format
|
||||
try {
|
||||
int.parse(color.substring(1), radix: 16);
|
||||
return true;
|
||||
} catch (_) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const UpdateProfileScreen({super.key});
|
||||
|
||||
@override
|
||||
@@ -75,7 +87,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
}
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.patch(
|
||||
'/id/accounts/me/profile',
|
||||
'/pass/accounts/me/profile',
|
||||
data: {'${position}_id': cloudFile.id},
|
||||
);
|
||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||
@@ -102,7 +114,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
try {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.patch(
|
||||
'/id/accounts/me',
|
||||
'/pass/accounts/me',
|
||||
data: {
|
||||
'name': usernameController.text,
|
||||
'nick': nicknameController.text,
|
||||
@@ -148,14 +160,41 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
text: user.value!.profile.timeZone,
|
||||
);
|
||||
|
||||
// Username color state
|
||||
final usernameColorType = useState<String>(
|
||||
user.value!.profile.usernameColor?.type ?? 'plain',
|
||||
);
|
||||
final usernameColorValue = useTextEditingController(
|
||||
text: user.value!.profile.usernameColor?.value,
|
||||
);
|
||||
final usernameColorDirection = useTextEditingController(
|
||||
text: user.value!.profile.usernameColor?.direction,
|
||||
);
|
||||
final usernameColorColors = useState<List<String>>(
|
||||
user.value!.profile.usernameColor?.colors ?? [],
|
||||
);
|
||||
|
||||
void updateProfile() async {
|
||||
if (!formKeyProfile.currentState!.validate()) return;
|
||||
|
||||
submitting.value = true;
|
||||
try {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final usernameColorData = {
|
||||
'type': usernameColorType.value,
|
||||
if (usernameColorType.value == 'plain' &&
|
||||
usernameColorValue.text.isNotEmpty)
|
||||
'value': usernameColorValue.text,
|
||||
if (usernameColorType.value == 'gradient') ...{
|
||||
if (usernameColorDirection.text.isNotEmpty)
|
||||
'direction': usernameColorDirection.text,
|
||||
'colors':
|
||||
usernameColorColors.value.where((c) => c.isNotEmpty).toList(),
|
||||
},
|
||||
};
|
||||
|
||||
await client.patch(
|
||||
'/id/accounts/me/profile',
|
||||
'/pass/accounts/me/profile',
|
||||
data: {
|
||||
'bio': bioController.text,
|
||||
'first_name': firstNameController.text,
|
||||
@@ -166,6 +205,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
'location': locationController.text,
|
||||
'time_zone': timeZoneController.text,
|
||||
'birthday': birthday.value?.toUtc().toIso8601String(),
|
||||
'username_color': usernameColorData,
|
||||
'links':
|
||||
links.value
|
||||
.where((e) => e.name.isNotEmpty && e.url.isNotEmpty)
|
||||
@@ -593,6 +633,320 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'usernameColor',
|
||||
).tr().bold().fontSize(18).padding(top: 16),
|
||||
Column(
|
||||
spacing: 16,
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
// Preview section
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
decoration: BoxDecoration(
|
||||
color:
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.surfaceContainerHighest,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text('preview').tr().bold().fontSize(14),
|
||||
const Gap(8),
|
||||
// Create a preview account with the current settings
|
||||
Builder(
|
||||
builder: (context) {
|
||||
final previewAccount = user.value!.copyWith(
|
||||
profile: user.value!.profile.copyWith(
|
||||
usernameColor: UsernameColor(
|
||||
type: usernameColorType.value,
|
||||
value:
|
||||
usernameColorType.value == 'plain' &&
|
||||
usernameColorValue
|
||||
.text
|
||||
.isNotEmpty
|
||||
? usernameColorValue.text
|
||||
: null,
|
||||
direction:
|
||||
usernameColorType.value ==
|
||||
'gradient' &&
|
||||
usernameColorDirection
|
||||
.text
|
||||
.isNotEmpty
|
||||
? usernameColorDirection.text
|
||||
: null,
|
||||
colors:
|
||||
usernameColorType.value == 'gradient'
|
||||
? usernameColorColors.value
|
||||
.where((c) => c.isNotEmpty)
|
||||
.toList()
|
||||
: null,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
// Check if user can use this color
|
||||
final tier =
|
||||
user.value!.perkSubscription?.identifier;
|
||||
final canUseColor = switch (tier) {
|
||||
'solian.stellar.primary' =>
|
||||
usernameColorType.value == 'plain' &&
|
||||
(kUsernamePlainColors.containsKey(
|
||||
usernameColorValue.text,
|
||||
) ||
|
||||
(usernameColorValue.text.startsWith(
|
||||
'#',
|
||||
) &&
|
||||
_isValidHexColor(
|
||||
usernameColorValue.text,
|
||||
))),
|
||||
'solian.stellar.nova' =>
|
||||
usernameColorType.value == 'plain',
|
||||
'solian.stellar.supernova' => true,
|
||||
_ => false,
|
||||
};
|
||||
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
AccountName(
|
||||
account: previewAccount,
|
||||
style: const TextStyle(fontSize: 18),
|
||||
ignorePermissions: true,
|
||||
),
|
||||
const Gap(4),
|
||||
Row(
|
||||
children: [
|
||||
Icon(
|
||||
canUseColor
|
||||
? Symbols.check_circle
|
||||
: Symbols.error,
|
||||
size: 16,
|
||||
color:
|
||||
canUseColor
|
||||
? Colors.green
|
||||
: Colors.red,
|
||||
),
|
||||
const Gap(4),
|
||||
Text(
|
||||
canUseColor
|
||||
? 'availableWithYourPlan'.tr()
|
||||
: 'upgradeRequired'.tr(),
|
||||
style: TextStyle(
|
||||
fontSize: 12,
|
||||
color:
|
||||
canUseColor
|
||||
? Colors.green
|
||||
: Colors.red,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
DropdownButtonFormField2<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'colorType'.tr(),
|
||||
),
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: 'plain',
|
||||
child: Text('plain'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'gradient',
|
||||
child: Text('gradient'.tr()),
|
||||
),
|
||||
],
|
||||
value: usernameColorType.value,
|
||||
onChanged: (value) {
|
||||
usernameColorType.value = value ?? 'plain';
|
||||
},
|
||||
customButton: Row(
|
||||
children: [
|
||||
Expanded(child: Text(usernameColorType.value).tr()),
|
||||
Icon(Symbols.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
if (usernameColorType.value == 'plain')
|
||||
Autocomplete<String>(
|
||||
optionsBuilder: (TextEditingValue textEditingValue) {
|
||||
final options = kUsernamePlainColors.keys.toList();
|
||||
if (textEditingValue.text == '') {
|
||||
return options;
|
||||
}
|
||||
return options.where(
|
||||
(option) => option.toLowerCase().contains(
|
||||
textEditingValue.text.toLowerCase(),
|
||||
),
|
||||
);
|
||||
},
|
||||
onSelected: (String selection) {
|
||||
usernameColorValue.text = selection;
|
||||
},
|
||||
fieldViewBuilder: (
|
||||
context,
|
||||
controller,
|
||||
focusNode,
|
||||
onFieldSubmitted,
|
||||
) {
|
||||
// Initialize the controller with the current value
|
||||
if (controller.text.isEmpty &&
|
||||
usernameColorValue.text.isNotEmpty) {
|
||||
controller.text = usernameColorValue.text;
|
||||
}
|
||||
|
||||
return TextFormField(
|
||||
controller: controller,
|
||||
focusNode: focusNode,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'colorValue'.tr(),
|
||||
hintText: 'e.g. red or #ff6600',
|
||||
),
|
||||
onChanged: (value) {
|
||||
usernameColorValue.text = value;
|
||||
},
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus
|
||||
?.unfocus(),
|
||||
);
|
||||
},
|
||||
),
|
||||
if (usernameColorType.value == 'gradient') ...[
|
||||
DropdownButtonFormField2<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'gradientDirection'.tr(),
|
||||
),
|
||||
items: [
|
||||
DropdownMenuItem(
|
||||
value: 'to right',
|
||||
child: Text('gradientDirectionToRight'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'to left',
|
||||
child: Text('gradientDirectionToLeft'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'to bottom',
|
||||
child: Text('gradientDirectionToBottom'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'to top',
|
||||
child: Text('gradientDirectionToTop'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'to bottom right',
|
||||
child: Text(
|
||||
'gradientDirectionToBottomRight'.tr(),
|
||||
),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'to bottom left',
|
||||
child: Text('gradientDirectionToBottomLeft'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'to top right',
|
||||
child: Text('gradientDirectionToTopRight'.tr()),
|
||||
),
|
||||
DropdownMenuItem(
|
||||
value: 'to top left',
|
||||
child: Text('gradientDirectionToTopLeft'.tr()),
|
||||
),
|
||||
],
|
||||
value:
|
||||
usernameColorDirection.text.isNotEmpty
|
||||
? usernameColorDirection.text
|
||||
: 'to right',
|
||||
onChanged: (value) {
|
||||
usernameColorDirection.text = value ?? 'to right';
|
||||
},
|
||||
customButton: Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: Text(
|
||||
usernameColorDirection.text.isNotEmpty
|
||||
? usernameColorDirection.text
|
||||
: 'to right',
|
||||
),
|
||||
),
|
||||
Icon(Symbols.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
Text(
|
||||
'gradientColors',
|
||||
).tr().bold().fontSize(14).padding(top: 8),
|
||||
Column(
|
||||
spacing: 8,
|
||||
children: [
|
||||
for (
|
||||
var i = 0;
|
||||
i < usernameColorColors.value.length;
|
||||
i++
|
||||
)
|
||||
Row(
|
||||
key: ValueKey(
|
||||
usernameColorColors.value[i].hashCode,
|
||||
),
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
child: TextFormField(
|
||||
initialValue:
|
||||
usernameColorColors.value[i],
|
||||
decoration: InputDecoration(
|
||||
labelText: 'color'.tr(),
|
||||
hintText: 'e.g. #ff0000',
|
||||
isDense: true,
|
||||
),
|
||||
onChanged: (value) {
|
||||
usernameColorColors.value[i] = value;
|
||||
},
|
||||
onTapOutside:
|
||||
(_) =>
|
||||
FocusManager.instance.primaryFocus
|
||||
?.unfocus(),
|
||||
),
|
||||
),
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.delete),
|
||||
onPressed: () {
|
||||
usernameColorColors.value =
|
||||
usernameColorColors.value
|
||||
.whereIndexed(
|
||||
(idx, _) => idx != i,
|
||||
)
|
||||
.toList();
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: FilledButton.icon(
|
||||
onPressed: () {
|
||||
usernameColorColors.value = List.from(
|
||||
usernameColorColors.value,
|
||||
)..add('');
|
||||
},
|
||||
label: Text('addColor').tr(),
|
||||
icon: const Icon(Symbols.add),
|
||||
).padding(top: 8),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
],
|
||||
),
|
||||
Text('links').tr().bold().fontSize(18).padding(top: 16),
|
||||
Column(
|
||||
spacing: 8,
|
||||
|
||||
@@ -31,7 +31,7 @@ class AuthFactorSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete('/id/accounts/me/factors/${factor.id}');
|
||||
await client.delete('/pass/accounts/me/factors/${factor.id}');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -49,7 +49,7 @@ class AuthFactorSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post('/id/accounts/me/factors/${factor.id}/disable');
|
||||
await client.post('/pass/accounts/me/factors/${factor.id}/disable');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -106,7 +106,7 @@ class AuthFactorSheet extends HookConsumerWidget {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post(
|
||||
'/id/accounts/me/factors/${factor.id}/enable',
|
||||
'/pass/accounts/me/factors/${factor.id}/enable',
|
||||
data: jsonEncode(password),
|
||||
);
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
@@ -193,7 +193,7 @@ class AuthFactorNewSheet extends HookConsumerWidget {
|
||||
showLoadingModal(context);
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
final resp = await apiClient.post(
|
||||
'/id/accounts/me/factors',
|
||||
'/pass/accounts/me/factors',
|
||||
data: {'type': factorType.value, 'secret': secretController.text},
|
||||
);
|
||||
final factor = SnAuthFactor.fromJson(resp.data);
|
||||
|
||||
@@ -77,7 +77,7 @@ class AccountConnectionSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete('/id/accounts/me/connections/${connection.id}');
|
||||
await client.delete('/pass/accounts/me/connections/${connection.id}');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -175,7 +175,7 @@ class AccountConnectionNewSheet extends HookConsumerWidget {
|
||||
if (context.mounted) showLoadingModal(context);
|
||||
|
||||
await client.post(
|
||||
'/id/auth/connect/apple/mobile',
|
||||
'/pass/auth/connect/apple/mobile',
|
||||
data: {
|
||||
'identity_token': credential.identityToken!,
|
||||
'authorization_code': credential.authorizationCode,
|
||||
@@ -200,7 +200,7 @@ class AccountConnectionNewSheet extends HookConsumerWidget {
|
||||
final serverUrl = ref.watch(serverUrlProvider);
|
||||
final accessToken = ref.watch(tokenProvider);
|
||||
launchUrlString(
|
||||
'$serverUrl/id/auth/login/${selectedProvider.value}?tk=${accessToken!.token}',
|
||||
'$serverUrl/pass/auth/login/${selectedProvider.value}?tk=${accessToken!.token}',
|
||||
);
|
||||
} else {
|
||||
await Navigator.of(context, rootNavigator: true).push(
|
||||
@@ -345,7 +345,7 @@ class AccountConnectionsSheet extends HookConsumerWidget {
|
||||
try {
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete(
|
||||
'/id/accounts/me/connections/${connection.id}',
|
||||
'/pass/accounts/me/connections/${connection.id}',
|
||||
);
|
||||
ref.invalidate(accountConnectionsProvider);
|
||||
return true;
|
||||
|
||||
@@ -25,7 +25,7 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete('/id/accounts/me/contacts/${contact.id}');
|
||||
await client.delete('/pass/accounts/me/contacts/${contact.id}');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -38,7 +38,7 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post('/id/accounts/me/contacts/${contact.id}/verify');
|
||||
await client.post('/pass/accounts/me/contacts/${contact.id}/verify');
|
||||
if (context.mounted) {
|
||||
showSnackBar('contactMethodVerificationSent'.tr());
|
||||
}
|
||||
@@ -53,7 +53,7 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post('/id/accounts/me/contacts/${contact.id}/primary');
|
||||
await client.post('/pass/accounts/me/contacts/${contact.id}/primary');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -66,7 +66,7 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post('/id/accounts/me/contacts/${contact.id}/public');
|
||||
await client.post('/pass/accounts/me/contacts/${contact.id}/public');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -79,7 +79,7 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete('/id/accounts/me/contacts/${contact.id}/public');
|
||||
await client.delete('/pass/accounts/me/contacts/${contact.id}/public');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -221,7 +221,7 @@ class ContactMethodNewSheet extends HookConsumerWidget {
|
||||
showLoadingModal(context);
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.post(
|
||||
'/id/accounts/me/contacts',
|
||||
'/pass/accounts/me/contacts',
|
||||
data: {'type': contactType.value, 'content': contentController.text},
|
||||
);
|
||||
if (context.mounted) {
|
||||
|
||||
@@ -97,9 +97,7 @@ class _AccountBasicInfo extends StatelessWidget {
|
||||
IconButton(
|
||||
onPressed: () {
|
||||
SharePlus.instance.share(
|
||||
ShareParams(
|
||||
uri: Uri.parse('https://solian.app/@${data.name}'),
|
||||
),
|
||||
ShareParams(uri: Uri.parse('https://solian.app/@${data.name}')),
|
||||
);
|
||||
},
|
||||
icon: const Icon(Symbols.share),
|
||||
@@ -563,14 +561,14 @@ Future<SnAccount> account(Ref ref, String uname) async {
|
||||
}
|
||||
}
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
final resp = await apiClient.get("/id/accounts/$uname");
|
||||
final resp = await apiClient.get("/pass/accounts/$uname");
|
||||
return SnAccount.fromJson(resp.data);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Future<List<SnAccountBadge>> accountBadges(Ref ref, String uname) async {
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
final resp = await apiClient.get("/id/accounts/$uname/badges");
|
||||
final resp = await apiClient.get("/pass/accounts/$uname/badges");
|
||||
return List<SnAccountBadge>.from(
|
||||
resp.data.map((x) => SnAccountBadge.fromJson(x)),
|
||||
);
|
||||
@@ -619,7 +617,7 @@ Future<SnRelationship?> accountRelationship(Ref ref, String uname) async {
|
||||
final account = await ref.watch(accountProvider(uname).future);
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
try {
|
||||
final resp = await apiClient.get("/id/relationships/${account.id}");
|
||||
final resp = await apiClient.get("/pass/relationships/${account.id}");
|
||||
return SnRelationship.fromJson(resp.data);
|
||||
} catch (err) {
|
||||
if (err is DioException && err.response?.statusCode == 404) {
|
||||
@@ -692,7 +690,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
showLoadingModal(context);
|
||||
try {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.post('/id/relationships/${account.value!.id}/friends');
|
||||
await client.post('/pass/relationships/${account.value!.id}/friends');
|
||||
ref.invalidate(accountRelationshipProvider(name));
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
@@ -706,9 +704,9 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
try {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
if (accountRelationship.value == null) {
|
||||
await client.post('/id/relationships/${account.value!.id}/block');
|
||||
await client.post('/pass/relationships/${account.value!.id}/block');
|
||||
} else {
|
||||
await client.delete('/id/relationships/${account.value!.id}/block');
|
||||
await client.delete('/pass/relationships/${account.value!.id}/block');
|
||||
}
|
||||
ref.invalidate(accountRelationshipProvider(name));
|
||||
} catch (err) {
|
||||
@@ -879,7 +877,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
child: Card(
|
||||
child: FortuneGraphWidget(
|
||||
events: accountEvents,
|
||||
eventCalanderUser: data.name,
|
||||
eventCalandarUser: data.name,
|
||||
margin: EdgeInsets.zero,
|
||||
),
|
||||
),
|
||||
@@ -1004,7 +1002,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
child: Card(
|
||||
child: FortuneGraphWidget(
|
||||
events: accountEvents,
|
||||
eventCalanderUser: data.name,
|
||||
eventCalandarUser: data.name,
|
||||
),
|
||||
).padding(horizontal: 4),
|
||||
),
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'profile.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$accountHash() => r'ce7264a04f69e32a5cb07bc10ca5fa47ae1fddaa';
|
||||
String _$accountHash() => r'5e2b7bd59151b4638a5561f495537c259f767123';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
@@ -145,7 +145,7 @@ class _AccountProviderElement
|
||||
String get uname => (origin as AccountProvider).uname;
|
||||
}
|
||||
|
||||
String _$accountBadgesHash() => r'1de05e122c23ff2c6ac6d318977165761e2ad177';
|
||||
String _$accountBadgesHash() => r'68db63f49827020beecbdbf20529520d0cd14a7d';
|
||||
|
||||
/// See also [accountBadges].
|
||||
@ProviderFor(accountBadges)
|
||||
@@ -517,7 +517,7 @@ class _AccountDirectChatProviderElement
|
||||
}
|
||||
|
||||
String _$accountRelationshipHash() =>
|
||||
r'9a3a4e8c6c6706f73df95feccb86736fcad33f30';
|
||||
r'319f743261b113a1d3c6a397d48d13c858312669';
|
||||
|
||||
/// See also [accountRelationship].
|
||||
@ProviderFor(accountRelationship)
|
||||
|
||||
@@ -21,7 +21,7 @@ part 'relationship.g.dart';
|
||||
@riverpod
|
||||
Future<List<SnRelationship>> sentFriendRequest(Ref ref) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final resp = await client.get('/id/relationships/requests');
|
||||
final resp = await client.get('/pass/relationships/requests');
|
||||
return resp.data
|
||||
.map((e) => SnRelationship.fromJson(e))
|
||||
.cast<SnRelationship>()
|
||||
@@ -43,7 +43,7 @@ class RelationshipListNotifier extends _$RelationshipListNotifier
|
||||
final take = 20;
|
||||
|
||||
final response = await client.get(
|
||||
'/id/relationships',
|
||||
'/pass/relationships',
|
||||
queryParameters: {'offset': offset, 'take': take},
|
||||
);
|
||||
|
||||
@@ -226,7 +226,7 @@ class RelationshipScreen extends HookConsumerWidget {
|
||||
if (result == null) return;
|
||||
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post('/id/relationships/${result.id}/friends');
|
||||
await client.post('/pass/relationships/${result.id}/friends');
|
||||
ref.invalidate(sentFriendRequestProvider);
|
||||
}
|
||||
|
||||
@@ -240,7 +240,7 @@ class RelationshipScreen extends HookConsumerWidget {
|
||||
submitting.value = true;
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post(
|
||||
'/id/relationships/${relationship.accountId}/friends/${isAccept ? 'accept' : 'decline'}',
|
||||
'/pass/relationships/${relationship.accountId}/friends/${isAccept ? 'accept' : 'decline'}',
|
||||
);
|
||||
relationshipNotifier.forceRefresh();
|
||||
if (!context.mounted) return;
|
||||
@@ -267,7 +267,7 @@ class RelationshipScreen extends HookConsumerWidget {
|
||||
) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.patch(
|
||||
'/id/relationships/${relationship.accountId}',
|
||||
'/pass/relationships/${relationship.accountId}',
|
||||
data: {'status': newStatus},
|
||||
);
|
||||
relationshipNotifier.forceRefresh();
|
||||
@@ -350,7 +350,7 @@ class _SentFriendRequestsSheet extends HookConsumerWidget {
|
||||
Future<void> cancelRequest(SnRelationship request) async {
|
||||
try {
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete('/id/relationships/${request.relatedId}/friends');
|
||||
await client.delete('/pass/relationships/${request.relatedId}/friends');
|
||||
ref.invalidate(sentFriendRequestProvider);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'relationship.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$sentFriendRequestHash() => r'dc02ace6cb755a01ab862c9fcff3b26de7f946cb';
|
||||
String _$sentFriendRequestHash() => r'0c52813eb6f86c05f6e0b1e4e840d0d9c350aa9e';
|
||||
|
||||
/// See also [sentFriendRequest].
|
||||
@ProviderFor(sentFriendRequest)
|
||||
@@ -27,7 +27,7 @@ final sentFriendRequestProvider =
|
||||
typedef SentFriendRequestRef =
|
||||
AutoDisposeFutureProviderRef<List<SnRelationship>>;
|
||||
String _$relationshipListNotifierHash() =>
|
||||
r'0a134ce69489a4f2002d2223853855b6f22e4e9f';
|
||||
r'fc46920256f7c48445c00652165e879890f2c9a3';
|
||||
|
||||
/// See also [RelationshipListNotifier].
|
||||
@ProviderFor(RelationshipListNotifier)
|
||||
|
||||
@@ -49,7 +49,7 @@ class CreateAccountScreen extends HookConsumerWidget {
|
||||
showLoadingModal(context);
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.post(
|
||||
'/id/accounts',
|
||||
'/pass/accounts',
|
||||
data: {
|
||||
'name': usernameController.text,
|
||||
'nick': nicknameController.text,
|
||||
|
||||
@@ -175,7 +175,7 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
||||
// Get token if challenge is completed
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final tokenResp = await client.post(
|
||||
'/id/auth/token',
|
||||
'/pass/auth/token',
|
||||
data: {
|
||||
'grant_type': 'authorization_code',
|
||||
'code': code ?? challenge!.id,
|
||||
@@ -241,7 +241,7 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
||||
// Pass challenge
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.patch(
|
||||
'/id/auth/challenge/${challenge!.id}',
|
||||
'/pass/auth/challenge/${challenge!.id}',
|
||||
data: {'factor_id': factor!.id, 'password': pwd},
|
||||
);
|
||||
final result = SnAuthChallenge.fromJson(resp.data);
|
||||
@@ -388,7 +388,7 @@ class _LoginPickerScreen extends HookConsumerWidget {
|
||||
|
||||
try {
|
||||
await client.post(
|
||||
'/id/auth/challenge/${challenge!.id}/factors/${factorPicked.value!.id}',
|
||||
'/pass/auth/challenge/${challenge!.id}/factors/${factorPicked.value!.id}',
|
||||
data:
|
||||
hintController.text.isNotEmpty
|
||||
? jsonEncode(hintController.text)
|
||||
@@ -531,7 +531,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
try {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.post(
|
||||
'/id/accounts/recovery/password',
|
||||
'/pass/accounts/recovery/password',
|
||||
data: {'account': uname, 'captcha_token': captchaTk},
|
||||
);
|
||||
showInfoAlert('loginResetPasswordSent'.tr(), 'done'.tr());
|
||||
@@ -549,7 +549,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
try {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.post(
|
||||
'/id/auth/challenge',
|
||||
'/pass/auth/challenge',
|
||||
data: {
|
||||
'account': uname,
|
||||
'device_id': await getUdid(),
|
||||
@@ -570,7 +570,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
final result = SnAuthChallenge.fromJson(resp.data);
|
||||
onChallenge(result);
|
||||
final factorResp = await client.get(
|
||||
'/id/auth/challenge/${result.id}/factors',
|
||||
'/pass/auth/challenge/${result.id}/factors',
|
||||
);
|
||||
onFactor(
|
||||
List<SnAuthFactor>.from(
|
||||
@@ -599,7 +599,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
|
||||
if (context.mounted) showLoadingModal(context);
|
||||
final resp = await client.post(
|
||||
'/id/auth/login/apple/mobile',
|
||||
'/pass/auth/login/apple/mobile',
|
||||
data: {
|
||||
'identity_token': credential.identityToken!,
|
||||
'authorization_code': credential.authorizationCode,
|
||||
@@ -611,7 +611,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
final challenge = SnAuthChallenge.fromJson(resp.data);
|
||||
onChallenge(challenge);
|
||||
final factorResp = await client.get(
|
||||
'/id/auth/challenge/${challenge.id}/factors',
|
||||
'/pass/auth/challenge/${challenge.id}/factors',
|
||||
);
|
||||
onFactor(
|
||||
List<SnAuthFactor>.from(
|
||||
@@ -636,11 +636,11 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
|
||||
final client = ref.watch(apiClientProvider);
|
||||
try {
|
||||
final resp = await client.get('/id/auth/challenge/$challengeId');
|
||||
final resp = await client.get('/pass/auth/challenge/$challengeId');
|
||||
final challenge = SnAuthChallenge.fromJson(resp.data);
|
||||
onChallenge(challenge);
|
||||
final factorResp = await client.get(
|
||||
'/id/auth/challenge/${challenge.id}/factors',
|
||||
'/pass/auth/challenge/${challenge.id}/factors',
|
||||
);
|
||||
onFactor(
|
||||
List<SnAuthFactor>.from(
|
||||
|
||||
@@ -80,7 +80,9 @@ class _OidcScreenState extends ConsumerState<OidcScreen> {
|
||||
: 'Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Safari/537.36',
|
||||
),
|
||||
initialUrlRequest: URLRequest(
|
||||
url: WebUri('$serverUrl/id/auth/login/${widget.provider}'),
|
||||
url: WebUri(
|
||||
'$serverUrl/pass/auth/login/${widget.provider}',
|
||||
),
|
||||
headers: {
|
||||
if (token?.token.isNotEmpty ?? false)
|
||||
'Authorization': 'AtField ${token!.token}',
|
||||
|
||||
@@ -10,12 +10,13 @@ import 'package:island/pods/chat/call.dart';
|
||||
import 'package:island/pods/chat/chat_summary.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/screens/realm/realms.dart';
|
||||
import 'package:island/services/event_bus.dart';
|
||||
import 'package:island/services/responsive.dart';
|
||||
import 'package:island/widgets/account/account_picker.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
import 'package:island/widgets/navigation/fab_menu.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:relative_time/relative_time.dart';
|
||||
@@ -238,10 +239,17 @@ class ChatListBodyWidget extends HookConsumerWidget {
|
||||
room: item,
|
||||
isDirect: item.type == 1,
|
||||
onTap: () {
|
||||
if (isWideScreen(context)) {
|
||||
context.replaceNamed(
|
||||
'chatRoom',
|
||||
pathParameters: {'id': item.id},
|
||||
);
|
||||
} else {
|
||||
context.pushNamed(
|
||||
'chatRoom',
|
||||
pathParameters: {'id': item.id},
|
||||
);
|
||||
}
|
||||
},
|
||||
);
|
||||
},
|
||||
@@ -326,28 +334,30 @@ class ChatListScreen extends HookConsumerWidget {
|
||||
tabController.addListener(() {
|
||||
selectedTab.value = tabController.index;
|
||||
});
|
||||
return null;
|
||||
|
||||
// Listen for chat rooms refresh events
|
||||
final subscription = eventBus.on<ChatRoomsRefreshEvent>().listen((event) {
|
||||
ref.invalidate(chatroomsJoinedProvider);
|
||||
});
|
||||
|
||||
return () {
|
||||
subscription.cancel();
|
||||
};
|
||||
}, [tabController]);
|
||||
|
||||
Future<void> createDirectMessage() async {
|
||||
final result = await showModalBottomSheet(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
builder: (context) => const AccountPickerSheet(),
|
||||
);
|
||||
if (result == null) return;
|
||||
final client = ref.read(apiClientProvider);
|
||||
try {
|
||||
await client.post(
|
||||
'/sphere/chat/direct',
|
||||
data: {'related_user_id': result.id},
|
||||
);
|
||||
ref.invalidate(chatroomsJoinedProvider);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
}
|
||||
}
|
||||
useEffect(() {
|
||||
// Set FAB type to chat
|
||||
final fabMenuNotifier = ref.read(fabMenuTypeProvider.notifier);
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
fabMenuNotifier.state = FabMenuType.chat;
|
||||
});
|
||||
return () {
|
||||
// Clean up: reset FAB type to main
|
||||
WidgetsBinding.instance.addPostFrameCallback((_) {
|
||||
fabMenuNotifier.state = FabMenuType.main;
|
||||
});
|
||||
};
|
||||
}, []);
|
||||
|
||||
if (isAside) {
|
||||
return Card(
|
||||
@@ -484,43 +494,6 @@ class ChatListScreen extends HookConsumerWidget {
|
||||
const Gap(8),
|
||||
],
|
||||
),
|
||||
floatingActionButton: FloatingActionButton(
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
builder:
|
||||
(context) => Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
ListTile(
|
||||
title: const Text('createChatRoom').tr(),
|
||||
leading: const Icon(Symbols.add),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
context.pushNamed('chatNew').then((value) {
|
||||
if (value != null) {
|
||||
ref.invalidate(chatroomsJoinedProvider);
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('createDirectMessage').tr(),
|
||||
leading: const Icon(Symbols.person),
|
||||
onTap: () {
|
||||
Navigator.pop(context);
|
||||
createDirectMessage();
|
||||
},
|
||||
),
|
||||
Gap(MediaQuery.of(context).padding.bottom + 16),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
child: const Icon(Symbols.add),
|
||||
),
|
||||
body: ChatListBodyWidget(
|
||||
isFloating: false,
|
||||
tabController: tabController,
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user