Compare commits
167 Commits
3.2.0+126
...
a243cda1df
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a243cda1df | ||
|
|
7b238f32fd | ||
|
313af28d7f
|
|||
|
c64e1e208c
|
|||
|
c9b07a9a2a
|
|||
| 55c0e355f1 | |||
| be414891ec | |||
| 787876ab6a | |||
|
8578cde620
|
|||
|
14d55d45a8
|
|||
|
724391584e
|
|||
| 3a5e45808a | |||
|
488055955c
|
|||
|
|
313ebc64cc | ||
|
|
1ed8b1d0c1 | ||
| 4af816d931 | |||
| 1c058a4323 | |||
| 461ed1fcda | |||
|
5363afa558
|
|||
|
f0d2737da8
|
|||
|
1f2f80aa3e
|
|||
|
240a872e65
|
|||
| c1ec6f0849 | |||
| ab42686d4d | |||
|
c9727e92b8
|
|||
|
9b8768061d
|
|||
|
0949f0da54
|
|||
|
215ca705ac
|
|||
|
03457af04a
|
|||
|
73c6a1febf
|
|||
|
ba8d30bcde
|
|||
|
8449658b47
|
|||
|
c7f417234e
|
|||
|
6c847ee1e1
|
|||
|
18ad4d376e
|
|||
|
c4d5ba5c9d
|
|||
|
1069669049
|
|||
|
aa648fec62
|
|||
|
541900673a
|
|||
|
265502ffd0
|
|||
|
3bd79350d1
|
|||
|
5294d1fb23
|
|||
|
ec1269dcf1
|
|||
|
edb0a25f34
|
|||
|
7cd10118cc
|
|||
|
fcddc8f345
|
|||
|
1cc34240da
|
|||
|
013f7f02bc
|
|||
|
4e79e4100f
|
|||
|
feda1f067f
|
|||
|
fe0e192a43
|
|||
|
93df294142
|
|||
|
78d65c39f3
|
|||
|
18b0dbd797
|
|||
|
80cc8cbb40
|
|||
|
646e95a9fc
|
|||
|
6f9d51673b
|
|||
|
f8c6887769
|
|||
|
cd2a507b7f
|
|||
|
3cafce00a2
|
|||
|
837f3fbe98
|
|||
|
ca7cc5d7ee
|
|||
|
ef2c14daa2
|
|||
|
3a17837cc6
|
|||
|
2617a64acf
|
|||
|
afe1e12a3b
|
|||
|
be80f5ff85
|
|||
|
3281d69eba
|
|||
|
77b6ce9937
|
|||
|
39275f61b5
|
|||
|
72193ba8f3
|
|||
|
98dd9b6617
|
|||
|
a22b94a263
|
|||
|
9c75eafdb3
|
|||
|
28fda3d0c7
|
|||
|
187c2ea43e
|
|||
|
ae7d967461
|
|||
|
1ce71f1fa1
|
|||
|
9b68808c77
|
|||
|
|
99b7bf8199 | ||
|
|
eb9bb73c31 | ||
|
|
a8c3830d67 | ||
|
|
07a5a19141 | ||
| ecc100ac45 | |||
| 573b76d3ff | |||
| f7dad5e419 | |||
| 9f2f1c0848 | |||
| 580d9fd979 | |||
| 3b375abc09 | |||
| c527b5e67c | |||
| e9f09bbe54 | |||
| 3aece9316c | |||
| a61c889c6c | |||
| 0dd3221a56 | |||
| 66918521f8 | |||
| bb1846e462 | |||
| a976a6eaf4 | |||
| 4252f66fd3 | |||
| f2d780b48f | |||
| 300541f9bb | |||
| 43787bb813 | |||
| 3417c51a3b | |||
| f98e603e82 | |||
| c9b71701c8 | |||
| 28e98488f1 | |||
| b4d476613e | |||
| b48a1aac44 | |||
| 596d212593 | |||
| 54f290327e | |||
| 16f248ceab | |||
| 856d811187 | |||
| d07b194c04 | |||
| 2554b58be6 | |||
| a627b5838e | |||
| c479a9f381 | |||
| 02057e663b | |||
| 6501594100 | |||
| c6599edc3d | |||
| 709a0620b6 | |||
| f9b2a96c7c | |||
| 4dca6189cb | |||
| c7f5b63fe5 | |||
| 96c2f45c85 | |||
| 06f04eb3a5 | |||
| 8af97e43b4 | |||
| d1e8234b93 | |||
| a03d6015a6 | |||
| 246ac52d0a | |||
| abf395ff9a | |||
| 4fdc8eb1d0 | |||
| d7dcde898c | |||
| f85484d3ed | |||
| 5060bd30c9 | |||
| 3959f2260b | |||
| 6f4f1216ad | |||
| f401ffbf81 | |||
| 0251697951 | |||
| 178c12b893 | |||
| 4beda9200e | |||
| 7dfe411053 | |||
| 1232318a5d | |||
|
|
56f41b6c0e | ||
|
|
3ea717d25a | ||
| 1fe4889460 | |||
| cdf2722268 | |||
| a127b5bace | |||
| b2097cf044 | |||
| 701f29748d | |||
| 9e40ed4600 | |||
| c90e6fe661 | |||
| 569483300d | |||
| bab602d98b | |||
| b4f2bb803a | |||
| 03bfed6f46 | |||
| f98e5a0aec | |||
| 3d473e2fec | |||
| 0b6efa373a | |||
| 9b60e96cde | |||
| 81cd9b2082 | |||
| 923d5d7514 | |||
| 7169aff841 | |||
| fac3efb50c | |||
| e809aadaea | |||
| f33b569221 | |||
| e5f2e2d146 | |||
| 11368d064f | |||
| 246b163aec |
@@ -62,4 +62,3 @@ If you want to build the release version, use the flutter build command. Learn m
|
||||
```bash
|
||||
flutter build <platform>
|
||||
```
|
||||
|
||||
|
||||
@@ -24,6 +24,8 @@ android {
|
||||
ndkVersion = "29.0.13113456"
|
||||
|
||||
compileOptions {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
@@ -63,6 +65,8 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
||||
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
implementation("com.squareup.okhttp3:okhttp:5.1.0")
|
||||
|
||||
Binary file not shown.
|
Before Width: | Height: | Size: 70 KiB |
41
android/app/src/main/res/drawable/ic_notification.xml
Normal file
41
android/app/src/main/res/drawable/ic_notification.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="192dp"
|
||||
android:height="192dp"
|
||||
android:viewportWidth="192"
|
||||
android:viewportHeight="192">
|
||||
<path
|
||||
android:pathData="M54,147h86"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="12"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M57,111s-2,-4.5 -2,-10m22,22s-4,7 -11,4m9,-22s-2,-4.5 -2,-10"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="10"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M54,147a32,32 0,0 1,-12 -61.67A39,39 0,0 1,81 46m59,101a30,30 0,0 0,29.93 -28"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="12"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M132,75m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="8"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M112.5,41.22C100.84,47.96 93,60.56 93,75c0,6.38 1.53,12.39 4.24,17.71m69.51,-35.42A38.84,38.84 0,0 1,171 75c0,14.43 -7.84,27.03 -19.49,33.78m-0.79,-43.32A20.9,20.9 0,0 1,153 75c0,7.77 -4.22,14.56 -10.49,18.19m-21,-36.38C115.22,60.44 111,67.23 111,75a20.9,20.9 0,0 0,2.28 9.53"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="10"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
@@ -133,6 +133,25 @@
|
||||
"other": "{} replies"
|
||||
},
|
||||
"forward": "Forward",
|
||||
"award": "Award",
|
||||
"awardPost": "Award Post",
|
||||
"awardMessage": "Message",
|
||||
"awardMessageHint": "Enter your award message...",
|
||||
"awardAttitude": "Attitude",
|
||||
"awardAttitudePositive": "Positive",
|
||||
"awardAttitudeNegative": "Negative",
|
||||
"awardAmount": "Amount",
|
||||
"awardAmountHint": "Enter amount...",
|
||||
"awardAmountRequired": "Amount is required",
|
||||
"awardAmountInvalid": "Please enter a valid amount",
|
||||
"awardMessageTooLong": "Message is too long (max 4096 characters)",
|
||||
"awardSuccess": "Award sent successfully!",
|
||||
"awardSubmit": "Award",
|
||||
"awardPostPreview": "Post Preview",
|
||||
"awardNoContent": "No content available",
|
||||
"awardByPublisher": "By {}",
|
||||
"awardBenefits": "Award Benefits",
|
||||
"awardBenefitsDescription": "Awarding this post increases its value and visibility. Higher valued posts have a better chance of being featured and highlighted in the community.",
|
||||
"repliedTo": "Replied to",
|
||||
"forwarded": "Forwarded",
|
||||
"hasAttachments": {
|
||||
@@ -195,6 +214,7 @@
|
||||
"checkInResultLevel2": "A Normal Day",
|
||||
"checkInResultLevel3": "Good Luck",
|
||||
"checkInResultLevel4": "Best Luck",
|
||||
"checkInResultLevel5": "Happy Birthday 🥳",
|
||||
"checkInActivityTitle": "{} checked in on {} and got a {}",
|
||||
"eventCalander": "Event Calander",
|
||||
"eventCalanderEmpty": "No events on that day.",
|
||||
@@ -228,6 +248,8 @@
|
||||
"settings": "Settings",
|
||||
"language": "Language",
|
||||
"accountLanguageHint": "This language will be used for email and push notifications.",
|
||||
"region": "Region",
|
||||
"accountRegionHint": "This region will be used for content delivery and localization.",
|
||||
"settingsDisplayLanguage": "Display Language",
|
||||
"languageFollowSystem": "Follow System",
|
||||
"postsCreatedCount": "Posts",
|
||||
@@ -338,6 +360,7 @@
|
||||
"notifications": "Notifications",
|
||||
"posts": "Posts",
|
||||
"settingsBackgroundImage": "Background Image",
|
||||
"settingsBackgroundImageEnable": "Show Background Image",
|
||||
"settingsBackgroundImageClear": "Clear Background Image",
|
||||
"settingsBackgroundGenerateColor": "Generate color scheme from Bacground Image",
|
||||
"messageNone": "No content to display",
|
||||
@@ -348,6 +371,8 @@
|
||||
"chatBreakNone": "None",
|
||||
"settingsRealmCompactView": "Compact Realm View",
|
||||
"settingsMixedFeed": "Mixed Feed",
|
||||
"settingsDataSavingMode": "Data Saving Mode",
|
||||
"dataSavingHint": "Data Saving Mode",
|
||||
"settingsAutoTranslate": "Auto Translate",
|
||||
"settingsHideBottomNav": "Hide Bottom Navigation",
|
||||
"settingsSoundEffects": "Sound Effects",
|
||||
@@ -386,6 +411,7 @@
|
||||
"postSettings": "Settings",
|
||||
"postPublisherUnselected": "Publisher Unspecified",
|
||||
"postType": "Post Type",
|
||||
"postTypePost": "Post",
|
||||
"articleAttachmentHint": "Attachments must be uploaded and inserted into the article body to be visible.",
|
||||
"postVisibility": "Post Visibility",
|
||||
"postVisibilityPublic": "Public",
|
||||
@@ -445,6 +471,8 @@
|
||||
"close": "Close",
|
||||
"drafts": "Drafts",
|
||||
"noDrafts": "No drafts yet",
|
||||
"searchDrafts": "Search drafts...",
|
||||
"noSearchResults": "No search results",
|
||||
"articleDrafts": "Article drafts",
|
||||
"postDrafts": "Post drafts",
|
||||
"saveDraft": "Save draft",
|
||||
@@ -491,6 +519,10 @@
|
||||
"contactMethodSetPrimary": "Set as Primary",
|
||||
"contactMethodSetPrimaryHint": "Set this contact method as your primary contact method for account recovery and notifications",
|
||||
"contactMethodDeleteHint": "Are you sure to delete this contact method? This action cannot be undone.",
|
||||
"contactMethodMakePublic": "Make Public",
|
||||
"contactMethodMakePrivate": "Make Private",
|
||||
"contactMethodPublic": "Public",
|
||||
"contactMethodPrivate": "Private",
|
||||
"chatNotifyLevel": "Notify Level",
|
||||
"chatNotifyLevelDescription": "Decide how many notifications you will receive.",
|
||||
"chatNotifyLevelAll": "All",
|
||||
@@ -633,8 +665,9 @@
|
||||
"chatJoin": "Join the Chat",
|
||||
"realmJoin": "Join the Realm",
|
||||
"realmJoinSuccess": "Successfully joined the realm.",
|
||||
"discoverRealms": "Discover realms",
|
||||
"discoverPublishers": "Discover publishers",
|
||||
"discoverRealms": "Realms",
|
||||
"discoverPublishers": "Publishers",
|
||||
"discoverShuffledPost": "Random Posts",
|
||||
"search": "Search",
|
||||
"publisherMembers": "Collaborators",
|
||||
"developerHub": "Developer Hub",
|
||||
@@ -643,6 +676,18 @@
|
||||
"enrollDeveloperHint": "Enroll one of your publishers to become a developer.",
|
||||
"noPublishersToEnroll": "You don't have any publishers that can be enrolled as a developer.",
|
||||
"totalCustomApps": "Total Custom Apps",
|
||||
"projects": "Projects",
|
||||
"noProjects": "No projects found.",
|
||||
"deleteProject": "Delete Project",
|
||||
"deleteProjectHint": "Are you sure you want to delete this project? This action cannot be undone.",
|
||||
"createProject": "Create Project",
|
||||
"editProject": "Edit Project",
|
||||
"projectDetails": "Project Details",
|
||||
"createBot": "Create Bot",
|
||||
"bots": "Bots",
|
||||
"noBots": "No bots yet.",
|
||||
"deleteBotHint": "Are you sure you want to delete this bot? This action cannot be undone.",
|
||||
"deleteBot": "Delete Bot",
|
||||
"customApps": "Custom Apps",
|
||||
"noCustomApps": "No custom apps yet.",
|
||||
"createCustomApp": "Create Custom App",
|
||||
@@ -680,7 +725,7 @@
|
||||
"publisherFeatureDevelopDescription": "Unlock development abilities for your publisher, including custom apps, API keys, and more.",
|
||||
"publisherFeatureDevelopHint": "Currently, this feature is under active development, you need send a request to unlock this feature.",
|
||||
"learnMore": "Learn More",
|
||||
"discoverWebArticles": "Articles from external sites",
|
||||
"discoverWebArticles": "Web Feed Articles",
|
||||
"webArticlesStand": "Article Stand",
|
||||
"about": "About",
|
||||
"membershipCancel": "Cancel Membership",
|
||||
@@ -850,5 +895,126 @@
|
||||
"zero": "No invitation",
|
||||
"one": "{} available invitation",
|
||||
"other": "{} available invitations"
|
||||
}
|
||||
},
|
||||
"failedToLoadUserInfo": "Failed to load user info",
|
||||
"failedToLoadUserInfoNetwork": "It seems be network issue, you can tap the button below to try again.",
|
||||
"failedToLoadUserInfoUnauthorized": "It seems your session has been logged out or not available anymore, you can still try agian to fetch the user info if you want.",
|
||||
"okay": "Okay",
|
||||
"postDetail": "Post Detail",
|
||||
"postCount": {
|
||||
"zero": "No posts",
|
||||
"one": "{} post",
|
||||
"other": "{} posts"
|
||||
},
|
||||
"mimeType": "MIME Type",
|
||||
"fileSize": "File Size",
|
||||
"fileHash": "File Hash",
|
||||
"exifData": "EXIF Data",
|
||||
"postShuffle": "Shuffle Posts",
|
||||
"leveling": "Leveling",
|
||||
"levelingHistory": "Leveling History",
|
||||
"stellarProgram": "Stellar Program",
|
||||
"socialCredits": "Social Credits",
|
||||
"credits": "Credits",
|
||||
"creditsStatus": "Credits Status",
|
||||
"socialCreditsDescription": "Social Credit is a way for Solar Network to evaluate users. It is calculated based on their behavior and interactions. With a base score of 100, higher scores indicate a user's credibility within the community. Scores change over time to reflect a user's recent behavior. Users with higher credit ratings enjoy more benefits, while users with lower credit ratings may have some functionality restricted.",
|
||||
"socialCreditsLevelPoor": "Poor",
|
||||
"socialCreditsLevelNormal": "Normal",
|
||||
"socialCreditsLevelGood": "Good",
|
||||
"socialCreditsLevelExcellent": "Excellent",
|
||||
"orderByPopularity": "Sort by popularity",
|
||||
"orderByReleaseDate": "Sort by release date",
|
||||
"editBot": "Edit Bot",
|
||||
"botAutomatedBy": "Automated by {}",
|
||||
"botDetails": "Bot Details",
|
||||
"overview": "Overview",
|
||||
"keys": "Keys",
|
||||
"botNotFound": "Bot not found.",
|
||||
"newBotKey": "New Bot Key",
|
||||
"newBotKeyHint": "Enter a name for your new key. The key will be shown only once.",
|
||||
"revokeBotKey": "Revoke Bot Key",
|
||||
"revokeBotKeyHint": "Are you sure you want to revoke this key? This action cannot be undone and any application using this key will stop working.",
|
||||
"noBotKeys": "No bot keys yet.",
|
||||
"revoke": "Revoke",
|
||||
"keyName": "Key Name",
|
||||
"newKeyGenerated": "New Key Generated",
|
||||
"copyKeyHint": "Please copy this key and store it somewhere safe. You will not be able to see it again.",
|
||||
"rotateKey": "Rotate Key",
|
||||
"rotateBotKey": "Rotate Bot Key",
|
||||
"rotateBotKeyHint": "Are you sure you want to rotate this key? The old key will become invalid immediately. This action cannot be undone.",
|
||||
"webFeedArticleCount": {
|
||||
"zero": "No articles",
|
||||
"one": "{} article",
|
||||
"other": "{} articles"
|
||||
},
|
||||
"webFeedSubscribed": "The feed has been subscribed",
|
||||
"webFeedUnsubscribed": "The feed has been unsubscribed",
|
||||
"appDetails": "App Details",
|
||||
"secrets": "Secrets",
|
||||
"appNotFound": "App not found.",
|
||||
"secretCopied": "Secret copied to clipboard.",
|
||||
"deleteSecret": "Delete Secret",
|
||||
"deleteSecretHint": "Are you sure you want to delete this secret? This action cannot be undone.",
|
||||
"generateSecret": "Generate New Secret",
|
||||
"createdAt": "Created at {}",
|
||||
"newSecretGenerated": "New Secret Generated",
|
||||
"copySecretHint": "Please copy this secret and store it somewhere safe. You will not be able to see it again.",
|
||||
"expiresIn": "Expires In (seconds)",
|
||||
"isOidc": "OIDC Compliant",
|
||||
"pinPost": "Pin Post",
|
||||
"unpinPost": "Unpin Post",
|
||||
"pinnedPost": "Pinned",
|
||||
"publisherPage": "Publisher Page",
|
||||
"realmPage": "Realm Page",
|
||||
"replyPage": "Reply Page",
|
||||
"pinPostPublisherHint": "Pin this post to your publisher page",
|
||||
"pinPostRealmHint": "Pin this post to the realm page",
|
||||
"pinPostRealmDisabledHint": "This post doesn't belong to any realm",
|
||||
"pinPostReplyHint": "Pin this post to the reply page",
|
||||
"pinPostReplyDisabledHint": "This post is not a reply",
|
||||
"pin": "Pin",
|
||||
"unpinPostHint": "Are you sure you want to unpin this post?",
|
||||
"all": "All",
|
||||
"statusPresent": "Present",
|
||||
"accountAutomated": "Automated",
|
||||
"chatBreakClearButton": "Clear",
|
||||
"chatBreak5m": "5m",
|
||||
"chatBreak10m": "10m",
|
||||
"chatBreak15m": "15m",
|
||||
"chatBreak30m": "30m",
|
||||
"chatBreakCustomMinutes": "Custom (minutes)",
|
||||
"errorGeneric": "Error: {}",
|
||||
"searchMessages": "Search Messages",
|
||||
"messagesCount": "{} messages",
|
||||
"dotSeparator": "·",
|
||||
"roleValidationHint": "Role must be between 0 and 100",
|
||||
"searchMessagesHint": "Search messages...",
|
||||
"searchLinks": "Links",
|
||||
"searchAttachments": "Attachments",
|
||||
"noMessagesFound": "No messages found",
|
||||
"openInBrowser": "Open in Browser",
|
||||
"highlightPost": "Highlight Post",
|
||||
"filters": "Filters",
|
||||
"apply": "Apply",
|
||||
"pubName": "Pub Name",
|
||||
"realm": "Realm",
|
||||
"shuffle": "Shuffle",
|
||||
"pinned": "Pinned",
|
||||
"noResultsFound": "No results found",
|
||||
"toggleFilters": "Toggle filters",
|
||||
"notableDayNext": "{} is in",
|
||||
"expandPoll": "Expand Poll",
|
||||
"collapsePoll": "Collapse Poll",
|
||||
"embedView": "Embed View",
|
||||
"embedUri": "Embed URI",
|
||||
"aspectRatio": "Aspect Ratio",
|
||||
"renderer": "Renderer",
|
||||
"addEmbed": "Add Embed",
|
||||
"editEmbed": "Edit Embed",
|
||||
"deleteEmbed": "Delete Embed",
|
||||
"deleteEmbedConfirm": "Are you sure you want to delete this embed?",
|
||||
"currentEmbed": "Current Embed",
|
||||
"noEmbed": "No embed yet",
|
||||
"save": "Save",
|
||||
"webView": "Web View"
|
||||
}
|
||||
|
||||
@@ -158,11 +158,12 @@
|
||||
"checkIn": "签到",
|
||||
"checkInNone": "尚未签到",
|
||||
"checkInNoneHint": "通过签到获取您的财富提示和每日奖励。",
|
||||
"checkInResultLevel0": "最差运气",
|
||||
"checkInResultLevel1": "坏运气",
|
||||
"checkInResultLevel2": "一个普通的日常",
|
||||
"checkInResultLevel3": "好运",
|
||||
"checkInResultLevel4": "最佳运气",
|
||||
"checkInResultLevel0": "大凶",
|
||||
"checkInResultLevel1": "凶",
|
||||
"checkInResultLevel2": "中平",
|
||||
"checkInResultLevel3": "吉",
|
||||
"checkInResultLevel4": "大吉",
|
||||
"checkInResultLevel5": "生日快乐 🥳",
|
||||
"checkInActivityTitle": "{} 在 {} 签到并获得了 {}",
|
||||
"eventCalander": "活动日历",
|
||||
"eventCalanderEmpty": "该日无活动。",
|
||||
@@ -304,6 +305,7 @@
|
||||
"notifications": "通知",
|
||||
"posts": "帖子",
|
||||
"settingsBackgroundImage": "背景图片",
|
||||
"settingsBackgroundImageEnable": "显示背景图片",
|
||||
"settingsBackgroundImageClear": "清除背景图片",
|
||||
"settingsBackgroundGenerateColor": "从背景图像生成主题色",
|
||||
"messageNone": "没有内容可显示",
|
||||
@@ -314,6 +316,8 @@
|
||||
"chatBreakNone": "无",
|
||||
"settingsRealmCompactView": "紧凑领域视图",
|
||||
"settingsMixedFeed": "混合动态",
|
||||
"settingsDataSavingMode": "流量节省模式",
|
||||
"dataSavingHint": "流量节省模式",
|
||||
"settingsAutoTranslate": "自动翻译",
|
||||
"settingsHideBottomNav": "隐藏底部导航",
|
||||
"settingsSoundEffects": "音效",
|
||||
@@ -345,7 +349,7 @@
|
||||
"accountSettingsHelpContent": "此页面允许您管理您的帐户安全性、隐私和其他设置。如果您需要帮助,请联系管理员。",
|
||||
"unauthorized": "未授权",
|
||||
"unauthorizedHint": "您未登录或会话已过期,请重新登录。",
|
||||
"publisherBelongsTo": "属于",
|
||||
"publisherBelongsTo": "属于 {}",
|
||||
"postContent": "内容",
|
||||
"postSettings": "设置",
|
||||
"postPublisherUnselected": "未指定发布者",
|
||||
@@ -824,5 +828,41 @@
|
||||
"zero": "无邀请",
|
||||
"one": "{} 个可用邀请",
|
||||
"other": "{} 个可用邀请"
|
||||
}
|
||||
},
|
||||
"failedToLoadUserInfo": "加载用户信息失败",
|
||||
"failedToLoadUserInfoNetwork": "这看起来是个网络问题,你可以按下面的按钮来重试",
|
||||
"failedToLoadUserInfoUnauthorized": "看来您的会话已被注销或不再可用,如果您愿意,您仍然可以再次尝试获取用户信息。",
|
||||
"okay": "了解",
|
||||
"postDetail": "帖子详情",
|
||||
"mimeType": "类型",
|
||||
"fileSize": "大小",
|
||||
"fileHash": "哈希",
|
||||
"exifData": "EXIF 数据",
|
||||
"leveling": "等级",
|
||||
"levelingHistory": "经验记录",
|
||||
"stellarProgram": "恒星计划",
|
||||
"socialCredits": "社会信用点",
|
||||
"credits": "信用",
|
||||
"socialCreditsDescription": "社会信用是 Solar Network 评价用户的一种方式。它基于用户的行为和互动来计算。以 100 分为基准,分数越高表示用户在社区中的信誉越好。分数会随着时间的推移而变化,反映用户的最新行为。信用等级高的用户可以享受到更多的福利,反之的用户部份功能可能受到限制。",
|
||||
"socialCreditsLevelPoor": "糟糕",
|
||||
"socialCreditsLevelNormal": "正常",
|
||||
"socialCreditsLevelGood": "良好",
|
||||
"socialCreditsLevelExcellent": "优秀",
|
||||
"appDetails": "应用详情",
|
||||
"secrets": "密钥",
|
||||
"appNotFound": "应用未找到。",
|
||||
"secretCopied": "密钥已复制到剪贴板。",
|
||||
"deleteSecret": "删除密钥",
|
||||
"deleteSecretHint": "您确定要删除此密钥吗?此操作无法撤销。",
|
||||
"generateSecret": "生成新密钥",
|
||||
"createdAt": "创建于 {}",
|
||||
"newSecretGenerated": "已生成新密钥",
|
||||
"copySecretHint": "请复制此密钥并将其存放在安全的地方。您将无法再次看到它。",
|
||||
"expiresIn": "过期时间(秒)",
|
||||
"isOidc": "OIDC 兼容",
|
||||
"statusPresent": "至今",
|
||||
"accountAutomated": "机器人",
|
||||
"openInBrowser": "在浏览器中打开",
|
||||
"highlightPost": "精选帖子",
|
||||
"notableDayNext": "距离 {} 还有"
|
||||
}
|
||||
|
||||
@@ -303,7 +303,8 @@
|
||||
"notifications": "通知",
|
||||
"posts": "帖子",
|
||||
"settingsBackgroundImage": "背景圖片",
|
||||
"settingsBackgroundImageClear": "清除背景圖片",
|
||||
"settingsBackgroundImageEnable": "顯示背景圖片",
|
||||
"settingsBackgroundImageClear": "清除背景圖片",
|
||||
"settingsBackgroundGenerateColor": "從背景圖像生成主題色",
|
||||
"messageNone": "沒有內容可顯示",
|
||||
"unreadMessages": {
|
||||
@@ -314,6 +315,8 @@
|
||||
"settingsRealmCompactView": "緊湊領域視圖",
|
||||
"settingsMixedFeed": "混合動態",
|
||||
"settingsAutoTranslate": "自動翻譯",
|
||||
"settingsDataSavingMode": "低數據模式",
|
||||
"dataSavingHint": "低數據模式",
|
||||
"settingsHideBottomNav": "隱藏底部導航",
|
||||
"settingsSoundEffects": "音效",
|
||||
"settingsAprilFoolFeatures": "愚人節功能",
|
||||
@@ -811,5 +814,17 @@
|
||||
"filesListAdditional": {
|
||||
"one": "+{} 個文件被摺疊",
|
||||
"other": "+{} 個文件被摺疊"
|
||||
}
|
||||
},
|
||||
"appDetails": "應用程式詳情",
|
||||
"secrets": "密鑰",
|
||||
"appNotFound": "找不到應用程式。",
|
||||
"secretCopied": "密鑰已複製到剪貼簿。",
|
||||
"deleteSecret": "刪除密鑰",
|
||||
"deleteSecretHint": "您確定要刪除此密鑰嗎?此操作無法復原。",
|
||||
"generateSecret": "產生新密鑰",
|
||||
"createdAt": "建立於 {}",
|
||||
"newSecretGenerated": "已產生新密鑰",
|
||||
"copySecretHint": "請複製此密鑰並將其存放在安全的地方。您將無法再次看到它。",
|
||||
"expiresIn": "過期時間(秒)",
|
||||
"isOidc": "OIDC 相容"
|
||||
}
|
||||
12
assets/icons/icon-outline.svg
Normal file
12
assets/icons/icon-outline.svg
Normal file
@@ -0,0 +1,12 @@
|
||||
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" fill="none">
|
||||
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="12"
|
||||
d="M54 147h86" />
|
||||
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"
|
||||
d="M57 111s-2-4.5-2-10m22 22s-4 7-11 4m9-22s-2-4.5-2-10" />
|
||||
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="12"
|
||||
d="M54 147a32 32 0 0 1-11.999-61.665A39 39 0 0 1 81 46m59 101a30 30 0 0 0 29.933-28" />
|
||||
<circle cx="132" cy="75" r="4" stroke="#fff" stroke-linecap="round" stroke-linejoin="round"
|
||||
stroke-width="8" />
|
||||
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"
|
||||
d="M112.5 41.217C100.843 47.961 93 60.564 93 75c0 6.375 1.53 12.393 4.242 17.707m69.513-35.419A38.84 38.84 0 0 1 171 75c0 14.433-7.84 27.034-19.493 33.779m-.793-43.317A20.9 20.9 0 0 1 153 75c0 7.77-4.221 14.556-10.495 18.188m-21.003-36.38C115.224 60.44 111 67.226 111 75a20.9 20.9 0 0 0 2.284 9.533" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 1.0 KiB |
BIN
assets/images/media-offline.jpg
Normal file
BIN
assets/images/media-offline.jpg
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 461 KiB |
Binary file not shown.
|
Before Width: | Height: | Size: 307 KiB |
@@ -21,6 +21,6 @@
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>12.0</string>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
168
ios/Podfile.lock
168
ios/Podfile.lock
@@ -40,83 +40,85 @@ PODS:
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- Firebase/Crashlytics (12.0.0):
|
||||
- file_saver (0.0.1):
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- Firebase/Crashlytics (12.2.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseCrashlytics (~> 12.0.0)
|
||||
- Firebase/Messaging (12.0.0):
|
||||
- FirebaseCrashlytics (~> 12.2.0)
|
||||
- Firebase/Messaging (12.2.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 12.0.0)
|
||||
- firebase_analytics (12.0.0):
|
||||
- FirebaseMessaging (~> 12.2.0)
|
||||
- firebase_analytics (12.0.1):
|
||||
- firebase_core
|
||||
- FirebaseAnalytics (= 12.0.0)
|
||||
- FirebaseAnalytics (= 12.2.0)
|
||||
- Flutter
|
||||
- firebase_core (4.0.0):
|
||||
- Firebase/CoreOnly (= 12.0.0)
|
||||
- firebase_core (4.1.0):
|
||||
- Firebase/CoreOnly (= 12.2.0)
|
||||
- Flutter
|
||||
- firebase_crashlytics (5.0.0):
|
||||
- Firebase/Crashlytics (= 12.0.0)
|
||||
- firebase_crashlytics (5.0.1):
|
||||
- Firebase/Crashlytics (= 12.2.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_messaging (16.0.0):
|
||||
- Firebase/Messaging (= 12.0.0)
|
||||
- firebase_messaging (16.0.1):
|
||||
- Firebase/Messaging (= 12.2.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseAnalytics (12.0.0):
|
||||
- FirebaseAnalytics/Default (= 12.0.0)
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseInstallations (~> 12.0.0)
|
||||
- FirebaseAnalytics (12.2.0):
|
||||
- FirebaseAnalytics/Default (= 12.2.0)
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.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.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseInstallations (~> 12.0.0)
|
||||
- GoogleAppMeasurement/Default (= 12.0.0)
|
||||
- FirebaseAnalytics/Default (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- GoogleAppMeasurement/Default (= 12.2.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseCore (12.0.0):
|
||||
- FirebaseCoreInternal (~> 12.0.0)
|
||||
- FirebaseCore (12.2.0):
|
||||
- FirebaseCoreInternal (~> 12.2.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreExtension (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseCoreInternal (12.0.0):
|
||||
- FirebaseCoreExtension (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseCoreInternal (12.2.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- FirebaseCrashlytics (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseInstallations (~> 12.0.0)
|
||||
- FirebaseRemoteConfigInterop (~> 12.0.0)
|
||||
- FirebaseSessions (~> 12.0.0)
|
||||
- FirebaseCrashlytics (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- FirebaseRemoteConfigInterop (~> 12.2.0)
|
||||
- FirebaseSessions (~> 12.2.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseInstallations (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseInstallations (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseMessaging (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseInstallations (~> 12.0.0)
|
||||
- FirebaseMessaging (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.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.0.0)
|
||||
- FirebaseSessions (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseCoreExtension (~> 12.0.0)
|
||||
- FirebaseInstallations (~> 12.0.0)
|
||||
- FirebaseRemoteConfigInterop (12.2.0)
|
||||
- FirebaseSessions (12.2.0):
|
||||
- FirebaseCore (~> 12.2.0)
|
||||
- FirebaseCoreExtension (~> 12.2.0)
|
||||
- FirebaseInstallations (~> 12.2.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
@@ -134,6 +136,8 @@ PODS:
|
||||
- OrderedSet (~> 6.0.3)
|
||||
- flutter_keyboard_visibility (0.0.1):
|
||||
- Flutter
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- Flutter
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- flutter_platform_alert (0.0.1):
|
||||
@@ -145,33 +149,33 @@ PODS:
|
||||
- flutter_udid (0.0.1):
|
||||
- Flutter
|
||||
- SAMKeychain
|
||||
- flutter_webrtc (1.0.0):
|
||||
- flutter_webrtc (1.1.0):
|
||||
- Flutter
|
||||
- WebRTC-SDK (= 137.7151.02)
|
||||
- WebRTC-SDK (= 137.7151.03)
|
||||
- gal (1.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- GoogleAdsOnDeviceConversion (2.1.0):
|
||||
- GoogleAdsOnDeviceConversion (2.3.0):
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Core (12.0.0):
|
||||
- GoogleAppMeasurement/Core (12.2.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.0.0):
|
||||
- GoogleAdsOnDeviceConversion (= 2.1.0)
|
||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (= 12.0.0)
|
||||
- GoogleAppMeasurement/Default (12.2.0):
|
||||
- GoogleAdsOnDeviceConversion (= 2.3.0)
|
||||
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (= 12.2.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.0.0):
|
||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (12.2.0):
|
||||
- GoogleAppMeasurement/Core (= 12.2.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
@@ -215,7 +219,7 @@ PODS:
|
||||
- livekit_client (2.5.0):
|
||||
- Flutter
|
||||
- flutter_webrtc
|
||||
- WebRTC-SDK (= 137.7151.02)
|
||||
- WebRTC-SDK (= 137.7151.03)
|
||||
- local_auth_darwin (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -248,9 +252,9 @@ PODS:
|
||||
- record_ios (1.1.0):
|
||||
- Flutter
|
||||
- SAMKeychain (1.5.3)
|
||||
- SDWebImage (5.21.1):
|
||||
- SDWebImage/Core (= 5.21.1)
|
||||
- SDWebImage/Core (5.21.1)
|
||||
- SDWebImage (5.21.2):
|
||||
- SDWebImage/Core (= 5.21.2)
|
||||
- SDWebImage/Core (5.21.2)
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
@@ -295,7 +299,7 @@ PODS:
|
||||
- Flutter
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- WebRTC-SDK (137.7151.02)
|
||||
- WebRTC-SDK (137.7151.03)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Alamofire
|
||||
@@ -303,6 +307,7 @@ DEPENDENCIES:
|
||||
- croppy (from `.symlinks/plugins/croppy/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
||||
@@ -311,6 +316,7 @@ DEPENDENCIES:
|
||||
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
@@ -381,6 +387,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
file_saver:
|
||||
:path: ".symlinks/plugins/file_saver/ios"
|
||||
firebase_analytics:
|
||||
:path: ".symlinks/plugins/firebase_analytics/ios"
|
||||
firebase_core:
|
||||
@@ -397,6 +405,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||
flutter_keyboard_visibility:
|
||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||
flutter_local_notifications:
|
||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_platform_alert:
|
||||
@@ -464,39 +474,41 @@ SPEC CHECKSUMS:
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
Firebase: 800d487043c0557d9faed71477a38d9aafb08a41
|
||||
firebase_analytics: cd56fc56f75c1df30a6ff5290cd56e230996a76d
|
||||
firebase_core: 633e1851ffe1b9ab875f6467a4f574c79cef02e4
|
||||
firebase_crashlytics: 2c6c1a17900a38081d938330e9f48e60ec5b255d
|
||||
firebase_messaging: d17feef781edc84ebefe62624fb384358ad96361
|
||||
FirebaseAnalytics: 6d790cd1b159b4eb61a99948df0934ce505a34f7
|
||||
FirebaseCore: 055f4ab117d5964158c833f3d5e7ec6d91648d4a
|
||||
FirebaseCoreExtension: 639afb3de6abd611952be78a794c54a47fa0f361
|
||||
FirebaseCoreInternal: dedc28e569a4be85f38f3d6af1070a2e12018d55
|
||||
FirebaseCrashlytics: db75aa0cab8d00f68406fa247c32fe17ade884d7
|
||||
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
||||
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
||||
FirebaseRemoteConfigInterop: bfa0ea72ba3dc5af739777296424e46bd6f42613
|
||||
FirebaseSessions: 4e784acda213108aafef536535cdfc03504acc42
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
Firebase: 26f6f8d460603af3df970ad505b16b15f5e2e9a1
|
||||
firebase_analytics: 111ff65791a430356bd6c7e4d7339537fc6a15ae
|
||||
firebase_core: 3ff52146406557dddd01d570e807e203ec7e1302
|
||||
firebase_crashlytics: 3637078b718a52dc9fb4d64e37c969e86b87ff6f
|
||||
firebase_messaging: 3dcc998dd98e1e54af75d0cccae8606eba43553c
|
||||
FirebaseAnalytics: e04e23bc070e3014aa5cf4980f9df7ce5cd79ec8
|
||||
FirebaseCore: 311c48a147ad4a0ab7febbaed89e8025c67510cd
|
||||
FirebaseCoreExtension: 73af080c22a2f7b44cefa391dc08f7e4ee162cb5
|
||||
FirebaseCoreInternal: 56ea29f3dad2894f81b060f706f9d53509b6ed3b
|
||||
FirebaseCrashlytics: f83cbf176d5c637ade108c0aacf1ccbd5ec499bf
|
||||
FirebaseInstallations: 3e884b01feabdf67582a80f3250425a00979b4ed
|
||||
FirebaseMessaging: 43ec73bbfedd0c385a849bb91593ab4ad4b9e48e
|
||||
FirebaseRemoteConfigInterop: 0896fd52ab72586a355c8f389ff85aaa9e5375e1
|
||||
FirebaseSessions: f4692789e770bec66ce17d772c0e9561c4f11737
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||
flutter_webrtc: 6f7da106613d52ade777d5b4875a43f48c28b457
|
||||
flutter_webrtc: b0b2e04411747142962164a1cfa43a1af9a0afac
|
||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||
GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64
|
||||
GoogleAppMeasurement: 8f6ab04ad6ae493b53fcf56bd26323fb2f1384f3
|
||||
GoogleAdsOnDeviceConversion: 9090c435cde08903e8dd1ba2c77fbec9e46d9afe
|
||||
GoogleAppMeasurement: 09f341dfa8527d1612a09cbfe809a242c0b737af
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
||||
livekit_client: e3b79b99405428aac439b6b76a254cd9a11dbbfb
|
||||
livekit_client: f810c81bbbc229a84f60b09e66603ac4e93f7599
|
||||
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
@@ -512,7 +524,7 @@ SPEC CHECKSUMS:
|
||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SDWebImage: 9f177d83116802728e122410fb25ad88f5c7608a
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
||||
@@ -524,7 +536,7 @@ SPEC CHECKSUMS:
|
||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||
WebRTC-SDK: d20de357dcbf7c9696b124b39f3ff62125107e4b
|
||||
WebRTC-SDK: 69d4e56b0b4b27d788e87bab9b9a1326ed05b1e3
|
||||
|
||||
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
||||
|
||||
|
||||
@@ -853,7 +853,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@@ -897,6 +897,7 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -915,6 +916,7 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -931,6 +933,7 @@
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
@@ -1078,7 +1081,7 @@
|
||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -1121,7 +1124,7 @@
|
||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -1161,7 +1164,7 @@
|
||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -1348,7 +1351,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1399,7 +1402,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
|
||||
@@ -47,6 +47,7 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
private func processNotification(request: UNNotificationRequest, content: UNMutableNotificationContent) throws {
|
||||
switch content.userInfo["type"] as? String {
|
||||
case "messages.new":
|
||||
content.categoryIdentifier = "REPLYABLE_MESSAGE"
|
||||
try handleMessagingNotification(request: request, content: content)
|
||||
default:
|
||||
try handleDefaultNotification(content: content)
|
||||
@@ -60,8 +61,6 @@ class NotificationService: UNNotificationServiceExtension {
|
||||
|
||||
let pfpIdentifier = meta["pfp"] as? String
|
||||
|
||||
content.categoryIdentifier = "REPLYABLE_MESSAGE"
|
||||
|
||||
let metaCopy = meta as? [String: Any] ?? [:]
|
||||
let pfpUrl = pfpIdentifier != nil ? getAttachmentUrl(for: pfpIdentifier!) : nil
|
||||
|
||||
|
||||
@@ -2,8 +2,15 @@ import 'package:drift/drift.dart';
|
||||
|
||||
class PostDrafts extends Table {
|
||||
TextColumn get id => text()();
|
||||
TextColumn get post => text()(); // Store SnPost model as JSON string
|
||||
// Searchable fields stored separately for performance
|
||||
TextColumn get title => text().nullable()();
|
||||
TextColumn get description => text().nullable()();
|
||||
TextColumn get content => text().nullable()();
|
||||
IntColumn get visibility => integer().withDefault(const Constant(0))();
|
||||
IntColumn get type => integer().withDefault(const Constant(0))();
|
||||
DateTimeColumn get lastModified => dateTime()();
|
||||
// Full post data stored as JSON for complete restoration
|
||||
TextColumn get postData => text()();
|
||||
|
||||
@override
|
||||
Set<Column> get primaryKey => {id};
|
||||
|
||||
@@ -12,7 +12,7 @@ class AppDatabase extends _$AppDatabase {
|
||||
AppDatabase(super.e);
|
||||
|
||||
@override
|
||||
int get schemaVersion => 4;
|
||||
int get schemaVersion => 6;
|
||||
|
||||
@override
|
||||
MigrationStrategy get migration => MigrationStrategy(
|
||||
@@ -28,9 +28,67 @@ class AppDatabase extends _$AppDatabase {
|
||||
// Drop old draft tables if they exist
|
||||
await m.createTable(postDrafts);
|
||||
}
|
||||
if (from < 6) {
|
||||
// Migrate from old schema to new schema with separate searchable fields
|
||||
await _migrateToVersion6(m);
|
||||
}
|
||||
},
|
||||
);
|
||||
|
||||
Future<void> _migrateToVersion6(Migrator m) async {
|
||||
// Rename existing table to old if it exists
|
||||
try {
|
||||
await customStatement(
|
||||
'ALTER TABLE post_drafts RENAME TO post_drafts_old',
|
||||
);
|
||||
} catch (e) {
|
||||
// Table might not exist
|
||||
}
|
||||
|
||||
// Drop the table
|
||||
await customStatement('DROP TABLE IF EXISTS post_drafts');
|
||||
|
||||
// Create new table
|
||||
await m.createTable(postDrafts);
|
||||
|
||||
// Migrate existing data if any
|
||||
try {
|
||||
final oldDrafts =
|
||||
await customSelect(
|
||||
'SELECT id, post, lastModified FROM post_drafts_old',
|
||||
readsFrom: {postDrafts},
|
||||
).get();
|
||||
|
||||
for (final row in oldDrafts) {
|
||||
final postJson = row.read<String>('post');
|
||||
final id = row.read<String>('id');
|
||||
final lastModified = row.read<DateTime>('lastModified');
|
||||
|
||||
if (postJson.isNotEmpty) {
|
||||
final post = SnPost.fromJson(jsonDecode(postJson));
|
||||
await into(postDrafts).insert(
|
||||
PostDraftsCompanion(
|
||||
id: Value(id),
|
||||
title: Value(post.title),
|
||||
description: Value(post.description),
|
||||
content: Value(post.content),
|
||||
visibility: Value(post.visibility),
|
||||
type: Value(post.type),
|
||||
lastModified: Value(lastModified),
|
||||
postData: Value(postJson),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Drop old table
|
||||
await customStatement('DROP TABLE IF EXISTS post_drafts_old');
|
||||
} catch (e) {
|
||||
// If migration fails, just recreate the table
|
||||
await m.createTable(postDrafts);
|
||||
}
|
||||
}
|
||||
|
||||
// Methods for chat messages
|
||||
Future<List<ChatMessage>> getMessagesForRoom(
|
||||
String roomId, {
|
||||
@@ -68,6 +126,32 @@ class AppDatabase extends _$AppDatabase {
|
||||
return (delete(chatMessages)..where((m) => m.id.equals(id))).go();
|
||||
}
|
||||
|
||||
Future<int> getTotalMessagesForRoom(String roomId) {
|
||||
return (select(
|
||||
chatMessages,
|
||||
)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length);
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> searchMessages(
|
||||
String roomId,
|
||||
String query,
|
||||
) async {
|
||||
var selectStatement = select(chatMessages)
|
||||
..where((m) => m.roomId.equals(roomId));
|
||||
|
||||
if (query.isNotEmpty) {
|
||||
selectStatement =
|
||||
selectStatement
|
||||
..where((m) => m.content.like('%${query.toLowerCase()}%'));
|
||||
}
|
||||
|
||||
final messages =
|
||||
await (selectStatement
|
||||
..orderBy([(m) => OrderingTerm.desc(m.createdAt)]))
|
||||
.get();
|
||||
return messages.map((msg) => companionToMessage(msg)).toList();
|
||||
}
|
||||
|
||||
// Convert between Drift and model objects
|
||||
ChatMessagesCompanion messageToCompanion(LocalChatMessage message) {
|
||||
return ChatMessagesCompanion(
|
||||
@@ -101,10 +185,31 @@ class AppDatabase extends _$AppDatabase {
|
||||
Future<List<SnPost>> getAllPostDrafts() async {
|
||||
final drafts = await select(postDrafts).get();
|
||||
return drafts
|
||||
.map((draft) => SnPost.fromJson(jsonDecode(draft.post)))
|
||||
.map((draft) => SnPost.fromJson(jsonDecode(draft.postData)))
|
||||
.toList();
|
||||
}
|
||||
|
||||
Future<List<PostDraft>> getAllPostDraftRecords() async {
|
||||
return await select(postDrafts).get();
|
||||
}
|
||||
|
||||
Future<List<PostDraft>> searchPostDrafts(String query) async {
|
||||
if (query.isEmpty) {
|
||||
return await select(postDrafts).get();
|
||||
}
|
||||
|
||||
final searchTerm = '%${query.toLowerCase()}%';
|
||||
return await (select(postDrafts)
|
||||
..where(
|
||||
(draft) =>
|
||||
draft.title.like(searchTerm) |
|
||||
draft.description.like(searchTerm) |
|
||||
draft.content.like(searchTerm),
|
||||
)
|
||||
..orderBy([(draft) => OrderingTerm.desc(draft.lastModified)]))
|
||||
.get();
|
||||
}
|
||||
|
||||
Future<void> addPostDraft(PostDraftsCompanion entry) async {
|
||||
await into(postDrafts).insert(entry, mode: InsertMode.replace);
|
||||
}
|
||||
@@ -116,4 +221,9 @@ class AppDatabase extends _$AppDatabase {
|
||||
Future<void> clearAllPostDrafts() async {
|
||||
await delete(postDrafts).go();
|
||||
}
|
||||
|
||||
Future<PostDraft?> getPostDraftById(String id) async {
|
||||
return await (select(postDrafts)
|
||||
..where((tbl) => tbl.id.equals(id))).getSingleOrNull();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -584,14 +584,58 @@ class $PostDraftsTable extends PostDrafts
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const VerificationMeta _postMeta = const VerificationMeta('post');
|
||||
static const VerificationMeta _titleMeta = const VerificationMeta('title');
|
||||
@override
|
||||
late final GeneratedColumn<String> post = GeneratedColumn<String>(
|
||||
'post',
|
||||
late final GeneratedColumn<String> title = GeneratedColumn<String>(
|
||||
'title',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _descriptionMeta = const VerificationMeta(
|
||||
'description',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<String> description = GeneratedColumn<String>(
|
||||
'description',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _contentMeta = const VerificationMeta(
|
||||
'content',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<String> content = GeneratedColumn<String>(
|
||||
'content',
|
||||
aliasedName,
|
||||
true,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: false,
|
||||
);
|
||||
static const VerificationMeta _visibilityMeta = const VerificationMeta(
|
||||
'visibility',
|
||||
);
|
||||
@override
|
||||
late final GeneratedColumn<int> visibility = GeneratedColumn<int>(
|
||||
'visibility',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant(0),
|
||||
);
|
||||
static const VerificationMeta _typeMeta = const VerificationMeta('type');
|
||||
@override
|
||||
late final GeneratedColumn<int> type = GeneratedColumn<int>(
|
||||
'type',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.int,
|
||||
requiredDuringInsert: false,
|
||||
defaultValue: const Constant(0),
|
||||
);
|
||||
static const VerificationMeta _lastModifiedMeta = const VerificationMeta(
|
||||
'lastModified',
|
||||
@@ -604,8 +648,28 @@ class $PostDraftsTable extends PostDrafts
|
||||
type: DriftSqlType.dateTime,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
static const VerificationMeta _postDataMeta = const VerificationMeta(
|
||||
'postData',
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [id, post, lastModified];
|
||||
late final GeneratedColumn<String> postData = GeneratedColumn<String>(
|
||||
'post_data',
|
||||
aliasedName,
|
||||
false,
|
||||
type: DriftSqlType.string,
|
||||
requiredDuringInsert: true,
|
||||
);
|
||||
@override
|
||||
List<GeneratedColumn> get $columns => [
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
content,
|
||||
visibility,
|
||||
type,
|
||||
lastModified,
|
||||
postData,
|
||||
];
|
||||
@override
|
||||
String get aliasedName => _alias ?? actualTableName;
|
||||
@override
|
||||
@@ -623,13 +687,38 @@ class $PostDraftsTable extends PostDrafts
|
||||
} else if (isInserting) {
|
||||
context.missing(_idMeta);
|
||||
}
|
||||
if (data.containsKey('post')) {
|
||||
if (data.containsKey('title')) {
|
||||
context.handle(
|
||||
_postMeta,
|
||||
post.isAcceptableOrUnknown(data['post']!, _postMeta),
|
||||
_titleMeta,
|
||||
title.isAcceptableOrUnknown(data['title']!, _titleMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('description')) {
|
||||
context.handle(
|
||||
_descriptionMeta,
|
||||
description.isAcceptableOrUnknown(
|
||||
data['description']!,
|
||||
_descriptionMeta,
|
||||
),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('content')) {
|
||||
context.handle(
|
||||
_contentMeta,
|
||||
content.isAcceptableOrUnknown(data['content']!, _contentMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('visibility')) {
|
||||
context.handle(
|
||||
_visibilityMeta,
|
||||
visibility.isAcceptableOrUnknown(data['visibility']!, _visibilityMeta),
|
||||
);
|
||||
}
|
||||
if (data.containsKey('type')) {
|
||||
context.handle(
|
||||
_typeMeta,
|
||||
type.isAcceptableOrUnknown(data['type']!, _typeMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_postMeta);
|
||||
}
|
||||
if (data.containsKey('last_modified')) {
|
||||
context.handle(
|
||||
@@ -642,6 +731,14 @@ class $PostDraftsTable extends PostDrafts
|
||||
} else if (isInserting) {
|
||||
context.missing(_lastModifiedMeta);
|
||||
}
|
||||
if (data.containsKey('post_data')) {
|
||||
context.handle(
|
||||
_postDataMeta,
|
||||
postData.isAcceptableOrUnknown(data['post_data']!, _postDataMeta),
|
||||
);
|
||||
} else if (isInserting) {
|
||||
context.missing(_postDataMeta);
|
||||
}
|
||||
return context;
|
||||
}
|
||||
|
||||
@@ -656,16 +753,38 @@ class $PostDraftsTable extends PostDrafts
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}id'],
|
||||
)!,
|
||||
post:
|
||||
title: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}title'],
|
||||
),
|
||||
description: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}description'],
|
||||
),
|
||||
content: attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}content'],
|
||||
),
|
||||
visibility:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}post'],
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}visibility'],
|
||||
)!,
|
||||
type:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.int,
|
||||
data['${effectivePrefix}type'],
|
||||
)!,
|
||||
lastModified:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.dateTime,
|
||||
data['${effectivePrefix}last_modified'],
|
||||
)!,
|
||||
postData:
|
||||
attachedDatabase.typeMapping.read(
|
||||
DriftSqlType.string,
|
||||
data['${effectivePrefix}post_data'],
|
||||
)!,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -677,27 +796,60 @@ class $PostDraftsTable extends PostDrafts
|
||||
|
||||
class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
final String id;
|
||||
final String post;
|
||||
final String? title;
|
||||
final String? description;
|
||||
final String? content;
|
||||
final int visibility;
|
||||
final int type;
|
||||
final DateTime lastModified;
|
||||
final String postData;
|
||||
const PostDraft({
|
||||
required this.id,
|
||||
required this.post,
|
||||
this.title,
|
||||
this.description,
|
||||
this.content,
|
||||
required this.visibility,
|
||||
required this.type,
|
||||
required this.lastModified,
|
||||
required this.postData,
|
||||
});
|
||||
@override
|
||||
Map<String, Expression> toColumns(bool nullToAbsent) {
|
||||
final map = <String, Expression>{};
|
||||
map['id'] = Variable<String>(id);
|
||||
map['post'] = Variable<String>(post);
|
||||
if (!nullToAbsent || title != null) {
|
||||
map['title'] = Variable<String>(title);
|
||||
}
|
||||
if (!nullToAbsent || description != null) {
|
||||
map['description'] = Variable<String>(description);
|
||||
}
|
||||
if (!nullToAbsent || content != null) {
|
||||
map['content'] = Variable<String>(content);
|
||||
}
|
||||
map['visibility'] = Variable<int>(visibility);
|
||||
map['type'] = Variable<int>(type);
|
||||
map['last_modified'] = Variable<DateTime>(lastModified);
|
||||
map['post_data'] = Variable<String>(postData);
|
||||
return map;
|
||||
}
|
||||
|
||||
PostDraftsCompanion toCompanion(bool nullToAbsent) {
|
||||
return PostDraftsCompanion(
|
||||
id: Value(id),
|
||||
post: Value(post),
|
||||
title:
|
||||
title == null && nullToAbsent ? const Value.absent() : Value(title),
|
||||
description:
|
||||
description == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(description),
|
||||
content:
|
||||
content == null && nullToAbsent
|
||||
? const Value.absent()
|
||||
: Value(content),
|
||||
visibility: Value(visibility),
|
||||
type: Value(type),
|
||||
lastModified: Value(lastModified),
|
||||
postData: Value(postData),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -708,8 +860,13 @@ class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return PostDraft(
|
||||
id: serializer.fromJson<String>(json['id']),
|
||||
post: serializer.fromJson<String>(json['post']),
|
||||
title: serializer.fromJson<String?>(json['title']),
|
||||
description: serializer.fromJson<String?>(json['description']),
|
||||
content: serializer.fromJson<String?>(json['content']),
|
||||
visibility: serializer.fromJson<int>(json['visibility']),
|
||||
type: serializer.fromJson<int>(json['type']),
|
||||
lastModified: serializer.fromJson<DateTime>(json['lastModified']),
|
||||
postData: serializer.fromJson<String>(json['postData']),
|
||||
);
|
||||
}
|
||||
@override
|
||||
@@ -717,25 +874,50 @@ class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
serializer ??= driftRuntimeOptions.defaultSerializer;
|
||||
return <String, dynamic>{
|
||||
'id': serializer.toJson<String>(id),
|
||||
'post': serializer.toJson<String>(post),
|
||||
'title': serializer.toJson<String?>(title),
|
||||
'description': serializer.toJson<String?>(description),
|
||||
'content': serializer.toJson<String?>(content),
|
||||
'visibility': serializer.toJson<int>(visibility),
|
||||
'type': serializer.toJson<int>(type),
|
||||
'lastModified': serializer.toJson<DateTime>(lastModified),
|
||||
'postData': serializer.toJson<String>(postData),
|
||||
};
|
||||
}
|
||||
|
||||
PostDraft copyWith({String? id, String? post, DateTime? lastModified}) =>
|
||||
PostDraft(
|
||||
id: id ?? this.id,
|
||||
post: post ?? this.post,
|
||||
lastModified: lastModified ?? this.lastModified,
|
||||
);
|
||||
PostDraft copyWith({
|
||||
String? id,
|
||||
Value<String?> title = const Value.absent(),
|
||||
Value<String?> description = const Value.absent(),
|
||||
Value<String?> content = const Value.absent(),
|
||||
int? visibility,
|
||||
int? type,
|
||||
DateTime? lastModified,
|
||||
String? postData,
|
||||
}) => PostDraft(
|
||||
id: id ?? this.id,
|
||||
title: title.present ? title.value : this.title,
|
||||
description: description.present ? description.value : this.description,
|
||||
content: content.present ? content.value : this.content,
|
||||
visibility: visibility ?? this.visibility,
|
||||
type: type ?? this.type,
|
||||
lastModified: lastModified ?? this.lastModified,
|
||||
postData: postData ?? this.postData,
|
||||
);
|
||||
PostDraft copyWithCompanion(PostDraftsCompanion data) {
|
||||
return PostDraft(
|
||||
id: data.id.present ? data.id.value : this.id,
|
||||
post: data.post.present ? data.post.value : this.post,
|
||||
title: data.title.present ? data.title.value : this.title,
|
||||
description:
|
||||
data.description.present ? data.description.value : this.description,
|
||||
content: data.content.present ? data.content.value : this.content,
|
||||
visibility:
|
||||
data.visibility.present ? data.visibility.value : this.visibility,
|
||||
type: data.type.present ? data.type.value : this.type,
|
||||
lastModified:
|
||||
data.lastModified.present
|
||||
? data.lastModified.value
|
||||
: this.lastModified,
|
||||
postData: data.postData.present ? data.postData.value : this.postData,
|
||||
);
|
||||
}
|
||||
|
||||
@@ -743,66 +925,120 @@ class PostDraft extends DataClass implements Insertable<PostDraft> {
|
||||
String toString() {
|
||||
return (StringBuffer('PostDraft(')
|
||||
..write('id: $id, ')
|
||||
..write('post: $post, ')
|
||||
..write('lastModified: $lastModified')
|
||||
..write('title: $title, ')
|
||||
..write('description: $description, ')
|
||||
..write('content: $content, ')
|
||||
..write('visibility: $visibility, ')
|
||||
..write('type: $type, ')
|
||||
..write('lastModified: $lastModified, ')
|
||||
..write('postData: $postData')
|
||||
..write(')'))
|
||||
.toString();
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(id, post, lastModified);
|
||||
int get hashCode => Object.hash(
|
||||
id,
|
||||
title,
|
||||
description,
|
||||
content,
|
||||
visibility,
|
||||
type,
|
||||
lastModified,
|
||||
postData,
|
||||
);
|
||||
@override
|
||||
bool operator ==(Object other) =>
|
||||
identical(this, other) ||
|
||||
(other is PostDraft &&
|
||||
other.id == this.id &&
|
||||
other.post == this.post &&
|
||||
other.lastModified == this.lastModified);
|
||||
other.title == this.title &&
|
||||
other.description == this.description &&
|
||||
other.content == this.content &&
|
||||
other.visibility == this.visibility &&
|
||||
other.type == this.type &&
|
||||
other.lastModified == this.lastModified &&
|
||||
other.postData == this.postData);
|
||||
}
|
||||
|
||||
class PostDraftsCompanion extends UpdateCompanion<PostDraft> {
|
||||
final Value<String> id;
|
||||
final Value<String> post;
|
||||
final Value<String?> title;
|
||||
final Value<String?> description;
|
||||
final Value<String?> content;
|
||||
final Value<int> visibility;
|
||||
final Value<int> type;
|
||||
final Value<DateTime> lastModified;
|
||||
final Value<String> postData;
|
||||
final Value<int> rowid;
|
||||
const PostDraftsCompanion({
|
||||
this.id = const Value.absent(),
|
||||
this.post = const Value.absent(),
|
||||
this.title = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.content = const Value.absent(),
|
||||
this.visibility = const Value.absent(),
|
||||
this.type = const Value.absent(),
|
||||
this.lastModified = const Value.absent(),
|
||||
this.postData = const Value.absent(),
|
||||
this.rowid = const Value.absent(),
|
||||
});
|
||||
PostDraftsCompanion.insert({
|
||||
required String id,
|
||||
required String post,
|
||||
this.title = const Value.absent(),
|
||||
this.description = const Value.absent(),
|
||||
this.content = const Value.absent(),
|
||||
this.visibility = const Value.absent(),
|
||||
this.type = const Value.absent(),
|
||||
required DateTime lastModified,
|
||||
required String postData,
|
||||
this.rowid = const Value.absent(),
|
||||
}) : id = Value(id),
|
||||
post = Value(post),
|
||||
lastModified = Value(lastModified);
|
||||
lastModified = Value(lastModified),
|
||||
postData = Value(postData);
|
||||
static Insertable<PostDraft> custom({
|
||||
Expression<String>? id,
|
||||
Expression<String>? post,
|
||||
Expression<String>? title,
|
||||
Expression<String>? description,
|
||||
Expression<String>? content,
|
||||
Expression<int>? visibility,
|
||||
Expression<int>? type,
|
||||
Expression<DateTime>? lastModified,
|
||||
Expression<String>? postData,
|
||||
Expression<int>? rowid,
|
||||
}) {
|
||||
return RawValuesInsertable({
|
||||
if (id != null) 'id': id,
|
||||
if (post != null) 'post': post,
|
||||
if (title != null) 'title': title,
|
||||
if (description != null) 'description': description,
|
||||
if (content != null) 'content': content,
|
||||
if (visibility != null) 'visibility': visibility,
|
||||
if (type != null) 'type': type,
|
||||
if (lastModified != null) 'last_modified': lastModified,
|
||||
if (postData != null) 'post_data': postData,
|
||||
if (rowid != null) 'rowid': rowid,
|
||||
});
|
||||
}
|
||||
|
||||
PostDraftsCompanion copyWith({
|
||||
Value<String>? id,
|
||||
Value<String>? post,
|
||||
Value<String?>? title,
|
||||
Value<String?>? description,
|
||||
Value<String?>? content,
|
||||
Value<int>? visibility,
|
||||
Value<int>? type,
|
||||
Value<DateTime>? lastModified,
|
||||
Value<String>? postData,
|
||||
Value<int>? rowid,
|
||||
}) {
|
||||
return PostDraftsCompanion(
|
||||
id: id ?? this.id,
|
||||
post: post ?? this.post,
|
||||
title: title ?? this.title,
|
||||
description: description ?? this.description,
|
||||
content: content ?? this.content,
|
||||
visibility: visibility ?? this.visibility,
|
||||
type: type ?? this.type,
|
||||
lastModified: lastModified ?? this.lastModified,
|
||||
postData: postData ?? this.postData,
|
||||
rowid: rowid ?? this.rowid,
|
||||
);
|
||||
}
|
||||
@@ -813,12 +1049,27 @@ class PostDraftsCompanion extends UpdateCompanion<PostDraft> {
|
||||
if (id.present) {
|
||||
map['id'] = Variable<String>(id.value);
|
||||
}
|
||||
if (post.present) {
|
||||
map['post'] = Variable<String>(post.value);
|
||||
if (title.present) {
|
||||
map['title'] = Variable<String>(title.value);
|
||||
}
|
||||
if (description.present) {
|
||||
map['description'] = Variable<String>(description.value);
|
||||
}
|
||||
if (content.present) {
|
||||
map['content'] = Variable<String>(content.value);
|
||||
}
|
||||
if (visibility.present) {
|
||||
map['visibility'] = Variable<int>(visibility.value);
|
||||
}
|
||||
if (type.present) {
|
||||
map['type'] = Variable<int>(type.value);
|
||||
}
|
||||
if (lastModified.present) {
|
||||
map['last_modified'] = Variable<DateTime>(lastModified.value);
|
||||
}
|
||||
if (postData.present) {
|
||||
map['post_data'] = Variable<String>(postData.value);
|
||||
}
|
||||
if (rowid.present) {
|
||||
map['rowid'] = Variable<int>(rowid.value);
|
||||
}
|
||||
@@ -829,8 +1080,13 @@ class PostDraftsCompanion extends UpdateCompanion<PostDraft> {
|
||||
String toString() {
|
||||
return (StringBuffer('PostDraftsCompanion(')
|
||||
..write('id: $id, ')
|
||||
..write('post: $post, ')
|
||||
..write('title: $title, ')
|
||||
..write('description: $description, ')
|
||||
..write('content: $content, ')
|
||||
..write('visibility: $visibility, ')
|
||||
..write('type: $type, ')
|
||||
..write('lastModified: $lastModified, ')
|
||||
..write('postData: $postData, ')
|
||||
..write('rowid: $rowid')
|
||||
..write(')'))
|
||||
.toString();
|
||||
@@ -1140,15 +1396,25 @@ typedef $$ChatMessagesTableProcessedTableManager =
|
||||
typedef $$PostDraftsTableCreateCompanionBuilder =
|
||||
PostDraftsCompanion Function({
|
||||
required String id,
|
||||
required String post,
|
||||
Value<String?> title,
|
||||
Value<String?> description,
|
||||
Value<String?> content,
|
||||
Value<int> visibility,
|
||||
Value<int> type,
|
||||
required DateTime lastModified,
|
||||
required String postData,
|
||||
Value<int> rowid,
|
||||
});
|
||||
typedef $$PostDraftsTableUpdateCompanionBuilder =
|
||||
PostDraftsCompanion Function({
|
||||
Value<String> id,
|
||||
Value<String> post,
|
||||
Value<String?> title,
|
||||
Value<String?> description,
|
||||
Value<String?> content,
|
||||
Value<int> visibility,
|
||||
Value<int> type,
|
||||
Value<DateTime> lastModified,
|
||||
Value<String> postData,
|
||||
Value<int> rowid,
|
||||
});
|
||||
|
||||
@@ -1166,8 +1432,28 @@ class $$PostDraftsTableFilterComposer
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get post => $composableBuilder(
|
||||
column: $table.post,
|
||||
ColumnFilters<String> get title => $composableBuilder(
|
||||
column: $table.title,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get description => $composableBuilder(
|
||||
column: $table.description,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get content => $composableBuilder(
|
||||
column: $table.content,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<int> get visibility => $composableBuilder(
|
||||
column: $table.visibility,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<int> get type => $composableBuilder(
|
||||
column: $table.type,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
@@ -1175,6 +1461,11 @@ class $$PostDraftsTableFilterComposer
|
||||
column: $table.lastModified,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
|
||||
ColumnFilters<String> get postData => $composableBuilder(
|
||||
column: $table.postData,
|
||||
builder: (column) => ColumnFilters(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$PostDraftsTableOrderingComposer
|
||||
@@ -1191,8 +1482,28 @@ class $$PostDraftsTableOrderingComposer
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get post => $composableBuilder(
|
||||
column: $table.post,
|
||||
ColumnOrderings<String> get title => $composableBuilder(
|
||||
column: $table.title,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get description => $composableBuilder(
|
||||
column: $table.description,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get content => $composableBuilder(
|
||||
column: $table.content,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<int> get visibility => $composableBuilder(
|
||||
column: $table.visibility,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<int> get type => $composableBuilder(
|
||||
column: $table.type,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
@@ -1200,6 +1511,11 @@ class $$PostDraftsTableOrderingComposer
|
||||
column: $table.lastModified,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
|
||||
ColumnOrderings<String> get postData => $composableBuilder(
|
||||
column: $table.postData,
|
||||
builder: (column) => ColumnOrderings(column),
|
||||
);
|
||||
}
|
||||
|
||||
class $$PostDraftsTableAnnotationComposer
|
||||
@@ -1214,13 +1530,32 @@ class $$PostDraftsTableAnnotationComposer
|
||||
GeneratedColumn<String> get id =>
|
||||
$composableBuilder(column: $table.id, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<String> get post =>
|
||||
$composableBuilder(column: $table.post, builder: (column) => column);
|
||||
GeneratedColumn<String> get title =>
|
||||
$composableBuilder(column: $table.title, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<String> get description => $composableBuilder(
|
||||
column: $table.description,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
GeneratedColumn<String> get content =>
|
||||
$composableBuilder(column: $table.content, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<int> get visibility => $composableBuilder(
|
||||
column: $table.visibility,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
GeneratedColumn<int> get type =>
|
||||
$composableBuilder(column: $table.type, builder: (column) => column);
|
||||
|
||||
GeneratedColumn<DateTime> get lastModified => $composableBuilder(
|
||||
column: $table.lastModified,
|
||||
builder: (column) => column,
|
||||
);
|
||||
|
||||
GeneratedColumn<String> get postData =>
|
||||
$composableBuilder(column: $table.postData, builder: (column) => column);
|
||||
}
|
||||
|
||||
class $$PostDraftsTableTableManager
|
||||
@@ -1255,25 +1590,45 @@ class $$PostDraftsTableTableManager
|
||||
updateCompanionCallback:
|
||||
({
|
||||
Value<String> id = const Value.absent(),
|
||||
Value<String> post = const Value.absent(),
|
||||
Value<String?> title = const Value.absent(),
|
||||
Value<String?> description = const Value.absent(),
|
||||
Value<String?> content = const Value.absent(),
|
||||
Value<int> visibility = const Value.absent(),
|
||||
Value<int> type = const Value.absent(),
|
||||
Value<DateTime> lastModified = const Value.absent(),
|
||||
Value<String> postData = const Value.absent(),
|
||||
Value<int> rowid = const Value.absent(),
|
||||
}) => PostDraftsCompanion(
|
||||
id: id,
|
||||
post: post,
|
||||
title: title,
|
||||
description: description,
|
||||
content: content,
|
||||
visibility: visibility,
|
||||
type: type,
|
||||
lastModified: lastModified,
|
||||
postData: postData,
|
||||
rowid: rowid,
|
||||
),
|
||||
createCompanionCallback:
|
||||
({
|
||||
required String id,
|
||||
required String post,
|
||||
Value<String?> title = const Value.absent(),
|
||||
Value<String?> description = const Value.absent(),
|
||||
Value<String?> content = const Value.absent(),
|
||||
Value<int> visibility = const Value.absent(),
|
||||
Value<int> type = const Value.absent(),
|
||||
required DateTime lastModified,
|
||||
required String postData,
|
||||
Value<int> rowid = const Value.absent(),
|
||||
}) => PostDraftsCompanion.insert(
|
||||
id: id,
|
||||
post: post,
|
||||
title: title,
|
||||
description: description,
|
||||
content: content,
|
||||
visibility: visibility,
|
||||
type: type,
|
||||
lastModified: lastModified,
|
||||
postData: postData,
|
||||
rowid: rowid,
|
||||
),
|
||||
withReferenceMapper:
|
||||
|
||||
@@ -8,7 +8,7 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
@@ -30,7 +30,6 @@ import 'package:shared_preferences/shared_preferences.dart';
|
||||
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
||||
|
||||
@pragma('vm:entry-point')
|
||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||
@@ -52,7 +51,6 @@ void main() async {
|
||||
}
|
||||
|
||||
try {
|
||||
await langdetect.initLangDetect();
|
||||
await EasyLocalization.ensureInitialized();
|
||||
|
||||
if (kIsWeb || !Platform.isLinux) {
|
||||
@@ -169,12 +167,12 @@ class IslandApp extends HookConsumerWidget {
|
||||
final theme = ref.watch(themeProvider);
|
||||
|
||||
void handleMessage(RemoteMessage notification) {
|
||||
if (notification.data['action_uri'] != null) {
|
||||
var uri = notification.data['action_uri'] as String;
|
||||
if (notification.data['meta']?['action_uri'] != null) {
|
||||
var uri = notification.data['meta']['action_uri'] as String;
|
||||
if (uri.startsWith('/')) {
|
||||
// In-app routes
|
||||
final router = ref.read(routerProvider);
|
||||
router.go(notification.data['action_uri']);
|
||||
router.push(notification.data['meta']['action_uri']);
|
||||
} else {
|
||||
// External links
|
||||
launchUrlString(uri);
|
||||
@@ -183,30 +181,9 @@ class IslandApp extends HookConsumerWidget {
|
||||
}
|
||||
|
||||
useEffect(() {
|
||||
if (!kIsWeb && Platform.isLinux) {
|
||||
if (!kIsWeb && (Platform.isLinux || Platform.isWindows)) {
|
||||
return null;
|
||||
}
|
||||
const channel = MethodChannel('dev.solsynth.solian/notifications');
|
||||
|
||||
Future<void> handleInitialLink() async {
|
||||
final String? link = await channel.invokeMethod('initialLink');
|
||||
if (link != null) {
|
||||
final router = ref.read(routerProvider);
|
||||
router.go(link);
|
||||
}
|
||||
}
|
||||
|
||||
if (!kIsWeb && Platform.isAndroid) {
|
||||
handleInitialLink();
|
||||
}
|
||||
|
||||
channel.setMethodCallHandler((call) async {
|
||||
if (call.method == 'newLink') {
|
||||
final String link = call.arguments;
|
||||
final router = ref.read(routerProvider);
|
||||
router.go(link);
|
||||
}
|
||||
});
|
||||
|
||||
// When the app is opened from a terminated state.
|
||||
FirebaseMessaging.instance.getInitialMessage().then((message) {
|
||||
@@ -246,6 +223,7 @@ class IslandApp extends HookConsumerWidget {
|
||||
if (user.value != null) {
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
subscribePushNotification(apiClient);
|
||||
initializeLocalNotifications();
|
||||
final wsNotifier = ref.read(websocketStateProvider.notifier);
|
||||
wsNotifier.connect();
|
||||
}
|
||||
@@ -262,6 +240,7 @@ class IslandApp extends HookConsumerWidget {
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: router,
|
||||
supportedLocales: context.supportedLocales,
|
||||
scrollBehavior: AppScrollBehavior(),
|
||||
localizationsDelegates: [
|
||||
...context.localizationDelegates,
|
||||
CroppyLocalizations.delegate,
|
||||
|
||||
@@ -13,10 +13,13 @@ sealed class SnAccount with _$SnAccount {
|
||||
required String name,
|
||||
required String nick,
|
||||
required String language,
|
||||
@Default("") String region,
|
||||
required bool isSuperuser,
|
||||
required String? automatedId,
|
||||
required SnAccountProfile profile,
|
||||
required SnWalletSubscriptionRef? perkSubscription,
|
||||
@Default([]) List<SnAccountBadge> badges,
|
||||
@Default([]) List<SnContactMethod> contacts,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
@@ -70,6 +73,8 @@ sealed class SnAccountProfile with _$SnAccountProfile {
|
||||
SnAccountBadge? activeBadge,
|
||||
required int experience,
|
||||
required int level,
|
||||
@Default(100) double socialCredits,
|
||||
@Default(0) int socialCreditsLevel,
|
||||
required double levelingProgress,
|
||||
required SnCloudFile? picture,
|
||||
required SnCloudFile? background,
|
||||
@@ -131,6 +136,7 @@ sealed class SnContactMethod with _$SnContactMethod {
|
||||
required int type,
|
||||
required DateTime? verifiedAt,
|
||||
required bool isPrimary,
|
||||
required bool isPublic,
|
||||
required String content,
|
||||
required String accountId,
|
||||
required DateTime createdAt,
|
||||
@@ -208,3 +214,37 @@ sealed class SnAuthDeviceWithChallenge with _$SnAuthDeviceWithChallenge {
|
||||
factory SnAuthDeviceWithChallenge.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnAuthDeviceWithChallengeFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnExperienceRecord with _$SnExperienceRecord {
|
||||
const factory SnExperienceRecord({
|
||||
required String id,
|
||||
required int delta,
|
||||
required String reasonType,
|
||||
required String reason,
|
||||
@Default(1.0) double? bonusMultiplier,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) = _SnExperienceRecord;
|
||||
|
||||
factory SnExperienceRecord.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnExperienceRecordFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnSocialCreditRecord with _$SnSocialCreditRecord {
|
||||
const factory SnSocialCreditRecord({
|
||||
required String id,
|
||||
required double delta,
|
||||
required String reasonType,
|
||||
required String reason,
|
||||
required DateTime? expiredAt,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
}) = _SnSocialCreditRecord;
|
||||
|
||||
factory SnSocialCreditRecord.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnSocialCreditRecordFromJson(json);
|
||||
}
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -11,7 +11,9 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
||||
name: json['name'] as String,
|
||||
nick: json['nick'] as String,
|
||||
language: json['language'] as String,
|
||||
region: json['region'] as String? ?? "",
|
||||
isSuperuser: json['is_superuser'] as bool,
|
||||
automatedId: json['automated_id'] as String?,
|
||||
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
||||
perkSubscription:
|
||||
json['perk_subscription'] == null
|
||||
@@ -24,6 +26,11 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
||||
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
contacts:
|
||||
(json['contacts'] as List<dynamic>?)
|
||||
?.map((e) => SnContactMethod.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
@@ -38,10 +45,13 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
||||
'name': instance.name,
|
||||
'nick': instance.nick,
|
||||
'language': instance.language,
|
||||
'region': instance.region,
|
||||
'is_superuser': instance.isSuperuser,
|
||||
'automated_id': instance.automatedId,
|
||||
'profile': instance.profile.toJson(),
|
||||
'perk_subscription': instance.perkSubscription?.toJson(),
|
||||
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
||||
'contacts': instance.contacts.map((e) => e.toJson()).toList(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
@@ -84,6 +94,8 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
||||
),
|
||||
experience: (json['experience'] as num).toInt(),
|
||||
level: (json['level'] as num).toInt(),
|
||||
socialCredits: (json['social_credits'] as num?)?.toDouble() ?? 100,
|
||||
socialCreditsLevel: (json['social_credits_level'] as num?)?.toInt() ?? 0,
|
||||
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
||||
picture:
|
||||
json['picture'] == null
|
||||
@@ -126,6 +138,8 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
||||
'active_badge': instance.activeBadge?.toJson(),
|
||||
'experience': instance.experience,
|
||||
'level': instance.level,
|
||||
'social_credits': instance.socialCredits,
|
||||
'social_credits_level': instance.socialCreditsLevel,
|
||||
'leveling_progress': instance.levelingProgress,
|
||||
'picture': instance.picture?.toJson(),
|
||||
'background': instance.background?.toJson(),
|
||||
@@ -221,6 +235,7 @@ _SnContactMethod _$SnContactMethodFromJson(Map<String, dynamic> json) =>
|
||||
? null
|
||||
: DateTime.parse(json['verified_at'] as String),
|
||||
isPrimary: json['is_primary'] as bool,
|
||||
isPublic: json['is_public'] as bool,
|
||||
content: json['content'] as String,
|
||||
accountId: json['account_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
@@ -237,6 +252,7 @@ Map<String, dynamic> _$SnContactMethodToJson(_SnContactMethod instance) =>
|
||||
'type': instance.type,
|
||||
'verified_at': instance.verifiedAt?.toIso8601String(),
|
||||
'is_primary': instance.isPrimary,
|
||||
'is_public': instance.isPublic,
|
||||
'content': instance.content,
|
||||
'account_id': instance.accountId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
@@ -348,3 +364,62 @@ Map<String, dynamic> _$SnAuthDeviceWithChallengeeToJson(
|
||||
'challenges': instance.challenges.map((e) => e.toJson()).toList(),
|
||||
'is_current': instance.isCurrent,
|
||||
};
|
||||
|
||||
_SnExperienceRecord _$SnExperienceRecordFromJson(Map<String, dynamic> json) =>
|
||||
_SnExperienceRecord(
|
||||
id: json['id'] as String,
|
||||
delta: (json['delta'] as num).toInt(),
|
||||
reasonType: json['reason_type'] as String,
|
||||
reason: json['reason'] as String,
|
||||
bonusMultiplier: (json['bonus_multiplier'] as num?)?.toDouble() ?? 1.0,
|
||||
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> _$SnExperienceRecordToJson(_SnExperienceRecord instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'delta': instance.delta,
|
||||
'reason_type': instance.reasonType,
|
||||
'reason': instance.reason,
|
||||
'bonus_multiplier': instance.bonusMultiplier,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
_SnSocialCreditRecord _$SnSocialCreditRecordFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _SnSocialCreditRecord(
|
||||
id: json['id'] as String,
|
||||
delta: (json['delta'] as num).toDouble(),
|
||||
reasonType: json['reason_type'] as String,
|
||||
reason: json['reason'] as String,
|
||||
expiredAt:
|
||||
json['expired_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['expired_at'] 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> _$SnSocialCreditRecordToJson(
|
||||
_SnSocialCreditRecord instance,
|
||||
) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'delta': instance.delta,
|
||||
'reason_type': instance.reasonType,
|
||||
'reason': instance.reason,
|
||||
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
@@ -4,6 +4,20 @@ import 'package:island/models/account.dart';
|
||||
part 'activity.freezed.dart';
|
||||
part 'activity.g.dart';
|
||||
|
||||
@freezed
|
||||
sealed class SnNotableDay with _$SnNotableDay {
|
||||
const factory SnNotableDay({
|
||||
required DateTime date,
|
||||
required String localName,
|
||||
required String globalName,
|
||||
required String countryCode,
|
||||
required List<int> holidays,
|
||||
}) = _SnNotableDay;
|
||||
|
||||
factory SnNotableDay.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnNotableDayFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnActivity with _$SnActivity {
|
||||
const factory SnActivity({
|
||||
@@ -54,7 +68,7 @@ sealed class SnEventCalendarEntry with _$SnEventCalendarEntry {
|
||||
const factory SnEventCalendarEntry({
|
||||
required DateTime date,
|
||||
required SnCheckInResult? checkInResult,
|
||||
required List<dynamic> statuses,
|
||||
required List<SnAccountStatus> statuses,
|
||||
}) = _SnEventCalendarEntry;
|
||||
|
||||
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -12,6 +12,281 @@ part of 'activity.dart';
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnNotableDay {
|
||||
|
||||
DateTime get date; String get localName; String get globalName; String get countryCode; List<int> get holidays;
|
||||
/// Create a copy of SnNotableDay
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnNotableDayCopyWith<SnNotableDay> get copyWith => _$SnNotableDayCopyWithImpl<SnNotableDay>(this as SnNotableDay, _$identity);
|
||||
|
||||
/// Serializes this SnNotableDay to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnNotableDay&&(identical(other.date, date) || other.date == date)&&(identical(other.localName, localName) || other.localName == localName)&&(identical(other.globalName, globalName) || other.globalName == globalName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&const DeepCollectionEquality().equals(other.holidays, holidays));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,date,localName,globalName,countryCode,const DeepCollectionEquality().hash(holidays));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnNotableDay(date: $date, localName: $localName, globalName: $globalName, countryCode: $countryCode, holidays: $holidays)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnNotableDayCopyWith<$Res> {
|
||||
factory $SnNotableDayCopyWith(SnNotableDay value, $Res Function(SnNotableDay) _then) = _$SnNotableDayCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
DateTime date, String localName, String globalName, String countryCode, List<int> holidays
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnNotableDayCopyWithImpl<$Res>
|
||||
implements $SnNotableDayCopyWith<$Res> {
|
||||
_$SnNotableDayCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnNotableDay _self;
|
||||
final $Res Function(SnNotableDay) _then;
|
||||
|
||||
/// Create a copy of SnNotableDay
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? localName = null,Object? globalName = null,Object? countryCode = null,Object? holidays = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,localName: null == localName ? _self.localName : localName // ignore: cast_nullable_to_non_nullable
|
||||
as String,globalName: null == globalName ? _self.globalName : globalName // ignore: cast_nullable_to_non_nullable
|
||||
as String,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,holidays: null == holidays ? _self.holidays : holidays // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnNotableDay].
|
||||
extension SnNotableDayPatterns on SnNotableDay {
|
||||
/// 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( _SnNotableDay value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnNotableDay() 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( _SnNotableDay value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnNotableDay():
|
||||
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( _SnNotableDay value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnNotableDay() 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, String localName, String globalName, String countryCode, List<int> holidays)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnNotableDay() when $default != null:
|
||||
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);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, String localName, String globalName, String countryCode, List<int> holidays) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnNotableDay():
|
||||
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);}
|
||||
}
|
||||
/// 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, String localName, String globalName, String countryCode, List<int> holidays)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnNotableDay() when $default != null:
|
||||
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnNotableDay implements SnNotableDay {
|
||||
const _SnNotableDay({required this.date, required this.localName, required this.globalName, required this.countryCode, required final List<int> holidays}): _holidays = holidays;
|
||||
factory _SnNotableDay.fromJson(Map<String, dynamic> json) => _$SnNotableDayFromJson(json);
|
||||
|
||||
@override final DateTime date;
|
||||
@override final String localName;
|
||||
@override final String globalName;
|
||||
@override final String countryCode;
|
||||
final List<int> _holidays;
|
||||
@override List<int> get holidays {
|
||||
if (_holidays is EqualUnmodifiableListView) return _holidays;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_holidays);
|
||||
}
|
||||
|
||||
|
||||
/// Create a copy of SnNotableDay
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnNotableDayCopyWith<_SnNotableDay> get copyWith => __$SnNotableDayCopyWithImpl<_SnNotableDay>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnNotableDayToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnNotableDay&&(identical(other.date, date) || other.date == date)&&(identical(other.localName, localName) || other.localName == localName)&&(identical(other.globalName, globalName) || other.globalName == globalName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&const DeepCollectionEquality().equals(other._holidays, _holidays));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,date,localName,globalName,countryCode,const DeepCollectionEquality().hash(_holidays));
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnNotableDay(date: $date, localName: $localName, globalName: $globalName, countryCode: $countryCode, holidays: $holidays)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnNotableDayCopyWith<$Res> implements $SnNotableDayCopyWith<$Res> {
|
||||
factory _$SnNotableDayCopyWith(_SnNotableDay value, $Res Function(_SnNotableDay) _then) = __$SnNotableDayCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
DateTime date, String localName, String globalName, String countryCode, List<int> holidays
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnNotableDayCopyWithImpl<$Res>
|
||||
implements _$SnNotableDayCopyWith<$Res> {
|
||||
__$SnNotableDayCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnNotableDay _self;
|
||||
final $Res Function(_SnNotableDay) _then;
|
||||
|
||||
/// Create a copy of SnNotableDay
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? date = null,Object? localName = null,Object? globalName = null,Object? countryCode = null,Object? holidays = null,}) {
|
||||
return _then(_SnNotableDay(
|
||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,localName: null == localName ? _self.localName : localName // ignore: cast_nullable_to_non_nullable
|
||||
as String,globalName: null == globalName ? _self.globalName : globalName // ignore: cast_nullable_to_non_nullable
|
||||
as String,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String,holidays: null == holidays ? _self._holidays : holidays // ignore: cast_nullable_to_non_nullable
|
||||
as List<int>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnActivity {
|
||||
|
||||
@@ -861,7 +1136,7 @@ as String,
|
||||
/// @nodoc
|
||||
mixin _$SnEventCalendarEntry {
|
||||
|
||||
DateTime get date; SnCheckInResult? get checkInResult; List<dynamic> get statuses;
|
||||
DateTime get date; SnCheckInResult? get checkInResult; List<SnAccountStatus> get statuses;
|
||||
/// Create a copy of SnEventCalendarEntry
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -894,7 +1169,7 @@ abstract mixin class $SnEventCalendarEntryCopyWith<$Res> {
|
||||
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
||||
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||
});
|
||||
|
||||
|
||||
@@ -916,7 +1191,7 @@ class _$SnEventCalendarEntryCopyWithImpl<$Res>
|
||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,
|
||||
as List<SnAccountStatus>,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnEventCalendarEntry
|
||||
@@ -1010,7 +1285,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnEventCalendarEntry() when $default != null:
|
||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||
@@ -1031,7 +1306,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnEventCalendarEntry():
|
||||
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
||||
@@ -1048,7 +1323,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnEventCalendarEntry() when $default != null:
|
||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||
@@ -1063,13 +1338,13 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnEventCalendarEntry implements SnEventCalendarEntry {
|
||||
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<dynamic> statuses}): _statuses = statuses;
|
||||
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<SnAccountStatus> statuses}): _statuses = statuses;
|
||||
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
|
||||
|
||||
@override final DateTime date;
|
||||
@override final SnCheckInResult? checkInResult;
|
||||
final List<dynamic> _statuses;
|
||||
@override List<dynamic> get statuses {
|
||||
final List<SnAccountStatus> _statuses;
|
||||
@override List<SnAccountStatus> get statuses {
|
||||
if (_statuses is EqualUnmodifiableListView) return _statuses;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_statuses);
|
||||
@@ -1109,7 +1384,7 @@ abstract mixin class _$SnEventCalendarEntryCopyWith<$Res> implements $SnEventCal
|
||||
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
||||
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||
});
|
||||
|
||||
|
||||
@@ -1131,7 +1406,7 @@ class __$SnEventCalendarEntryCopyWithImpl<$Res>
|
||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,
|
||||
as List<SnAccountStatus>,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,27 @@ part of 'activity.dart';
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_SnNotableDay _$SnNotableDayFromJson(Map<String, dynamic> json) =>
|
||||
_SnNotableDay(
|
||||
date: DateTime.parse(json['date'] as String),
|
||||
localName: json['local_name'] as String,
|
||||
globalName: json['global_name'] as String,
|
||||
countryCode: json['country_code'] as String,
|
||||
holidays:
|
||||
(json['holidays'] as List<dynamic>)
|
||||
.map((e) => (e as num).toInt())
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnNotableDayToJson(_SnNotableDay instance) =>
|
||||
<String, dynamic>{
|
||||
'date': instance.date.toIso8601String(),
|
||||
'local_name': instance.localName,
|
||||
'global_name': instance.globalName,
|
||||
'country_code': instance.countryCode,
|
||||
'holidays': instance.holidays,
|
||||
};
|
||||
|
||||
_SnActivity _$SnActivityFromJson(Map<String, dynamic> json) => _SnActivity(
|
||||
id: json['id'] as String,
|
||||
type: json['type'] as String,
|
||||
@@ -87,7 +108,10 @@ _SnEventCalendarEntry _$SnEventCalendarEntryFromJson(
|
||||
: SnCheckInResult.fromJson(
|
||||
json['check_in_result'] as Map<String, dynamic>,
|
||||
),
|
||||
statuses: json['statuses'] as List<dynamic>,
|
||||
statuses:
|
||||
(json['statuses'] as List<dynamic>)
|
||||
.map((e) => SnAccountStatus.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
||||
@@ -95,5 +119,5 @@ Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
||||
) => <String, dynamic>{
|
||||
'date': instance.date.toIso8601String(),
|
||||
'check_in_result': instance.checkInResult?.toJson(),
|
||||
'statuses': instance.statuses,
|
||||
'statuses': instance.statuses.map((e) => e.toJson()).toList(),
|
||||
};
|
||||
|
||||
@@ -11,11 +11,25 @@ sealed class AppToken with _$AppToken {
|
||||
_$AppTokenFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class GeoIpLocation with _$GeoIpLocation {
|
||||
const factory GeoIpLocation({
|
||||
required double? latitude,
|
||||
required double? longitude,
|
||||
required String? countryCode,
|
||||
required String? country,
|
||||
required String? city,
|
||||
}) = _GeoIpLocation;
|
||||
|
||||
factory GeoIpLocation.fromJson(Map<String, dynamic> json) =>
|
||||
_$GeoIpLocationFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnAuthChallenge with _$SnAuthChallenge {
|
||||
const factory SnAuthChallenge({
|
||||
required String id,
|
||||
required DateTime expiredAt,
|
||||
required DateTime? expiredAt,
|
||||
required int stepRemain,
|
||||
required int stepTotal,
|
||||
required int failedAttempts,
|
||||
@@ -26,7 +40,7 @@ sealed class SnAuthChallenge with _$SnAuthChallenge {
|
||||
required String ipAddress,
|
||||
required String userAgent,
|
||||
required String? nonce,
|
||||
required String? location,
|
||||
required GeoIpLocation? location,
|
||||
required String accountId,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
@@ -43,7 +57,7 @@ sealed class SnAuthSession with _$SnAuthSession {
|
||||
required String id,
|
||||
required String? label,
|
||||
required DateTime lastGrantedAt,
|
||||
required DateTime expiredAt,
|
||||
required DateTime? expiredAt,
|
||||
required String accountId,
|
||||
required String challengeId,
|
||||
required SnAuthChallenge challenge,
|
||||
|
||||
@@ -269,10 +269,279 @@ as String,
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$GeoIpLocation {
|
||||
|
||||
double? get latitude; double? get longitude; String? get countryCode; String? get country; String? get city;
|
||||
/// Create a copy of GeoIpLocation
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$GeoIpLocationCopyWith<GeoIpLocation> get copyWith => _$GeoIpLocationCopyWithImpl<GeoIpLocation>(this as GeoIpLocation, _$identity);
|
||||
|
||||
/// Serializes this GeoIpLocation to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is GeoIpLocation&&(identical(other.latitude, latitude) || other.latitude == latitude)&&(identical(other.longitude, longitude) || other.longitude == longitude)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.country, country) || other.country == country)&&(identical(other.city, city) || other.city == city));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,latitude,longitude,countryCode,country,city);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GeoIpLocation(latitude: $latitude, longitude: $longitude, countryCode: $countryCode, country: $country, city: $city)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $GeoIpLocationCopyWith<$Res> {
|
||||
factory $GeoIpLocationCopyWith(GeoIpLocation value, $Res Function(GeoIpLocation) _then) = _$GeoIpLocationCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
double? latitude, double? longitude, String? countryCode, String? country, String? city
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$GeoIpLocationCopyWithImpl<$Res>
|
||||
implements $GeoIpLocationCopyWith<$Res> {
|
||||
_$GeoIpLocationCopyWithImpl(this._self, this._then);
|
||||
|
||||
final GeoIpLocation _self;
|
||||
final $Res Function(GeoIpLocation) _then;
|
||||
|
||||
/// Create a copy of GeoIpLocation
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? latitude = freezed,Object? longitude = freezed,Object? countryCode = freezed,Object? country = freezed,Object? city = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
latitude: freezed == latitude ? _self.latitude : latitude // ignore: cast_nullable_to_non_nullable
|
||||
as double?,longitude: freezed == longitude ? _self.longitude : longitude // ignore: cast_nullable_to_non_nullable
|
||||
as double?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,country: freezed == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String?,city: freezed == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [GeoIpLocation].
|
||||
extension GeoIpLocationPatterns on GeoIpLocation {
|
||||
/// 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( _GeoIpLocation value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GeoIpLocation() 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( _GeoIpLocation value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GeoIpLocation():
|
||||
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( _GeoIpLocation value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _GeoIpLocation() 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( double? latitude, double? longitude, String? countryCode, String? country, String? city)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GeoIpLocation() when $default != null:
|
||||
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);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( double? latitude, double? longitude, String? countryCode, String? country, String? city) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GeoIpLocation():
|
||||
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);}
|
||||
}
|
||||
/// 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( double? latitude, double? longitude, String? countryCode, String? country, String? city)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _GeoIpLocation() when $default != null:
|
||||
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _GeoIpLocation implements GeoIpLocation {
|
||||
const _GeoIpLocation({required this.latitude, required this.longitude, required this.countryCode, required this.country, required this.city});
|
||||
factory _GeoIpLocation.fromJson(Map<String, dynamic> json) => _$GeoIpLocationFromJson(json);
|
||||
|
||||
@override final double? latitude;
|
||||
@override final double? longitude;
|
||||
@override final String? countryCode;
|
||||
@override final String? country;
|
||||
@override final String? city;
|
||||
|
||||
/// Create a copy of GeoIpLocation
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$GeoIpLocationCopyWith<_GeoIpLocation> get copyWith => __$GeoIpLocationCopyWithImpl<_GeoIpLocation>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$GeoIpLocationToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GeoIpLocation&&(identical(other.latitude, latitude) || other.latitude == latitude)&&(identical(other.longitude, longitude) || other.longitude == longitude)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.country, country) || other.country == country)&&(identical(other.city, city) || other.city == city));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,latitude,longitude,countryCode,country,city);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'GeoIpLocation(latitude: $latitude, longitude: $longitude, countryCode: $countryCode, country: $country, city: $city)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$GeoIpLocationCopyWith<$Res> implements $GeoIpLocationCopyWith<$Res> {
|
||||
factory _$GeoIpLocationCopyWith(_GeoIpLocation value, $Res Function(_GeoIpLocation) _then) = __$GeoIpLocationCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
double? latitude, double? longitude, String? countryCode, String? country, String? city
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$GeoIpLocationCopyWithImpl<$Res>
|
||||
implements _$GeoIpLocationCopyWith<$Res> {
|
||||
__$GeoIpLocationCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _GeoIpLocation _self;
|
||||
final $Res Function(_GeoIpLocation) _then;
|
||||
|
||||
/// Create a copy of GeoIpLocation
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? latitude = freezed,Object? longitude = freezed,Object? countryCode = freezed,Object? country = freezed,Object? city = freezed,}) {
|
||||
return _then(_GeoIpLocation(
|
||||
latitude: freezed == latitude ? _self.latitude : latitude // ignore: cast_nullable_to_non_nullable
|
||||
as double?,longitude: freezed == longitude ? _self.longitude : longitude // ignore: cast_nullable_to_non_nullable
|
||||
as double?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||
as String?,country: freezed == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||
as String?,city: freezed == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnAuthChallenge {
|
||||
|
||||
String get id; DateTime get expiredAt; int get stepRemain; int get stepTotal; int get failedAttempts; int get type; List<String> get blacklistFactors; List<dynamic> get audiences; List<dynamic> get scopes; String get ipAddress; String get userAgent; String? get nonce; String? get location; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; DateTime? get expiredAt; int get stepRemain; int get stepTotal; int get failedAttempts; int get type; List<String> get blacklistFactors; List<dynamic> get audiences; List<dynamic> get scopes; String get ipAddress; String get userAgent; String? get nonce; GeoIpLocation? get location; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnAuthChallenge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -305,11 +574,11 @@ abstract mixin class $SnAuthChallengeCopyWith<$Res> {
|
||||
factory $SnAuthChallengeCopyWith(SnAuthChallenge value, $Res Function(SnAuthChallenge) _then) = _$SnAuthChallengeCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
$GeoIpLocationCopyWith<$Res>? get location;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -322,11 +591,11 @@ class _$SnAuthChallengeCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAuthChallenge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? expiredAt = null,Object? stepRemain = null,Object? stepTotal = null,Object? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? expiredAt = freezed,Object? stepRemain = null,Object? stepTotal = null,Object? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = 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,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,stepRemain: null == stepRemain ? _self.stepRemain : stepRemain // ignore: cast_nullable_to_non_nullable
|
||||
as String,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,stepRemain: null == stepRemain ? _self.stepRemain : stepRemain // ignore: cast_nullable_to_non_nullable
|
||||
as int,stepTotal: null == stepTotal ? _self.stepTotal : stepTotal // ignore: cast_nullable_to_non_nullable
|
||||
as int,failedAttempts: null == failedAttempts ? _self.failedAttempts : failedAttempts // ignore: cast_nullable_to_non_nullable
|
||||
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
@@ -337,14 +606,26 @@ as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // i
|
||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as GeoIpLocation?,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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnAuthChallenge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$GeoIpLocationCopyWith<$Res>? get location {
|
||||
if (_self.location == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $GeoIpLocationCopyWith<$Res>(_self.location!, (value) {
|
||||
return _then(_self.copyWith(location: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -423,7 +704,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthChallenge() when $default != null:
|
||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
@@ -444,7 +725,7 @@ return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthChallenge():
|
||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
@@ -461,7 +742,7 @@ return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthChallenge() when $default != null:
|
||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
@@ -480,7 +761,7 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
||||
factory _SnAuthChallenge.fromJson(Map<String, dynamic> json) => _$SnAuthChallengeFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final DateTime expiredAt;
|
||||
@override final DateTime? expiredAt;
|
||||
@override final int stepRemain;
|
||||
@override final int stepTotal;
|
||||
@override final int failedAttempts;
|
||||
@@ -509,7 +790,7 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
||||
@override final String ipAddress;
|
||||
@override final String userAgent;
|
||||
@override final String? nonce;
|
||||
@override final String? location;
|
||||
@override final GeoIpLocation? location;
|
||||
@override final String accountId;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@@ -548,11 +829,11 @@ abstract mixin class _$SnAuthChallengeCopyWith<$Res> implements $SnAuthChallenge
|
||||
factory _$SnAuthChallengeCopyWith(_SnAuthChallenge value, $Res Function(_SnAuthChallenge) _then) = __$SnAuthChallengeCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
@override $GeoIpLocationCopyWith<$Res>? get location;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -565,11 +846,11 @@ class __$SnAuthChallengeCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAuthChallenge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? expiredAt = null,Object? stepRemain = null,Object? stepTotal = null,Object? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? expiredAt = freezed,Object? stepRemain = null,Object? stepTotal = null,Object? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnAuthChallenge(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,stepRemain: null == stepRemain ? _self.stepRemain : stepRemain // ignore: cast_nullable_to_non_nullable
|
||||
as String,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,stepRemain: null == stepRemain ? _self.stepRemain : stepRemain // ignore: cast_nullable_to_non_nullable
|
||||
as int,stepTotal: null == stepTotal ? _self.stepTotal : stepTotal // ignore: cast_nullable_to_non_nullable
|
||||
as int,failedAttempts: null == failedAttempts ? _self.failedAttempts : failedAttempts // ignore: cast_nullable_to_non_nullable
|
||||
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
@@ -580,7 +861,7 @@ as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // i
|
||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as GeoIpLocation?,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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
@@ -588,14 +869,26 @@ as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnAuthChallenge
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$GeoIpLocationCopyWith<$Res>? get location {
|
||||
if (_self.location == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $GeoIpLocationCopyWith<$Res>(_self.location!, (value) {
|
||||
return _then(_self.copyWith(location: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnAuthSession {
|
||||
|
||||
String get id; String? get label; DateTime get lastGrantedAt; DateTime get expiredAt; String get accountId; String get challengeId; SnAuthChallenge get challenge; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; String? get label; DateTime get lastGrantedAt; DateTime? get expiredAt; String get accountId; String get challengeId; SnAuthChallenge get challenge; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnAuthSession
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -628,7 +921,7 @@ abstract mixin class $SnAuthSessionCopyWith<$Res> {
|
||||
factory $SnAuthSessionCopyWith(SnAuthSession value, $Res Function(SnAuthSession) _then) = _$SnAuthSessionCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@@ -645,13 +938,13 @@ class _$SnAuthSessionCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAuthSession
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = null,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = freezed,Object? accountId = null,Object? challengeId = null,Object? challenge = 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,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,lastGrantedAt: null == lastGrantedAt ? _self.lastGrantedAt : lastGrantedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,challengeId: null == challengeId ? _self.challengeId : challengeId // ignore: cast_nullable_to_non_nullable
|
||||
as String,challenge: null == challenge ? _self.challenge : challenge // ignore: cast_nullable_to_non_nullable
|
||||
as SnAuthChallenge,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
@@ -748,7 +1041,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthSession() when $default != null:
|
||||
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
@@ -769,7 +1062,7 @@ return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.a
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthSession():
|
||||
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
@@ -786,7 +1079,7 @@ return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.a
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthSession() when $default != null:
|
||||
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
@@ -807,7 +1100,7 @@ class _SnAuthSession implements SnAuthSession {
|
||||
@override final String id;
|
||||
@override final String? label;
|
||||
@override final DateTime lastGrantedAt;
|
||||
@override final DateTime expiredAt;
|
||||
@override final DateTime? expiredAt;
|
||||
@override final String accountId;
|
||||
@override final String challengeId;
|
||||
@override final SnAuthChallenge challenge;
|
||||
@@ -848,7 +1141,7 @@ abstract mixin class _$SnAuthSessionCopyWith<$Res> implements $SnAuthSessionCopy
|
||||
factory _$SnAuthSessionCopyWith(_SnAuthSession value, $Res Function(_SnAuthSession) _then) = __$SnAuthSessionCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@@ -865,13 +1158,13 @@ class __$SnAuthSessionCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnAuthSession
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = null,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = freezed,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnAuthSession(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String?,lastGrantedAt: null == lastGrantedAt ? _self.lastGrantedAt : lastGrantedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,challengeId: null == challengeId ? _self.challengeId : challengeId // ignore: cast_nullable_to_non_nullable
|
||||
as String,challenge: null == challenge ? _self.challenge : challenge // ignore: cast_nullable_to_non_nullable
|
||||
as SnAuthChallenge,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
|
||||
@@ -13,10 +13,31 @@ Map<String, dynamic> _$AppTokenToJson(_AppToken instance) => <String, dynamic>{
|
||||
'token': instance.token,
|
||||
};
|
||||
|
||||
_GeoIpLocation _$GeoIpLocationFromJson(Map<String, dynamic> json) =>
|
||||
_GeoIpLocation(
|
||||
latitude: (json['latitude'] as num?)?.toDouble(),
|
||||
longitude: (json['longitude'] as num?)?.toDouble(),
|
||||
countryCode: json['country_code'] as String?,
|
||||
country: json['country'] as String?,
|
||||
city: json['city'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$GeoIpLocationToJson(_GeoIpLocation instance) =>
|
||||
<String, dynamic>{
|
||||
'latitude': instance.latitude,
|
||||
'longitude': instance.longitude,
|
||||
'country_code': instance.countryCode,
|
||||
'country': instance.country,
|
||||
'city': instance.city,
|
||||
};
|
||||
|
||||
_SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||
_SnAuthChallenge(
|
||||
id: json['id'] as String,
|
||||
expiredAt: DateTime.parse(json['expired_at'] as String),
|
||||
expiredAt:
|
||||
json['expired_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['expired_at'] as String),
|
||||
stepRemain: (json['step_remain'] as num).toInt(),
|
||||
stepTotal: (json['step_total'] as num).toInt(),
|
||||
failedAttempts: (json['failed_attempts'] as num).toInt(),
|
||||
@@ -30,7 +51,12 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||
ipAddress: json['ip_address'] as String,
|
||||
userAgent: json['user_agent'] as String,
|
||||
nonce: json['nonce'] as String?,
|
||||
location: json['location'] as String?,
|
||||
location:
|
||||
json['location'] == null
|
||||
? null
|
||||
: GeoIpLocation.fromJson(
|
||||
json['location'] as Map<String, dynamic>,
|
||||
),
|
||||
accountId: json['account_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
@@ -43,7 +69,7 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||
Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'expired_at': instance.expiredAt.toIso8601String(),
|
||||
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||
'step_remain': instance.stepRemain,
|
||||
'step_total': instance.stepTotal,
|
||||
'failed_attempts': instance.failedAttempts,
|
||||
@@ -54,7 +80,7 @@ Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
||||
'ip_address': instance.ipAddress,
|
||||
'user_agent': instance.userAgent,
|
||||
'nonce': instance.nonce,
|
||||
'location': instance.location,
|
||||
'location': instance.location?.toJson(),
|
||||
'account_id': instance.accountId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
@@ -66,7 +92,10 @@ _SnAuthSession _$SnAuthSessionFromJson(Map<String, dynamic> json) =>
|
||||
id: json['id'] as String,
|
||||
label: json['label'] as String?,
|
||||
lastGrantedAt: DateTime.parse(json['last_granted_at'] as String),
|
||||
expiredAt: DateTime.parse(json['expired_at'] as String),
|
||||
expiredAt:
|
||||
json['expired_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['expired_at'] as String),
|
||||
accountId: json['account_id'] as String,
|
||||
challengeId: json['challenge_id'] as String,
|
||||
challenge: SnAuthChallenge.fromJson(
|
||||
@@ -85,7 +114,7 @@ Map<String, dynamic> _$SnAuthSessionToJson(_SnAuthSession instance) =>
|
||||
'id': instance.id,
|
||||
'label': instance.label,
|
||||
'last_granted_at': instance.lastGrantedAt.toIso8601String(),
|
||||
'expired_at': instance.expiredAt.toIso8601String(),
|
||||
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||
'account_id': instance.accountId,
|
||||
'challenge_id': instance.challengeId,
|
||||
'challenge': instance.challenge.toJson(),
|
||||
|
||||
63
lib/models/bot.dart
Normal file
63
lib/models/bot.dart
Normal file
@@ -0,0 +1,63 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/models/developer.dart';
|
||||
|
||||
part 'bot.freezed.dart';
|
||||
part 'bot.g.dart';
|
||||
|
||||
@freezed
|
||||
sealed class Bot with _$Bot {
|
||||
const factory Bot({
|
||||
required String id,
|
||||
required String slug,
|
||||
required bool isActive,
|
||||
required String projectId,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required SnAccount account,
|
||||
SnDeveloper? developer,
|
||||
}) = _Bot;
|
||||
|
||||
factory Bot.fromJson(Map<String, dynamic> json) => _$BotFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class BotConfig with _$BotConfig {
|
||||
const factory BotConfig({
|
||||
@Default(false) bool isPublic,
|
||||
@Default(false) bool isInteractive,
|
||||
@Default([]) List<String> allowedRealms,
|
||||
@Default([]) List<String> allowedChatTypes,
|
||||
@Default({}) Map<String, dynamic> metadata,
|
||||
}) = _BotConfig;
|
||||
|
||||
factory BotConfig.fromJson(Map<String, dynamic> json) =>
|
||||
_$BotConfigFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class BotLinks with _$BotLinks {
|
||||
const factory BotLinks({
|
||||
String? website,
|
||||
String? documentation,
|
||||
String? privacyPolicy,
|
||||
String? termsOfService,
|
||||
}) = _BotLinks;
|
||||
|
||||
factory BotLinks.fromJson(Map<String, dynamic> json) =>
|
||||
_$BotLinksFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class BotSecret with _$BotSecret {
|
||||
const factory BotSecret({
|
||||
@Default('') String id,
|
||||
@Default('') String secret,
|
||||
String? description,
|
||||
DateTime? expiredAt,
|
||||
@Default('') String botId,
|
||||
}) = _BotSecret;
|
||||
|
||||
factory BotSecret.fromJson(Map<String, dynamic> json) =>
|
||||
_$BotSecretFromJson(json);
|
||||
}
|
||||
1156
lib/models/bot.freezed.dart
Normal file
1156
lib/models/bot.freezed.dart
Normal file
File diff suppressed because it is too large
Load Diff
91
lib/models/bot.g.dart
Normal file
91
lib/models/bot.g.dart
Normal file
@@ -0,0 +1,91 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'bot.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_Bot _$BotFromJson(Map<String, dynamic> json) => _Bot(
|
||||
id: json['id'] as String,
|
||||
slug: json['slug'] as String,
|
||||
isActive: json['is_active'] as bool,
|
||||
projectId: json['project_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
account: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||
developer:
|
||||
json['developer'] == null
|
||||
? null
|
||||
: SnDeveloper.fromJson(json['developer'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BotToJson(_Bot instance) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'slug': instance.slug,
|
||||
'is_active': instance.isActive,
|
||||
'project_id': instance.projectId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'account': instance.account.toJson(),
|
||||
'developer': instance.developer?.toJson(),
|
||||
};
|
||||
|
||||
_BotConfig _$BotConfigFromJson(Map<String, dynamic> json) => _BotConfig(
|
||||
isPublic: json['is_public'] as bool? ?? false,
|
||||
isInteractive: json['is_interactive'] as bool? ?? false,
|
||||
allowedRealms:
|
||||
(json['allowed_realms'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
const [],
|
||||
allowedChatTypes:
|
||||
(json['allowed_chat_types'] as List<dynamic>?)
|
||||
?.map((e) => e as String)
|
||||
.toList() ??
|
||||
const [],
|
||||
metadata: json['metadata'] as Map<String, dynamic>? ?? const {},
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BotConfigToJson(_BotConfig instance) =>
|
||||
<String, dynamic>{
|
||||
'is_public': instance.isPublic,
|
||||
'is_interactive': instance.isInteractive,
|
||||
'allowed_realms': instance.allowedRealms,
|
||||
'allowed_chat_types': instance.allowedChatTypes,
|
||||
'metadata': instance.metadata,
|
||||
};
|
||||
|
||||
_BotLinks _$BotLinksFromJson(Map<String, dynamic> json) => _BotLinks(
|
||||
website: json['website'] as String?,
|
||||
documentation: json['documentation'] as String?,
|
||||
privacyPolicy: json['privacy_policy'] as String?,
|
||||
termsOfService: json['terms_of_service'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BotLinksToJson(_BotLinks instance) => <String, dynamic>{
|
||||
'website': instance.website,
|
||||
'documentation': instance.documentation,
|
||||
'privacy_policy': instance.privacyPolicy,
|
||||
'terms_of_service': instance.termsOfService,
|
||||
};
|
||||
|
||||
_BotSecret _$BotSecretFromJson(Map<String, dynamic> json) => _BotSecret(
|
||||
id: json['id'] as String? ?? '',
|
||||
secret: json['secret'] as String? ?? '',
|
||||
description: json['description'] as String?,
|
||||
expiredAt:
|
||||
json['expired_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['expired_at'] as String),
|
||||
botId: json['bot_id'] as String? ?? '',
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$BotSecretToJson(_BotSecret instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'secret': instance.secret,
|
||||
'description': instance.description,
|
||||
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||
'bot_id': instance.botId,
|
||||
};
|
||||
20
lib/models/bot_key.dart
Normal file
20
lib/models/bot_key.dart
Normal file
@@ -0,0 +1,20 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'bot_key.freezed.dart';
|
||||
part 'bot_key.g.dart';
|
||||
|
||||
@freezed
|
||||
sealed class SnAccountApiKey with _$SnAccountApiKey {
|
||||
const factory SnAccountApiKey({
|
||||
required String id,
|
||||
required String label,
|
||||
required String accountId,
|
||||
required String sessionId,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
String? key,
|
||||
}) = _SnAccountApiKey;
|
||||
|
||||
factory SnAccountApiKey.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnAccountApiKeyFromJson(json);
|
||||
}
|
||||
289
lib/models/bot_key.freezed.dart
Normal file
289
lib/models/bot_key.freezed.dart
Normal file
@@ -0,0 +1,289 @@
|
||||
// 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 'bot_key.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnAccountApiKey {
|
||||
|
||||
String get id; String get label; String get accountId; String get sessionId; DateTime get createdAt; DateTime get updatedAt; String? get key;
|
||||
/// Create a copy of SnAccountApiKey
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountApiKeyCopyWith<SnAccountApiKey> get copyWith => _$SnAccountApiKeyCopyWithImpl<SnAccountApiKey>(this as SnAccountApiKey, _$identity);
|
||||
|
||||
/// Serializes this SnAccountApiKey to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountApiKey&&(identical(other.id, id) || other.id == id)&&(identical(other.label, label) || other.label == label)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.sessionId, sessionId) || other.sessionId == sessionId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.key, key) || other.key == key));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,label,accountId,sessionId,createdAt,updatedAt,key);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountApiKey(id: $id, label: $label, accountId: $accountId, sessionId: $sessionId, createdAt: $createdAt, updatedAt: $updatedAt, key: $key)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnAccountApiKeyCopyWith<$Res> {
|
||||
factory $SnAccountApiKeyCopyWith(SnAccountApiKey value, $Res Function(SnAccountApiKey) _then) = _$SnAccountApiKeyCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnAccountApiKeyCopyWithImpl<$Res>
|
||||
implements $SnAccountApiKeyCopyWith<$Res> {
|
||||
_$SnAccountApiKeyCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnAccountApiKey _self;
|
||||
final $Res Function(SnAccountApiKey) _then;
|
||||
|
||||
/// Create a copy of SnAccountApiKey
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? label = null,Object? accountId = null,Object? sessionId = null,Object? createdAt = null,Object? updatedAt = null,Object? key = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,sessionId: null == sessionId ? _self.sessionId : sessionId // 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,key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnAccountApiKey].
|
||||
extension SnAccountApiKeyPatterns on SnAccountApiKey {
|
||||
/// 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( _SnAccountApiKey value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountApiKey() 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( _SnAccountApiKey value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountApiKey():
|
||||
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( _SnAccountApiKey value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountApiKey() 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 label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountApiKey() when $default != null:
|
||||
return $default(_that.id,_that.label,_that.accountId,_that.sessionId,_that.createdAt,_that.updatedAt,_that.key);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 label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountApiKey():
|
||||
return $default(_that.id,_that.label,_that.accountId,_that.sessionId,_that.createdAt,_that.updatedAt,_that.key);}
|
||||
}
|
||||
/// 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 label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAccountApiKey() when $default != null:
|
||||
return $default(_that.id,_that.label,_that.accountId,_that.sessionId,_that.createdAt,_that.updatedAt,_that.key);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAccountApiKey implements SnAccountApiKey {
|
||||
const _SnAccountApiKey({required this.id, required this.label, required this.accountId, required this.sessionId, required this.createdAt, required this.updatedAt, this.key});
|
||||
factory _SnAccountApiKey.fromJson(Map<String, dynamic> json) => _$SnAccountApiKeyFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String label;
|
||||
@override final String accountId;
|
||||
@override final String sessionId;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final String? key;
|
||||
|
||||
/// Create a copy of SnAccountApiKey
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnAccountApiKeyCopyWith<_SnAccountApiKey> get copyWith => __$SnAccountApiKeyCopyWithImpl<_SnAccountApiKey>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnAccountApiKeyToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountApiKey&&(identical(other.id, id) || other.id == id)&&(identical(other.label, label) || other.label == label)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.sessionId, sessionId) || other.sessionId == sessionId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.key, key) || other.key == key));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,label,accountId,sessionId,createdAt,updatedAt,key);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAccountApiKey(id: $id, label: $label, accountId: $accountId, sessionId: $sessionId, createdAt: $createdAt, updatedAt: $updatedAt, key: $key)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnAccountApiKeyCopyWith<$Res> implements $SnAccountApiKeyCopyWith<$Res> {
|
||||
factory _$SnAccountApiKeyCopyWith(_SnAccountApiKey value, $Res Function(_SnAccountApiKey) _then) = __$SnAccountApiKeyCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnAccountApiKeyCopyWithImpl<$Res>
|
||||
implements _$SnAccountApiKeyCopyWith<$Res> {
|
||||
__$SnAccountApiKeyCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnAccountApiKey _self;
|
||||
final $Res Function(_SnAccountApiKey) _then;
|
||||
|
||||
/// Create a copy of SnAccountApiKey
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? label = null,Object? accountId = null,Object? sessionId = null,Object? createdAt = null,Object? updatedAt = null,Object? key = freezed,}) {
|
||||
return _then(_SnAccountApiKey(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||
as String,sessionId: null == sessionId ? _self.sessionId : sessionId // 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,key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||
as String?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
29
lib/models/bot_key.g.dart
Normal file
29
lib/models/bot_key.g.dart
Normal file
@@ -0,0 +1,29 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'bot_key.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_SnAccountApiKey _$SnAccountApiKeyFromJson(Map<String, dynamic> json) =>
|
||||
_SnAccountApiKey(
|
||||
id: json['id'] as String,
|
||||
label: json['label'] as String,
|
||||
accountId: json['account_id'] as String,
|
||||
sessionId: json['session_id'] as String,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
key: json['key'] as String?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnAccountApiKeyToJson(_SnAccountApiKey instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'label': instance.label,
|
||||
'account_id': instance.accountId,
|
||||
'session_id': instance.sessionId,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'key': instance.key,
|
||||
};
|
||||
@@ -104,7 +104,7 @@ sealed class SnChatMember with _$SnChatMember {
|
||||
sealed class SnChatSummary with _$SnChatSummary {
|
||||
const factory SnChatSummary({
|
||||
required int unreadCount,
|
||||
required SnChatMessage lastMessage,
|
||||
required SnChatMessage? lastMessage,
|
||||
}) = _SnChatSummary;
|
||||
|
||||
factory SnChatSummary.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -1410,7 +1410,7 @@ $SnAccountStatusCopyWith<$Res>? get status {
|
||||
/// @nodoc
|
||||
mixin _$SnChatSummary {
|
||||
|
||||
int get unreadCount; SnChatMessage get lastMessage;
|
||||
int get unreadCount; SnChatMessage? get lastMessage;
|
||||
/// Create a copy of SnChatSummary
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -1443,11 +1443,11 @@ abstract mixin class $SnChatSummaryCopyWith<$Res> {
|
||||
factory $SnChatSummaryCopyWith(SnChatSummary value, $Res Function(SnChatSummary) _then) = _$SnChatSummaryCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
int unreadCount, SnChatMessage lastMessage
|
||||
int unreadCount, SnChatMessage? lastMessage
|
||||
});
|
||||
|
||||
|
||||
$SnChatMessageCopyWith<$Res> get lastMessage;
|
||||
$SnChatMessageCopyWith<$Res>? get lastMessage;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1460,20 +1460,23 @@ class _$SnChatSummaryCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnChatSummary
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? unreadCount = null,Object? lastMessage = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? unreadCount = null,Object? lastMessage = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
unreadCount: null == unreadCount ? _self.unreadCount : unreadCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,lastMessage: null == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
||||
as SnChatMessage,
|
||||
as int,lastMessage: freezed == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
||||
as SnChatMessage?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnChatSummary
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnChatMessageCopyWith<$Res> get lastMessage {
|
||||
$SnChatMessageCopyWith<$Res>? get lastMessage {
|
||||
if (_self.lastMessage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage, (value) {
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage!, (value) {
|
||||
return _then(_self.copyWith(lastMessage: value));
|
||||
});
|
||||
}
|
||||
@@ -1555,7 +1558,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage lastMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage? lastMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnChatSummary() when $default != null:
|
||||
return $default(_that.unreadCount,_that.lastMessage);case _:
|
||||
@@ -1576,7 +1579,7 @@ return $default(_that.unreadCount,_that.lastMessage);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage lastMessage) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage? lastMessage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnChatSummary():
|
||||
return $default(_that.unreadCount,_that.lastMessage);}
|
||||
@@ -1593,7 +1596,7 @@ return $default(_that.unreadCount,_that.lastMessage);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int unreadCount, SnChatMessage lastMessage)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int unreadCount, SnChatMessage? lastMessage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnChatSummary() when $default != null:
|
||||
return $default(_that.unreadCount,_that.lastMessage);case _:
|
||||
@@ -1612,7 +1615,7 @@ class _SnChatSummary implements SnChatSummary {
|
||||
factory _SnChatSummary.fromJson(Map<String, dynamic> json) => _$SnChatSummaryFromJson(json);
|
||||
|
||||
@override final int unreadCount;
|
||||
@override final SnChatMessage lastMessage;
|
||||
@override final SnChatMessage? lastMessage;
|
||||
|
||||
/// Create a copy of SnChatSummary
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1647,11 +1650,11 @@ abstract mixin class _$SnChatSummaryCopyWith<$Res> implements $SnChatSummaryCopy
|
||||
factory _$SnChatSummaryCopyWith(_SnChatSummary value, $Res Function(_SnChatSummary) _then) = __$SnChatSummaryCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
int unreadCount, SnChatMessage lastMessage
|
||||
int unreadCount, SnChatMessage? lastMessage
|
||||
});
|
||||
|
||||
|
||||
@override $SnChatMessageCopyWith<$Res> get lastMessage;
|
||||
@override $SnChatMessageCopyWith<$Res>? get lastMessage;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1664,11 +1667,11 @@ class __$SnChatSummaryCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnChatSummary
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? unreadCount = null,Object? lastMessage = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? unreadCount = null,Object? lastMessage = freezed,}) {
|
||||
return _then(_SnChatSummary(
|
||||
unreadCount: null == unreadCount ? _self.unreadCount : unreadCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,lastMessage: null == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
||||
as SnChatMessage,
|
||||
as int,lastMessage: freezed == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
||||
as SnChatMessage?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1676,9 +1679,12 @@ as SnChatMessage,
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnChatMessageCopyWith<$Res> get lastMessage {
|
||||
$SnChatMessageCopyWith<$Res>? get lastMessage {
|
||||
if (_self.lastMessage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage, (value) {
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage!, (value) {
|
||||
return _then(_self.copyWith(lastMessage: value));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -213,15 +213,18 @@ Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
||||
_SnChatSummary _$SnChatSummaryFromJson(Map<String, dynamic> json) =>
|
||||
_SnChatSummary(
|
||||
unreadCount: (json['unread_count'] as num).toInt(),
|
||||
lastMessage: SnChatMessage.fromJson(
|
||||
json['last_message'] as Map<String, dynamic>,
|
||||
),
|
||||
lastMessage:
|
||||
json['last_message'] == null
|
||||
? null
|
||||
: SnChatMessage.fromJson(
|
||||
json['last_message'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnChatSummaryToJson(_SnChatSummary instance) =>
|
||||
<String, dynamic>{
|
||||
'unread_count': instance.unreadCount,
|
||||
'last_message': instance.lastMessage.toJson(),
|
||||
'last_message': instance.lastMessage?.toJson(),
|
||||
};
|
||||
|
||||
_MessageChange _$MessageChangeFromJson(Map<String, dynamic> json) =>
|
||||
|
||||
19
lib/models/custom_app_secret.dart
Normal file
19
lib/models/custom_app_secret.dart
Normal file
@@ -0,0 +1,19 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
part 'custom_app_secret.freezed.dart';
|
||||
part 'custom_app_secret.g.dart';
|
||||
|
||||
@freezed
|
||||
sealed class CustomAppSecret with _$CustomAppSecret {
|
||||
const factory CustomAppSecret({
|
||||
required String id,
|
||||
required String? secret,
|
||||
required DateTime createdAt,
|
||||
String? description,
|
||||
int? expiresIn,
|
||||
bool? isOidc,
|
||||
}) = _CustomAppSecret;
|
||||
|
||||
factory CustomAppSecret.fromJson(Map<String, dynamic> json) =>
|
||||
_$CustomAppSecretFromJson(json);
|
||||
}
|
||||
286
lib/models/custom_app_secret.freezed.dart
Normal file
286
lib/models/custom_app_secret.freezed.dart
Normal file
@@ -0,0 +1,286 @@
|
||||
// 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 'custom_app_secret.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// FreezedGenerator
|
||||
// **************************************************************************
|
||||
|
||||
// dart format off
|
||||
T _$identity<T>(T value) => value;
|
||||
|
||||
/// @nodoc
|
||||
mixin _$CustomAppSecret {
|
||||
|
||||
String get id; String? get secret; DateTime get createdAt; String? get description; int? get expiresIn; bool? get isOidc;
|
||||
/// Create a copy of CustomAppSecret
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$CustomAppSecretCopyWith<CustomAppSecret> get copyWith => _$CustomAppSecretCopyWithImpl<CustomAppSecret>(this as CustomAppSecret, _$identity);
|
||||
|
||||
/// Serializes this CustomAppSecret to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is CustomAppSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiresIn, expiresIn) || other.expiresIn == expiresIn)&&(identical(other.isOidc, isOidc) || other.isOidc == isOidc));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,secret,createdAt,description,expiresIn,isOidc);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CustomAppSecret(id: $id, secret: $secret, createdAt: $createdAt, description: $description, expiresIn: $expiresIn, isOidc: $isOidc)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $CustomAppSecretCopyWith<$Res> {
|
||||
factory $CustomAppSecretCopyWith(CustomAppSecret value, $Res Function(CustomAppSecret) _then) = _$CustomAppSecretCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$CustomAppSecretCopyWithImpl<$Res>
|
||||
implements $CustomAppSecretCopyWith<$Res> {
|
||||
_$CustomAppSecretCopyWithImpl(this._self, this._then);
|
||||
|
||||
final CustomAppSecret _self;
|
||||
final $Res Function(CustomAppSecret) _then;
|
||||
|
||||
/// Create a copy of CustomAppSecret
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? secret = freezed,Object? createdAt = null,Object? description = freezed,Object? expiresIn = freezed,Object? isOidc = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,secret: freezed == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,expiresIn: freezed == expiresIn ? _self.expiresIn : expiresIn // ignore: cast_nullable_to_non_nullable
|
||||
as int?,isOidc: freezed == isOidc ? _self.isOidc : isOidc // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [CustomAppSecret].
|
||||
extension CustomAppSecretPatterns on CustomAppSecret {
|
||||
/// 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( _CustomAppSecret value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CustomAppSecret() 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( _CustomAppSecret value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CustomAppSecret():
|
||||
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( _CustomAppSecret value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _CustomAppSecret() 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? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CustomAppSecret() when $default != null:
|
||||
return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);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? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CustomAppSecret():
|
||||
return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);}
|
||||
}
|
||||
/// 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? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _CustomAppSecret() when $default != null:
|
||||
return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _CustomAppSecret implements CustomAppSecret {
|
||||
const _CustomAppSecret({required this.id, required this.secret, required this.createdAt, this.description, this.expiresIn, this.isOidc});
|
||||
factory _CustomAppSecret.fromJson(Map<String, dynamic> json) => _$CustomAppSecretFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final String? secret;
|
||||
@override final DateTime createdAt;
|
||||
@override final String? description;
|
||||
@override final int? expiresIn;
|
||||
@override final bool? isOidc;
|
||||
|
||||
/// Create a copy of CustomAppSecret
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$CustomAppSecretCopyWith<_CustomAppSecret> get copyWith => __$CustomAppSecretCopyWithImpl<_CustomAppSecret>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$CustomAppSecretToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CustomAppSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiresIn, expiresIn) || other.expiresIn == expiresIn)&&(identical(other.isOidc, isOidc) || other.isOidc == isOidc));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,secret,createdAt,description,expiresIn,isOidc);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'CustomAppSecret(id: $id, secret: $secret, createdAt: $createdAt, description: $description, expiresIn: $expiresIn, isOidc: $isOidc)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$CustomAppSecretCopyWith<$Res> implements $CustomAppSecretCopyWith<$Res> {
|
||||
factory _$CustomAppSecretCopyWith(_CustomAppSecret value, $Res Function(_CustomAppSecret) _then) = __$CustomAppSecretCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$CustomAppSecretCopyWithImpl<$Res>
|
||||
implements _$CustomAppSecretCopyWith<$Res> {
|
||||
__$CustomAppSecretCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _CustomAppSecret _self;
|
||||
final $Res Function(_CustomAppSecret) _then;
|
||||
|
||||
/// Create a copy of CustomAppSecret
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? secret = freezed,Object? createdAt = null,Object? description = freezed,Object? expiresIn = freezed,Object? isOidc = freezed,}) {
|
||||
return _then(_CustomAppSecret(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,secret: freezed == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,expiresIn: freezed == expiresIn ? _self.expiresIn : expiresIn // ignore: cast_nullable_to_non_nullable
|
||||
as int?,isOidc: freezed == isOidc ? _self.isOidc : isOidc // ignore: cast_nullable_to_non_nullable
|
||||
as bool?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
27
lib/models/custom_app_secret.g.dart
Normal file
27
lib/models/custom_app_secret.g.dart
Normal file
@@ -0,0 +1,27 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'custom_app_secret.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
// **************************************************************************
|
||||
|
||||
_CustomAppSecret _$CustomAppSecretFromJson(Map<String, dynamic> json) =>
|
||||
_CustomAppSecret(
|
||||
id: json['id'] as String,
|
||||
secret: json['secret'] as String?,
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
description: json['description'] as String?,
|
||||
expiresIn: (json['expires_in'] as num?)?.toInt(),
|
||||
isOidc: json['is_oidc'] as bool?,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$CustomAppSecretToJson(_CustomAppSecret instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'secret': instance.secret,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'description': instance.description,
|
||||
'expires_in': instance.expiresIn,
|
||||
'is_oidc': instance.isOidc,
|
||||
};
|
||||
23
lib/models/dev_project.dart
Normal file
23
lib/models/dev_project.dart
Normal file
@@ -0,0 +1,23 @@
|
||||
|
||||
class DevProject {
|
||||
final String id;
|
||||
final String slug;
|
||||
final String name;
|
||||
final String? description;
|
||||
|
||||
DevProject({
|
||||
required this.id,
|
||||
required this.slug,
|
||||
required this.name,
|
||||
this.description,
|
||||
});
|
||||
|
||||
factory DevProject.fromJson(Map<String, dynamic> json) {
|
||||
return DevProject(
|
||||
id: json['id'],
|
||||
slug: json['slug'],
|
||||
name: json['name'],
|
||||
description: json['description'],
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/models/publisher.dart';
|
||||
|
||||
part 'poll.freezed.dart';
|
||||
@@ -101,6 +102,7 @@ sealed class SnPollAnswer with _$SnPollAnswer {
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
SnAccount? account,
|
||||
}) = _SnPollAnswer;
|
||||
|
||||
factory SnPollAnswer.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -1187,7 +1187,7 @@ as int,
|
||||
/// @nodoc
|
||||
mixin _$SnPollAnswer {
|
||||
|
||||
String get id; Map<String, dynamic> get answer; String get accountId; String get pollId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; Map<String, dynamic> get answer; String get accountId; String get pollId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; SnAccount? get account;
|
||||
/// Create a copy of SnPollAnswer
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -1200,16 +1200,16 @@ $SnPollAnswerCopyWith<SnPollAnswer> get copyWith => _$SnPollAnswerCopyWithImpl<S
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other.answer, answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(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 SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other.answer, answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.account, account) || other.account == account));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(answer),accountId,pollId,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(answer),accountId,pollId,createdAt,updatedAt,deletedAt,account);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, account: $account)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1220,11 +1220,11 @@ abstract mixin class $SnPollAnswerCopyWith<$Res> {
|
||||
factory $SnPollAnswerCopyWith(SnPollAnswer value, $Res Function(SnPollAnswer) _then) = _$SnPollAnswerCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account
|
||||
});
|
||||
|
||||
|
||||
|
||||
$SnAccountCopyWith<$Res>? get account;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1237,7 +1237,7 @@ class _$SnPollAnswerCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPollAnswer
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? account = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,answer: null == answer ? _self.answer : answer // ignore: cast_nullable_to_non_nullable
|
||||
@@ -1246,10 +1246,23 @@ as String,pollId: null == pollId ? _self.pollId : pollId // ignore: cast_nullabl
|
||||
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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
as DateTime?,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnPollAnswer
|
||||
/// 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));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1328,10 +1341,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPollAnswer() when $default != null:
|
||||
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.account);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -1349,10 +1362,10 @@ return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.created
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPollAnswer():
|
||||
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.account);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -1366,10 +1379,10 @@ return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.created
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPollAnswer() when $default != null:
|
||||
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.account);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -1381,7 +1394,7 @@ return $default(_that.id,_that.answer,_that.accountId,_that.pollId,_that.created
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPollAnswer implements SnPollAnswer {
|
||||
const _SnPollAnswer({required this.id, required final Map<String, dynamic> answer, required this.accountId, required this.pollId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _answer = answer;
|
||||
const _SnPollAnswer({required this.id, required final Map<String, dynamic> answer, required this.accountId, required this.pollId, required this.createdAt, required this.updatedAt, required this.deletedAt, this.account}): _answer = answer;
|
||||
factory _SnPollAnswer.fromJson(Map<String, dynamic> json) => _$SnPollAnswerFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -1397,6 +1410,7 @@ class _SnPollAnswer implements SnPollAnswer {
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
@override final SnAccount? account;
|
||||
|
||||
/// Create a copy of SnPollAnswer
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1411,16 +1425,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other._answer, _answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(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 _SnPollAnswer&&(identical(other.id, id) || other.id == id)&&const DeepCollectionEquality().equals(other._answer, _answer)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.pollId, pollId) || other.pollId == pollId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.account, account) || other.account == account));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(_answer),accountId,pollId,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,const DeepCollectionEquality().hash(_answer),accountId,pollId,createdAt,updatedAt,deletedAt,account);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnPollAnswer(id: $id, answer: $answer, accountId: $accountId, pollId: $pollId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, account: $account)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1431,11 +1445,11 @@ abstract mixin class _$SnPollAnswerCopyWith<$Res> implements $SnPollAnswerCopyWi
|
||||
factory _$SnPollAnswerCopyWith(_SnPollAnswer value, $Res Function(_SnPollAnswer) _then) = __$SnPollAnswerCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, Map<String, dynamic> answer, String accountId, String pollId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccount? account
|
||||
});
|
||||
|
||||
|
||||
|
||||
@override $SnAccountCopyWith<$Res>? get account;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1448,7 +1462,7 @@ class __$SnPollAnswerCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPollAnswer
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? answer = null,Object? accountId = null,Object? pollId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? account = freezed,}) {
|
||||
return _then(_SnPollAnswer(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,answer: null == answer ? _self._answer : answer // ignore: cast_nullable_to_non_nullable
|
||||
@@ -1457,11 +1471,24 @@ as String,pollId: null == pollId ? _self.pollId : pollId // ignore: cast_nullabl
|
||||
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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
as DateTime?,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccount?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnPollAnswer
|
||||
/// 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));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
||||
|
||||
@@ -144,6 +144,10 @@ _SnPollAnswer _$SnPollAnswerFromJson(Map<String, dynamic> json) =>
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
account:
|
||||
json['account'] == null
|
||||
? null
|
||||
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPollAnswerToJson(_SnPollAnswer instance) =>
|
||||
@@ -155,4 +159,5 @@ Map<String, dynamic> _$SnPollAnswerToJson(_SnPollAnswer instance) =>
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
'account': instance.account?.toJson(),
|
||||
};
|
||||
|
||||
@@ -22,11 +22,14 @@ sealed class SnPost with _$SnPost {
|
||||
String? slug,
|
||||
@Default(0) int type,
|
||||
Map<String, dynamic>? meta,
|
||||
SnPostEmbedView? embedView,
|
||||
@Default(0) int viewsUnique,
|
||||
@Default(0) int viewsTotal,
|
||||
@Default(0) int upvotes,
|
||||
@Default(0) int downvotes,
|
||||
@Default(0) int repliesCount,
|
||||
@Default(0) int awardedScore,
|
||||
int? pinMode,
|
||||
String? threadedPostId,
|
||||
SnPost? threadedPost,
|
||||
String? repliedPostId,
|
||||
@@ -104,3 +107,38 @@ const Map<String, ReactInfo> kReactionTemplates = {
|
||||
'pray': ReactInfo(icon: '🙏', attitude: 0),
|
||||
'heart': ReactInfo(icon: '❤️', attitude: 0),
|
||||
};
|
||||
|
||||
enum PostEmbedViewRenderer {
|
||||
@JsonValue(0)
|
||||
webView,
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnPostEmbedView with _$SnPostEmbedView {
|
||||
const factory SnPostEmbedView({
|
||||
required String uri,
|
||||
double? aspectRatio,
|
||||
@Default(PostEmbedViewRenderer.webView) PostEmbedViewRenderer renderer,
|
||||
}) = _SnPostEmbedView;
|
||||
|
||||
factory SnPostEmbedView.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnPostEmbedViewFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnPostAward with _$SnPostAward {
|
||||
const factory SnPostAward({
|
||||
required String id,
|
||||
required double amount,
|
||||
required int attitude,
|
||||
String? message,
|
||||
required String postId,
|
||||
required String accountId,
|
||||
@Default(null) DateTime? createdAt,
|
||||
@Default(null) DateTime? updatedAt,
|
||||
DateTime? deletedAt,
|
||||
}) = _SnPostAward;
|
||||
|
||||
factory SnPostAward.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnPostAwardFromJson(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; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
|
||||
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; 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;
|
||||
/// 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.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.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));
|
||||
}
|
||||
|
||||
@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),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),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]);
|
||||
|
||||
@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, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, 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)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,11 +48,11 @@ 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, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, 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
|
||||
});
|
||||
|
||||
|
||||
$SnPostCopyWith<$Res>? get threadedPost;$SnPostCopyWith<$Res>? get repliedPost;$SnPostCopyWith<$Res>? get forwardedPost;$SnRealmCopyWith<$Res>? get realm;$SnPublisherCopyWith<$Res> get publisher;
|
||||
$SnPostEmbedViewCopyWith<$Res>? get embedView;$SnPostCopyWith<$Res>? get threadedPost;$SnPostCopyWith<$Res>? get repliedPost;$SnPostCopyWith<$Res>? get forwardedPost;$SnRealmCopyWith<$Res>? get realm;$SnPublisherCopyWith<$Res> get publisher;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -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? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? 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,}) {
|
||||
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
|
||||
@@ -78,12 +78,15 @@ as int,content: freezed == content ? _self.content : content // ignore: cast_nul
|
||||
as String?,slug: freezed == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as int,meta: freezed == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,embedView: freezed == embedView ? _self.embedView : embedView // ignore: cast_nullable_to_non_nullable
|
||||
as SnPostEmbedView?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||
as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore: cast_nullable_to_non_nullable
|
||||
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
||||
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
|
||||
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as int,awardedScore: null == awardedScore ? _self.awardedScore : awardedScore // ignore: cast_nullable_to_non_nullable
|
||||
as int,pinMode: freezed == pinMode ? _self.pinMode : pinMode // ignore: cast_nullable_to_non_nullable
|
||||
as int?,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
|
||||
as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repliedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
||||
@@ -110,6 +113,18 @@ as bool,
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostEmbedViewCopyWith<$Res>? get embedView {
|
||||
if (_self.embedView == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnPostEmbedViewCopyWith<$Res>(_self.embedView!, (value) {
|
||||
return _then(_self.copyWith(embedView: value));
|
||||
});
|
||||
}/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostCopyWith<$Res>? get threadedPost {
|
||||
if (_self.threadedPost == null) {
|
||||
return null;
|
||||
@@ -242,10 +257,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, 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;
|
||||
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.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.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 orElse();
|
||||
|
||||
}
|
||||
@@ -263,10 +278,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, 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;
|
||||
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.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.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);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -280,10 +295,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, 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;
|
||||
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.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.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 null;
|
||||
|
||||
}
|
||||
@@ -295,7 +310,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.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
||||
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.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;
|
||||
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -317,11 +332,14 @@ class _SnPost implements SnPost {
|
||||
return EqualUnmodifiableMapView(value);
|
||||
}
|
||||
|
||||
@override final SnPostEmbedView? embedView;
|
||||
@override@JsonKey() final int viewsUnique;
|
||||
@override@JsonKey() final int viewsTotal;
|
||||
@override@JsonKey() final int upvotes;
|
||||
@override@JsonKey() final int downvotes;
|
||||
@override@JsonKey() final int repliesCount;
|
||||
@override@JsonKey() final int awardedScore;
|
||||
@override final int? pinMode;
|
||||
@override final String? threadedPostId;
|
||||
@override final SnPost? threadedPost;
|
||||
@override final String? repliedPostId;
|
||||
@@ -398,16 +416,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.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.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));
|
||||
}
|
||||
|
||||
@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),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),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]);
|
||||
|
||||
@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, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, 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)';
|
||||
}
|
||||
|
||||
|
||||
@@ -418,11 +436,11 @@ 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, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, 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
|
||||
});
|
||||
|
||||
|
||||
@override $SnPostCopyWith<$Res>? get threadedPost;@override $SnPostCopyWith<$Res>? get repliedPost;@override $SnPostCopyWith<$Res>? get forwardedPost;@override $SnRealmCopyWith<$Res>? get realm;@override $SnPublisherCopyWith<$Res> get publisher;
|
||||
@override $SnPostEmbedViewCopyWith<$Res>? get embedView;@override $SnPostCopyWith<$Res>? get threadedPost;@override $SnPostCopyWith<$Res>? get repliedPost;@override $SnPostCopyWith<$Res>? get forwardedPost;@override $SnRealmCopyWith<$Res>? get realm;@override $SnPublisherCopyWith<$Res> get publisher;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -435,7 +453,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? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? 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,}) {
|
||||
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
|
||||
@@ -448,12 +466,15 @@ as int,content: freezed == content ? _self.content : content // ignore: cast_nul
|
||||
as String?,slug: freezed == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as int,meta: freezed == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>?,embedView: freezed == embedView ? _self.embedView : embedView // ignore: cast_nullable_to_non_nullable
|
||||
as SnPostEmbedView?,viewsUnique: null == viewsUnique ? _self.viewsUnique : viewsUnique // ignore: cast_nullable_to_non_nullable
|
||||
as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore: cast_nullable_to_non_nullable
|
||||
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
||||
as int,downvotes: null == downvotes ? _self.downvotes : downvotes // ignore: cast_nullable_to_non_nullable
|
||||
as int,repliesCount: null == repliesCount ? _self.repliesCount : repliesCount // ignore: cast_nullable_to_non_nullable
|
||||
as int,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as int,awardedScore: null == awardedScore ? _self.awardedScore : awardedScore // ignore: cast_nullable_to_non_nullable
|
||||
as int,pinMode: freezed == pinMode ? _self.pinMode : pinMode // ignore: cast_nullable_to_non_nullable
|
||||
as int?,threadedPostId: freezed == threadedPostId ? _self.threadedPostId : threadedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,threadedPost: freezed == threadedPost ? _self.threadedPost : threadedPost // ignore: cast_nullable_to_non_nullable
|
||||
as SnPost?,repliedPostId: freezed == repliedPostId ? _self.repliedPostId : repliedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,repliedPost: freezed == repliedPost ? _self.repliedPost : repliedPost // ignore: cast_nullable_to_non_nullable
|
||||
@@ -481,6 +502,18 @@ as bool,
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostEmbedViewCopyWith<$Res>? get embedView {
|
||||
if (_self.embedView == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnPostEmbedViewCopyWith<$Res>(_self.embedView!, (value) {
|
||||
return _then(_self.copyWith(embedView: value));
|
||||
});
|
||||
}/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostCopyWith<$Res>? get threadedPost {
|
||||
if (_self.threadedPost == null) {
|
||||
return null;
|
||||
@@ -1321,6 +1354,550 @@ as int,
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnPostEmbedView {
|
||||
|
||||
String get uri; double? get aspectRatio; PostEmbedViewRenderer get renderer;
|
||||
/// Create a copy of SnPostEmbedView
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostEmbedViewCopyWith<SnPostEmbedView> get copyWith => _$SnPostEmbedViewCopyWithImpl<SnPostEmbedView>(this as SnPostEmbedView, _$identity);
|
||||
|
||||
/// Serializes this SnPostEmbedView to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostEmbedView&&(identical(other.uri, uri) || other.uri == uri)&&(identical(other.aspectRatio, aspectRatio) || other.aspectRatio == aspectRatio)&&(identical(other.renderer, renderer) || other.renderer == renderer));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,uri,aspectRatio,renderer);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostEmbedView(uri: $uri, aspectRatio: $aspectRatio, renderer: $renderer)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnPostEmbedViewCopyWith<$Res> {
|
||||
factory $SnPostEmbedViewCopyWith(SnPostEmbedView value, $Res Function(SnPostEmbedView) _then) = _$SnPostEmbedViewCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String uri, double? aspectRatio, PostEmbedViewRenderer renderer
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnPostEmbedViewCopyWithImpl<$Res>
|
||||
implements $SnPostEmbedViewCopyWith<$Res> {
|
||||
_$SnPostEmbedViewCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnPostEmbedView _self;
|
||||
final $Res Function(SnPostEmbedView) _then;
|
||||
|
||||
/// Create a copy of SnPostEmbedView
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? uri = null,Object? aspectRatio = freezed,Object? renderer = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
uri: null == uri ? _self.uri : uri // ignore: cast_nullable_to_non_nullable
|
||||
as String,aspectRatio: freezed == aspectRatio ? _self.aspectRatio : aspectRatio // ignore: cast_nullable_to_non_nullable
|
||||
as double?,renderer: null == renderer ? _self.renderer : renderer // ignore: cast_nullable_to_non_nullable
|
||||
as PostEmbedViewRenderer,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnPostEmbedView].
|
||||
extension SnPostEmbedViewPatterns on SnPostEmbedView {
|
||||
/// 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( _SnPostEmbedView value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostEmbedView() 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( _SnPostEmbedView value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostEmbedView():
|
||||
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( _SnPostEmbedView value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostEmbedView() 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 uri, double? aspectRatio, PostEmbedViewRenderer renderer)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostEmbedView() when $default != null:
|
||||
return $default(_that.uri,_that.aspectRatio,_that.renderer);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 uri, double? aspectRatio, PostEmbedViewRenderer renderer) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostEmbedView():
|
||||
return $default(_that.uri,_that.aspectRatio,_that.renderer);}
|
||||
}
|
||||
/// 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 uri, double? aspectRatio, PostEmbedViewRenderer renderer)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostEmbedView() when $default != null:
|
||||
return $default(_that.uri,_that.aspectRatio,_that.renderer);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPostEmbedView implements SnPostEmbedView {
|
||||
const _SnPostEmbedView({required this.uri, this.aspectRatio, this.renderer = PostEmbedViewRenderer.webView});
|
||||
factory _SnPostEmbedView.fromJson(Map<String, dynamic> json) => _$SnPostEmbedViewFromJson(json);
|
||||
|
||||
@override final String uri;
|
||||
@override final double? aspectRatio;
|
||||
@override@JsonKey() final PostEmbedViewRenderer renderer;
|
||||
|
||||
/// Create a copy of SnPostEmbedView
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnPostEmbedViewCopyWith<_SnPostEmbedView> get copyWith => __$SnPostEmbedViewCopyWithImpl<_SnPostEmbedView>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnPostEmbedViewToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostEmbedView&&(identical(other.uri, uri) || other.uri == uri)&&(identical(other.aspectRatio, aspectRatio) || other.aspectRatio == aspectRatio)&&(identical(other.renderer, renderer) || other.renderer == renderer));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,uri,aspectRatio,renderer);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostEmbedView(uri: $uri, aspectRatio: $aspectRatio, renderer: $renderer)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnPostEmbedViewCopyWith<$Res> implements $SnPostEmbedViewCopyWith<$Res> {
|
||||
factory _$SnPostEmbedViewCopyWith(_SnPostEmbedView value, $Res Function(_SnPostEmbedView) _then) = __$SnPostEmbedViewCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String uri, double? aspectRatio, PostEmbedViewRenderer renderer
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnPostEmbedViewCopyWithImpl<$Res>
|
||||
implements _$SnPostEmbedViewCopyWith<$Res> {
|
||||
__$SnPostEmbedViewCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnPostEmbedView _self;
|
||||
final $Res Function(_SnPostEmbedView) _then;
|
||||
|
||||
/// Create a copy of SnPostEmbedView
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? uri = null,Object? aspectRatio = freezed,Object? renderer = null,}) {
|
||||
return _then(_SnPostEmbedView(
|
||||
uri: null == uri ? _self.uri : uri // ignore: cast_nullable_to_non_nullable
|
||||
as String,aspectRatio: freezed == aspectRatio ? _self.aspectRatio : aspectRatio // ignore: cast_nullable_to_non_nullable
|
||||
as double?,renderer: null == renderer ? _self.renderer : renderer // ignore: cast_nullable_to_non_nullable
|
||||
as PostEmbedViewRenderer,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnPostAward {
|
||||
|
||||
String get id; double get amount; int get attitude; String? get message; String get postId; String get accountId; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnPostAward
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPostAwardCopyWith<SnPostAward> get copyWith => _$SnPostAwardCopyWithImpl<SnPostAward>(this as SnPostAward, _$identity);
|
||||
|
||||
/// Serializes this SnPostAward to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostAward&&(identical(other.id, id) || other.id == id)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.message, message) || other.message == message)&&(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.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,amount,attitude,message,postId,accountId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostAward(id: $id, amount: $amount, attitude: $attitude, message: $message, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnPostAwardCopyWith<$Res> {
|
||||
factory $SnPostAwardCopyWith(SnPostAward value, $Res Function(SnPostAward) _then) = _$SnPostAwardCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnPostAwardCopyWithImpl<$Res>
|
||||
implements $SnPostAwardCopyWith<$Res> {
|
||||
_$SnPostAwardCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnPostAward _self;
|
||||
final $Res Function(SnPostAward) _then;
|
||||
|
||||
/// Create a copy of SnPostAward
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? amount = null,Object? attitude = null,Object? message = freezed,Object? postId = null,Object? accountId = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
|
||||
as double,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
|
||||
as int,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
||||
as String?,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: 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?,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnPostAward].
|
||||
extension SnPostAwardPatterns on SnPostAward {
|
||||
/// 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( _SnPostAward value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostAward() 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( _SnPostAward value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostAward():
|
||||
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( _SnPostAward value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostAward() 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, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostAward() when $default != null:
|
||||
return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_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, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostAward():
|
||||
return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_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, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostAward() when $default != null:
|
||||
return $default(_that.id,_that.amount,_that.attitude,_that.message,_that.postId,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPostAward implements SnPostAward {
|
||||
const _SnPostAward({required this.id, required this.amount, required this.attitude, this.message, required this.postId, required this.accountId, this.createdAt = null, this.updatedAt = null, this.deletedAt});
|
||||
factory _SnPostAward.fromJson(Map<String, dynamic> json) => _$SnPostAwardFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final double amount;
|
||||
@override final int attitude;
|
||||
@override final String? message;
|
||||
@override final String postId;
|
||||
@override final String accountId;
|
||||
@override@JsonKey() final DateTime? createdAt;
|
||||
@override@JsonKey() final DateTime? updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
|
||||
/// Create a copy of SnPostAward
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnPostAwardCopyWith<_SnPostAward> get copyWith => __$SnPostAwardCopyWithImpl<_SnPostAward>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnPostAwardToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostAward&&(identical(other.id, id) || other.id == id)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.attitude, attitude) || other.attitude == attitude)&&(identical(other.message, message) || other.message == message)&&(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.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,amount,attitude,message,postId,accountId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostAward(id: $id, amount: $amount, attitude: $attitude, message: $message, postId: $postId, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnPostAwardCopyWith<$Res> implements $SnPostAwardCopyWith<$Res> {
|
||||
factory _$SnPostAwardCopyWith(_SnPostAward value, $Res Function(_SnPostAward) _then) = __$SnPostAwardCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, double amount, int attitude, String? message, String postId, String accountId, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnPostAwardCopyWithImpl<$Res>
|
||||
implements _$SnPostAwardCopyWith<$Res> {
|
||||
__$SnPostAwardCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnPostAward _self;
|
||||
final $Res Function(_SnPostAward) _then;
|
||||
|
||||
/// Create a copy of SnPostAward
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? amount = null,Object? attitude = null,Object? message = freezed,Object? postId = null,Object? accountId = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnPostAward(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
|
||||
as double,attitude: null == attitude ? _self.attitude : attitude // ignore: cast_nullable_to_non_nullable
|
||||
as int,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
||||
as String?,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: 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?,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
// dart format on
|
||||
|
||||
@@ -24,11 +24,19 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
slug: json['slug'] as String?,
|
||||
type: (json['type'] as num?)?.toInt() ?? 0,
|
||||
meta: json['meta'] as Map<String, dynamic>?,
|
||||
embedView:
|
||||
json['embed_view'] == null
|
||||
? null
|
||||
: SnPostEmbedView.fromJson(
|
||||
json['embed_view'] as Map<String, dynamic>,
|
||||
),
|
||||
viewsUnique: (json['views_unique'] as num?)?.toInt() ?? 0,
|
||||
viewsTotal: (json['views_total'] as num?)?.toInt() ?? 0,
|
||||
upvotes: (json['upvotes'] as num?)?.toInt() ?? 0,
|
||||
downvotes: (json['downvotes'] as num?)?.toInt() ?? 0,
|
||||
repliesCount: (json['replies_count'] as num?)?.toInt() ?? 0,
|
||||
awardedScore: (json['awarded_score'] as num?)?.toInt() ?? 0,
|
||||
pinMode: (json['pin_mode'] as num?)?.toInt(),
|
||||
threadedPostId: json['threaded_post_id'] as String?,
|
||||
threadedPost:
|
||||
json['threaded_post'] == null
|
||||
@@ -104,11 +112,14 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
||||
'slug': instance.slug,
|
||||
'type': instance.type,
|
||||
'meta': instance.meta,
|
||||
'embed_view': instance.embedView?.toJson(),
|
||||
'views_unique': instance.viewsUnique,
|
||||
'views_total': instance.viewsTotal,
|
||||
'upvotes': instance.upvotes,
|
||||
'downvotes': instance.downvotes,
|
||||
'replies_count': instance.repliesCount,
|
||||
'awarded_score': instance.awardedScore,
|
||||
'pin_mode': instance.pinMode,
|
||||
'threaded_post_id': instance.threadedPostId,
|
||||
'threaded_post': instance.threadedPost?.toJson(),
|
||||
'replied_post_id': instance.repliedPostId,
|
||||
@@ -164,3 +175,58 @@ Map<String, dynamic> _$SnSubscriptionStatusToJson(
|
||||
'publisher_id': instance.publisherId,
|
||||
'publisher_name': instance.publisherName,
|
||||
};
|
||||
|
||||
_SnPostEmbedView _$SnPostEmbedViewFromJson(Map<String, dynamic> json) =>
|
||||
_SnPostEmbedView(
|
||||
uri: json['uri'] as String,
|
||||
aspectRatio: (json['aspect_ratio'] as num?)?.toDouble(),
|
||||
renderer:
|
||||
$enumDecodeNullable(
|
||||
_$PostEmbedViewRendererEnumMap,
|
||||
json['renderer'],
|
||||
) ??
|
||||
PostEmbedViewRenderer.webView,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPostEmbedViewToJson(_SnPostEmbedView instance) =>
|
||||
<String, dynamic>{
|
||||
'uri': instance.uri,
|
||||
'aspect_ratio': instance.aspectRatio,
|
||||
'renderer': _$PostEmbedViewRendererEnumMap[instance.renderer]!,
|
||||
};
|
||||
|
||||
const _$PostEmbedViewRendererEnumMap = {PostEmbedViewRenderer.webView: 0};
|
||||
|
||||
_SnPostAward _$SnPostAwardFromJson(Map<String, dynamic> json) => _SnPostAward(
|
||||
id: json['id'] as String,
|
||||
amount: (json['amount'] as num).toDouble(),
|
||||
attitude: (json['attitude'] as num).toInt(),
|
||||
message: json['message'] as String?,
|
||||
postId: json['post_id'] as String,
|
||||
accountId: json['account_id'] as String,
|
||||
createdAt:
|
||||
json['created_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt:
|
||||
json['updated_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPostAwardToJson(_SnPostAward instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'amount': instance.amount,
|
||||
'attitude': instance.attitude,
|
||||
'message': instance.message,
|
||||
'post_id': instance.postId,
|
||||
'account_id': instance.accountId,
|
||||
'created_at': instance.createdAt?.toIso8601String(),
|
||||
'updated_at': instance.updatedAt?.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/post.dart';
|
||||
import 'package:island/services/text.dart';
|
||||
import 'package:island/utils/text.dart';
|
||||
|
||||
part 'post_category.freezed.dart';
|
||||
part 'post_category.g.dart';
|
||||
@@ -15,6 +15,7 @@ sealed class SnPostCategory with _$SnPostCategory {
|
||||
required String slug,
|
||||
String? name,
|
||||
@Default([]) List<SnPost> posts,
|
||||
@Default(0) int usage,
|
||||
}) = _SnPostCategory;
|
||||
|
||||
factory SnPostCategory.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SnPostCategory {
|
||||
|
||||
String get id; String get slug; String? get name; List<SnPost> get posts;
|
||||
String get id; String get slug; String? get name; List<SnPost> get posts; int get usage;
|
||||
/// Create a copy of SnPostCategory
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -28,16 +28,16 @@ $SnPostCategoryCopyWith<SnPostCategory> get copyWith => _$SnPostCategoryCopyWith
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts));
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts),usage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract mixin class $SnPostCategoryCopyWith<$Res> {
|
||||
factory $SnPostCategoryCopyWith(SnPostCategory value, $Res Function(SnPostCategory) _then) = _$SnPostCategoryCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String slug, String? name, List<SnPost> posts
|
||||
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||
});
|
||||
|
||||
|
||||
@@ -65,13 +65,14 @@ class _$SnPostCategoryCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPostCategory
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||
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,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,posts: null == posts ? _self.posts : posts // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPost>,
|
||||
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -153,10 +154,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostCategory() when $default != null:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -174,10 +175,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostCategory():
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -191,10 +192,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostCategory() when $default != null:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -206,7 +207,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPostCategory extends SnPostCategory {
|
||||
const _SnPostCategory({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts,super._();
|
||||
const _SnPostCategory({required this.id, required this.slug, this.name, final List<SnPost> posts = const [], this.usage = 0}): _posts = posts,super._();
|
||||
factory _SnPostCategory.fromJson(Map<String, dynamic> json) => _$SnPostCategoryFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -219,6 +220,7 @@ class _SnPostCategory extends SnPostCategory {
|
||||
return EqualUnmodifiableListView(_posts);
|
||||
}
|
||||
|
||||
@override@JsonKey() final int usage;
|
||||
|
||||
/// Create a copy of SnPostCategory
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -233,16 +235,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostCategory&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts));
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts),usage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||
return 'SnPostCategory(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +255,7 @@ abstract mixin class _$SnPostCategoryCopyWith<$Res> implements $SnPostCategoryCo
|
||||
factory _$SnPostCategoryCopyWith(_SnPostCategory value, $Res Function(_SnPostCategory) _then) = __$SnPostCategoryCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String slug, String? name, List<SnPost> posts
|
||||
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||
});
|
||||
|
||||
|
||||
@@ -270,13 +272,14 @@ class __$SnPostCategoryCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPostCategory
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||
return _then(_SnPostCategory(
|
||||
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,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,posts: null == posts ? _self._posts : posts // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPost>,
|
||||
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -16,6 +16,7 @@ _SnPostCategory _$SnPostCategoryFromJson(Map<String, dynamic> json) =>
|
||||
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
usage: (json['usage'] as num?)?.toInt() ?? 0,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPostCategoryToJson(_SnPostCategory instance) =>
|
||||
@@ -24,4 +25,5 @@ Map<String, dynamic> _$SnPostCategoryToJson(_SnPostCategory instance) =>
|
||||
'slug': instance.slug,
|
||||
'name': instance.name,
|
||||
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
||||
'usage': instance.usage,
|
||||
};
|
||||
|
||||
@@ -11,6 +11,7 @@ sealed class SnPostTag with _$SnPostTag {
|
||||
required String slug,
|
||||
String? name,
|
||||
@Default([]) List<SnPost> posts,
|
||||
@Default(0) int usage,
|
||||
}) = _SnPostTag;
|
||||
|
||||
factory SnPostTag.fromJson(Map<String, dynamic> json) =>
|
||||
|
||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SnPostTag {
|
||||
|
||||
String get id; String get slug; String? get name; List<SnPost> get posts;
|
||||
String get id; String get slug; String? get name; List<SnPost> get posts; int get usage;
|
||||
/// Create a copy of SnPostTag
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -28,16 +28,16 @@ $SnPostTagCopyWith<SnPostTag> get copyWith => _$SnPostTagCopyWithImpl<SnPostTag>
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other.posts, posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts));
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(posts),usage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,7 +48,7 @@ abstract mixin class $SnPostTagCopyWith<$Res> {
|
||||
factory $SnPostTagCopyWith(SnPostTag value, $Res Function(SnPostTag) _then) = _$SnPostTagCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, String slug, String? name, List<SnPost> posts
|
||||
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||
});
|
||||
|
||||
|
||||
@@ -65,13 +65,14 @@ class _$SnPostTagCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPostTag
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||
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,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,posts: null == posts ? _self.posts : posts // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPost>,
|
||||
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -153,10 +154,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostTag() when $default != null:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -174,10 +175,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String slug, String? name, List<SnPost> posts, int usage) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostTag():
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -191,10 +192,10 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String slug, String? name, List<SnPost> posts, int usage)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPostTag() when $default != null:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
return $default(_that.id,_that.slug,_that.name,_that.posts,_that.usage);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -206,7 +207,7 @@ return $default(_that.id,_that.slug,_that.name,_that.posts);case _:
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPostTag implements SnPostTag {
|
||||
const _SnPostTag({required this.id, required this.slug, this.name, final List<SnPost> posts = const []}): _posts = posts;
|
||||
const _SnPostTag({required this.id, required this.slug, this.name, final List<SnPost> posts = const [], this.usage = 0}): _posts = posts;
|
||||
factory _SnPostTag.fromJson(Map<String, dynamic> json) => _$SnPostTagFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -219,6 +220,7 @@ class _SnPostTag implements SnPostTag {
|
||||
return EqualUnmodifiableListView(_posts);
|
||||
}
|
||||
|
||||
@override@JsonKey() final int usage;
|
||||
|
||||
/// Create a copy of SnPostTag
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -233,16 +235,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPostTag&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&const DeepCollectionEquality().equals(other._posts, _posts)&&(identical(other.usage, usage) || other.usage == usage));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts));
|
||||
int get hashCode => Object.hash(runtimeType,id,slug,name,const DeepCollectionEquality().hash(_posts),usage);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts)';
|
||||
return 'SnPostTag(id: $id, slug: $slug, name: $name, posts: $posts, usage: $usage)';
|
||||
}
|
||||
|
||||
|
||||
@@ -253,7 +255,7 @@ abstract mixin class _$SnPostTagCopyWith<$Res> implements $SnPostTagCopyWith<$Re
|
||||
factory _$SnPostTagCopyWith(_SnPostTag value, $Res Function(_SnPostTag) _then) = __$SnPostTagCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, String slug, String? name, List<SnPost> posts
|
||||
String id, String slug, String? name, List<SnPost> posts, int usage
|
||||
});
|
||||
|
||||
|
||||
@@ -270,13 +272,14 @@ class __$SnPostTagCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnPostTag
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = freezed,Object? posts = null,Object? usage = null,}) {
|
||||
return _then(_SnPostTag(
|
||||
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,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||
as String?,posts: null == posts ? _self._posts : posts // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnPost>,
|
||||
as List<SnPost>,usage: null == usage ? _self.usage : usage // ignore: cast_nullable_to_non_nullable
|
||||
as int,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ _SnPostTag _$SnPostTagFromJson(Map<String, dynamic> json) => _SnPostTag(
|
||||
?.map((e) => SnPost.fromJson(e as Map<String, dynamic>))
|
||||
.toList() ??
|
||||
const [],
|
||||
usage: (json['usage'] as num?)?.toInt() ?? 0,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnPostTagToJson(_SnPostTag instance) =>
|
||||
@@ -23,4 +24,5 @@ Map<String, dynamic> _$SnPostTagToJson(_SnPostTag instance) =>
|
||||
'slug': instance.slug,
|
||||
'name': instance.name,
|
||||
'posts': instance.posts.map((e) => e.toJson()).toList(),
|
||||
'usage': instance.usage,
|
||||
};
|
||||
|
||||
@@ -108,17 +108,14 @@ sealed class SnWalletOrder with _$SnWalletOrder {
|
||||
required String id,
|
||||
required int status,
|
||||
required String currency,
|
||||
required dynamic remarks,
|
||||
required String? remarks,
|
||||
required String appIdentifier,
|
||||
@Default({}) Map<String, dynamic> meta,
|
||||
required int amount,
|
||||
required DateTime expiredAt,
|
||||
required String? payeeWalletId,
|
||||
required SnWallet? payeeWallet,
|
||||
required String? transactionId,
|
||||
required SnTransaction? transaction,
|
||||
required String? issuerAppId,
|
||||
required dynamic issuerApp,
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
|
||||
@@ -1554,7 +1554,7 @@ as String,
|
||||
/// @nodoc
|
||||
mixin _$SnWalletOrder {
|
||||
|
||||
String get id; int get status; String get currency; dynamic get remarks; String get appIdentifier; Map<String, dynamic> get meta; int get amount; DateTime get expiredAt; String? get payeeWalletId; SnWallet? get payeeWallet; String? get transactionId; SnTransaction? get transaction; String? get issuerAppId; dynamic get issuerApp; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get id; int get status; String get currency; String? get remarks; String get appIdentifier; Map<String, dynamic> get meta; int get amount; DateTime get expiredAt; String? get payeeWalletId; String? get transactionId; String? get issuerAppId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
/// Create a copy of SnWalletOrder
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -1567,16 +1567,16 @@ $SnWalletOrderCopyWith<SnWalletOrder> get copyWith => _$SnWalletOrderCopyWithImp
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&const DeepCollectionEquality().equals(other.remarks, remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.payeeWallet, payeeWallet) || other.payeeWallet == payeeWallet)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.transaction, transaction) || other.transaction == transaction)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&const DeepCollectionEquality().equals(other.issuerApp, issuerApp)&&(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 SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.remarks, remarks) || other.remarks == remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&(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,status,currency,const DeepCollectionEquality().hash(remarks),appIdentifier,const DeepCollectionEquality().hash(meta),amount,expiredAt,payeeWalletId,payeeWallet,transactionId,transaction,issuerAppId,const DeepCollectionEquality().hash(issuerApp),createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,status,currency,remarks,appIdentifier,const DeepCollectionEquality().hash(meta),amount,expiredAt,payeeWalletId,transactionId,issuerAppId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, transactionId: $transactionId, transaction: $transaction, issuerAppId: $issuerAppId, issuerApp: $issuerApp, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, transactionId: $transactionId, issuerAppId: $issuerAppId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1587,11 +1587,11 @@ abstract mixin class $SnWalletOrderCopyWith<$Res> {
|
||||
factory $SnWalletOrderCopyWith(SnWalletOrder value, $Res Function(SnWalletOrder) _then) = _$SnWalletOrderCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
$SnWalletCopyWith<$Res>? get payeeWallet;$SnTransactionCopyWith<$Res>? get transaction;
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1604,53 +1604,26 @@ class _$SnWalletOrderCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnWalletOrder
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? payeeWallet = freezed,Object? transactionId = freezed,Object? transaction = freezed,Object? issuerAppId = freezed,Object? issuerApp = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? transactionId = freezed,Object? issuerAppId = 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,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as int,currency: null == currency ? _self.currency : currency // ignore: cast_nullable_to_non_nullable
|
||||
as String,remarks: freezed == remarks ? _self.remarks : remarks // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
|
||||
as String?,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
|
||||
as String,meta: null == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
|
||||
as int,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,payeeWalletId: freezed == payeeWalletId ? _self.payeeWalletId : payeeWalletId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,payeeWallet: freezed == payeeWallet ? _self.payeeWallet : payeeWallet // ignore: cast_nullable_to_non_nullable
|
||||
as SnWallet?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,transaction: freezed == transaction ? _self.transaction : transaction // ignore: cast_nullable_to_non_nullable
|
||||
as SnTransaction?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,issuerApp: freezed == issuerApp ? _self.issuerApp : issuerApp // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as String?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // 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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnWalletOrder
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnWalletCopyWith<$Res>? get payeeWallet {
|
||||
if (_self.payeeWallet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnWalletCopyWith<$Res>(_self.payeeWallet!, (value) {
|
||||
return _then(_self.copyWith(payeeWallet: value));
|
||||
});
|
||||
}/// Create a copy of SnWalletOrder
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnTransactionCopyWith<$Res>? get transaction {
|
||||
if (_self.transaction == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnTransactionCopyWith<$Res>(_self.transaction!, (value) {
|
||||
return _then(_self.copyWith(transaction: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1729,10 +1702,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnWalletOrder() when $default != null:
|
||||
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.payeeWallet,_that.transactionId,_that.transaction,_that.issuerAppId,_that.issuerApp,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.transactionId,_that.issuerAppId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -1750,10 +1723,10 @@ return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIden
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnWalletOrder():
|
||||
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.payeeWallet,_that.transactionId,_that.transaction,_that.issuerAppId,_that.issuerApp,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.transactionId,_that.issuerAppId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -1767,10 +1740,10 @@ return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIden
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnWalletOrder() when $default != null:
|
||||
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.payeeWallet,_that.transactionId,_that.transaction,_that.issuerAppId,_that.issuerApp,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIdentifier,_that.meta,_that.amount,_that.expiredAt,_that.payeeWalletId,_that.transactionId,_that.issuerAppId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -1782,13 +1755,13 @@ return $default(_that.id,_that.status,_that.currency,_that.remarks,_that.appIden
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnWalletOrder implements SnWalletOrder {
|
||||
const _SnWalletOrder({required this.id, required this.status, required this.currency, required this.remarks, required this.appIdentifier, final Map<String, dynamic> meta = const {}, required this.amount, required this.expiredAt, required this.payeeWalletId, required this.payeeWallet, required this.transactionId, required this.transaction, required this.issuerAppId, required this.issuerApp, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta;
|
||||
const _SnWalletOrder({required this.id, required this.status, required this.currency, required this.remarks, required this.appIdentifier, final Map<String, dynamic> meta = const {}, required this.amount, required this.expiredAt, required this.payeeWalletId, required this.transactionId, required this.issuerAppId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _meta = meta;
|
||||
factory _SnWalletOrder.fromJson(Map<String, dynamic> json) => _$SnWalletOrderFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@override final int status;
|
||||
@override final String currency;
|
||||
@override final dynamic remarks;
|
||||
@override final String? remarks;
|
||||
@override final String appIdentifier;
|
||||
final Map<String, dynamic> _meta;
|
||||
@override@JsonKey() Map<String, dynamic> get meta {
|
||||
@@ -1800,11 +1773,8 @@ class _SnWalletOrder implements SnWalletOrder {
|
||||
@override final int amount;
|
||||
@override final DateTime expiredAt;
|
||||
@override final String? payeeWalletId;
|
||||
@override final SnWallet? payeeWallet;
|
||||
@override final String? transactionId;
|
||||
@override final SnTransaction? transaction;
|
||||
@override final String? issuerAppId;
|
||||
@override final dynamic issuerApp;
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
@@ -1822,16 +1792,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&const DeepCollectionEquality().equals(other.remarks, remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.payeeWallet, payeeWallet) || other.payeeWallet == payeeWallet)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.transaction, transaction) || other.transaction == transaction)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&const DeepCollectionEquality().equals(other.issuerApp, issuerApp)&&(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 _SnWalletOrder&&(identical(other.id, id) || other.id == id)&&(identical(other.status, status) || other.status == status)&&(identical(other.currency, currency) || other.currency == currency)&&(identical(other.remarks, remarks) || other.remarks == remarks)&&(identical(other.appIdentifier, appIdentifier) || other.appIdentifier == appIdentifier)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.amount, amount) || other.amount == amount)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.payeeWalletId, payeeWalletId) || other.payeeWalletId == payeeWalletId)&&(identical(other.transactionId, transactionId) || other.transactionId == transactionId)&&(identical(other.issuerAppId, issuerAppId) || other.issuerAppId == issuerAppId)&&(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,status,currency,const DeepCollectionEquality().hash(remarks),appIdentifier,const DeepCollectionEquality().hash(_meta),amount,expiredAt,payeeWalletId,payeeWallet,transactionId,transaction,issuerAppId,const DeepCollectionEquality().hash(issuerApp),createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,id,status,currency,remarks,appIdentifier,const DeepCollectionEquality().hash(_meta),amount,expiredAt,payeeWalletId,transactionId,issuerAppId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, payeeWallet: $payeeWallet, transactionId: $transactionId, transaction: $transaction, issuerAppId: $issuerAppId, issuerApp: $issuerApp, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnWalletOrder(id: $id, status: $status, currency: $currency, remarks: $remarks, appIdentifier: $appIdentifier, meta: $meta, amount: $amount, expiredAt: $expiredAt, payeeWalletId: $payeeWalletId, transactionId: $transactionId, issuerAppId: $issuerAppId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1842,11 +1812,11 @@ abstract mixin class _$SnWalletOrderCopyWith<$Res> implements $SnWalletOrderCopy
|
||||
factory _$SnWalletOrderCopyWith(_SnWalletOrder value, $Res Function(_SnWalletOrder) _then) = __$SnWalletOrderCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String id, int status, String currency, dynamic remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, SnWallet? payeeWallet, String? transactionId, SnTransaction? transaction, String? issuerAppId, dynamic issuerApp, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String id, int status, String currency, String? remarks, String appIdentifier, Map<String, dynamic> meta, int amount, DateTime expiredAt, String? payeeWalletId, String? transactionId, String? issuerAppId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@override $SnWalletCopyWith<$Res>? get payeeWallet;@override $SnTransactionCopyWith<$Res>? get transaction;
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1859,54 +1829,27 @@ class __$SnWalletOrderCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnWalletOrder
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? payeeWallet = freezed,Object? transactionId = freezed,Object? transaction = freezed,Object? issuerAppId = freezed,Object? issuerApp = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? status = null,Object? currency = null,Object? remarks = freezed,Object? appIdentifier = null,Object? meta = null,Object? amount = null,Object? expiredAt = null,Object? payeeWalletId = freezed,Object? transactionId = freezed,Object? issuerAppId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
return _then(_SnWalletOrder(
|
||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||
as String,status: null == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as int,currency: null == currency ? _self.currency : currency // ignore: cast_nullable_to_non_nullable
|
||||
as String,remarks: freezed == remarks ? _self.remarks : remarks // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
|
||||
as String?,appIdentifier: null == appIdentifier ? _self.appIdentifier : appIdentifier // ignore: cast_nullable_to_non_nullable
|
||||
as String,meta: null == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, dynamic>,amount: null == amount ? _self.amount : amount // ignore: cast_nullable_to_non_nullable
|
||||
as int,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime,payeeWalletId: freezed == payeeWalletId ? _self.payeeWalletId : payeeWalletId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,payeeWallet: freezed == payeeWallet ? _self.payeeWallet : payeeWallet // ignore: cast_nullable_to_non_nullable
|
||||
as SnWallet?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,transaction: freezed == transaction ? _self.transaction : transaction // ignore: cast_nullable_to_non_nullable
|
||||
as SnTransaction?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,issuerApp: freezed == issuerApp ? _self.issuerApp : issuerApp // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||
as String?,transactionId: freezed == transactionId ? _self.transactionId : transactionId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,issuerAppId: freezed == issuerAppId ? _self.issuerAppId : issuerAppId // 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,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
|
||||
/// Create a copy of SnWalletOrder
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnWalletCopyWith<$Res>? get payeeWallet {
|
||||
if (_self.payeeWallet == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnWalletCopyWith<$Res>(_self.payeeWallet!, (value) {
|
||||
return _then(_self.copyWith(payeeWallet: value));
|
||||
});
|
||||
}/// Create a copy of SnWalletOrder
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnTransactionCopyWith<$Res>? get transaction {
|
||||
if (_self.transaction == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnTransactionCopyWith<$Res>(_self.transaction!, (value) {
|
||||
return _then(_self.copyWith(transaction: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// dart format on
|
||||
|
||||
@@ -195,25 +195,14 @@ _SnWalletOrder _$SnWalletOrderFromJson(Map<String, dynamic> json) =>
|
||||
id: json['id'] as String,
|
||||
status: (json['status'] as num).toInt(),
|
||||
currency: json['currency'] as String,
|
||||
remarks: json['remarks'],
|
||||
remarks: json['remarks'] as String?,
|
||||
appIdentifier: json['app_identifier'] as String,
|
||||
meta: json['meta'] as Map<String, dynamic>? ?? const {},
|
||||
amount: (json['amount'] as num).toInt(),
|
||||
expiredAt: DateTime.parse(json['expired_at'] as String),
|
||||
payeeWalletId: json['payee_wallet_id'] as String?,
|
||||
payeeWallet:
|
||||
json['payee_wallet'] == null
|
||||
? null
|
||||
: SnWallet.fromJson(json['payee_wallet'] as Map<String, dynamic>),
|
||||
transactionId: json['transaction_id'] as String?,
|
||||
transaction:
|
||||
json['transaction'] == null
|
||||
? null
|
||||
: SnTransaction.fromJson(
|
||||
json['transaction'] as Map<String, dynamic>,
|
||||
),
|
||||
issuerAppId: json['issuer_app_id'] as String?,
|
||||
issuerApp: json['issuer_app'],
|
||||
createdAt: DateTime.parse(json['created_at'] as String),
|
||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||
deletedAt:
|
||||
@@ -233,11 +222,8 @@ Map<String, dynamic> _$SnWalletOrderToJson(_SnWalletOrder instance) =>
|
||||
'amount': instance.amount,
|
||||
'expired_at': instance.expiredAt.toIso8601String(),
|
||||
'payee_wallet_id': instance.payeeWalletId,
|
||||
'payee_wallet': instance.payeeWallet?.toJson(),
|
||||
'transaction_id': instance.transactionId,
|
||||
'transaction': instance.transaction?.toJson(),
|
||||
'issuer_app_id': instance.issuerAppId,
|
||||
'issuer_app': instance.issuerApp,
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
|
||||
456
lib/pods/activity/activity_rpc.dart
Normal file
456
lib/pods/activity/activity_rpc.dart
Normal file
@@ -0,0 +1,456 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer' as developer;
|
||||
import 'dart:io';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:shelf/shelf.dart';
|
||||
import 'package:shelf/shelf_io.dart' as shelf_io;
|
||||
import 'package:shelf_web_socket/shelf_web_socket.dart';
|
||||
import 'package:web_socket_channel/web_socket_channel.dart';
|
||||
|
||||
// Conditional imports for IPC server - use web stubs on web platform
|
||||
import 'ipc_server.dart' if (dart.library.html) 'ipc_server.web.dart';
|
||||
|
||||
const String kRpcLogPrefix = 'arRPC.websocket';
|
||||
const String kRpcIpcLogPrefix = 'arRPC.ipc';
|
||||
|
||||
// IPC Constants
|
||||
const String kIpcBasePath = 'discord-ipc';
|
||||
|
||||
// IPC Packet Types
|
||||
class IpcTypes {
|
||||
static const int handshake = 0;
|
||||
static const int frame = 1;
|
||||
static const int close = 2;
|
||||
static const int ping = 3;
|
||||
static const int pong = 4;
|
||||
}
|
||||
|
||||
// IPC Close Codes
|
||||
class IpcCloseCodes {
|
||||
static const int closeNormal = 1000;
|
||||
static const int closeUnsupported = 1003;
|
||||
static const int closeAbnormal = 1006;
|
||||
}
|
||||
|
||||
// IPC Error Codes
|
||||
class IpcErrorCodes {
|
||||
static const int invalidClientId = 4000;
|
||||
static const int invalidOrigin = 4001;
|
||||
static const int rateLimited = 4002;
|
||||
static const int tokenRevoked = 4003;
|
||||
static const int invalidVersion = 4004;
|
||||
static const int invalidEncoding = 4005;
|
||||
}
|
||||
|
||||
// Reference https://github.com/OpenAsar/arrpc/blob/main/src/transports/ipc.js
|
||||
class ActivityRpcServer {
|
||||
static const List<int> portRange = [6463, 6472]; // Ports 6463–6472
|
||||
Map<String, Function>
|
||||
handlers; // {connection: (socket), message: (socket, data), close: (socket)}
|
||||
HttpServer? _httpServer;
|
||||
IpcServer? _ipcServer;
|
||||
final List<WebSocketChannel> _wsSockets = [];
|
||||
|
||||
ActivityRpcServer(this.handlers);
|
||||
|
||||
void updateHandlers(Map<String, Function> newHandlers) {
|
||||
handlers = newHandlers;
|
||||
}
|
||||
|
||||
// Start the server
|
||||
Future<void> start() async {
|
||||
int port = portRange[0];
|
||||
bool wsSuccess = false;
|
||||
|
||||
// Start WebSocket server
|
||||
while (port <= portRange[1]) {
|
||||
developer.log('Trying port $port', name: kRpcLogPrefix);
|
||||
try {
|
||||
_httpServer = await HttpServer.bind(InternetAddress.loopbackIPv4, port);
|
||||
developer.log('Listening on $port', name: kRpcLogPrefix);
|
||||
|
||||
shelf_io.serveRequests(_httpServer!, (Request request) async {
|
||||
developer.log('New request', name: kRpcLogPrefix);
|
||||
if (request.headers['upgrade']?.toLowerCase() == 'websocket') {
|
||||
final handler = webSocketHandler((WebSocketChannel channel, _) {
|
||||
_wsSockets.add(channel);
|
||||
_onWsConnection(channel, request);
|
||||
});
|
||||
return handler(request);
|
||||
}
|
||||
developer.log(
|
||||
'New request disposed due to not websocket',
|
||||
name: kRpcLogPrefix,
|
||||
);
|
||||
return Response.notFound('Not a WebSocket request');
|
||||
});
|
||||
wsSuccess = true;
|
||||
break;
|
||||
} catch (e) {
|
||||
if (e is SocketException && e.osError?.errorCode == 98) {
|
||||
developer.log('$port in use!', name: kRpcLogPrefix);
|
||||
} else {
|
||||
developer.log('HTTP error: $e', name: kRpcLogPrefix);
|
||||
}
|
||||
port++;
|
||||
await Future.delayed(Duration(milliseconds: 100)); // Add delay
|
||||
}
|
||||
}
|
||||
|
||||
if (!wsSuccess) {
|
||||
throw Exception(
|
||||
'Failed to bind to any port in range ${portRange[0]}–${portRange[1]}',
|
||||
);
|
||||
}
|
||||
|
||||
// Start IPC server
|
||||
final shouldStartIpc = !Platform.isMacOS && !kIsWeb;
|
||||
if (shouldStartIpc) {
|
||||
try {
|
||||
_ipcServer = MultiPlatformIpcServer();
|
||||
|
||||
// Set up IPC handlers
|
||||
_ipcServer!.handlePacket = (socket, packet, _) {
|
||||
_handleIpcPacket(socket, packet);
|
||||
};
|
||||
|
||||
await _ipcServer!.start();
|
||||
} catch (e) {
|
||||
developer.log('IPC server error: $e', name: kRpcIpcLogPrefix);
|
||||
}
|
||||
} else {
|
||||
developer.log(
|
||||
'IPC server disabled on macOS or web in production mode',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Stop the server
|
||||
Future<void> stop() async {
|
||||
// Stop WebSocket server
|
||||
for (var socket in _wsSockets) {
|
||||
try {
|
||||
await socket.sink.close();
|
||||
} catch (e) {
|
||||
developer.log('Error closing WebSocket: $e', name: kRpcLogPrefix);
|
||||
}
|
||||
}
|
||||
_wsSockets.clear();
|
||||
await _httpServer?.close(force: true);
|
||||
|
||||
// Stop IPC server
|
||||
await _ipcServer?.stop();
|
||||
|
||||
developer.log('Servers stopped', name: kRpcLogPrefix);
|
||||
}
|
||||
|
||||
// Handle new WebSocket connection
|
||||
void _onWsConnection(WebSocketChannel socket, Request request) {
|
||||
final uri = request.url;
|
||||
final params = uri.queryParameters;
|
||||
final ver = int.tryParse(params['v'] ?? '1') ?? 1;
|
||||
final encoding = params['encoding'] ?? 'json';
|
||||
final clientId = params['client_id'] ?? '';
|
||||
final origin = request.headers['origin'] ?? '';
|
||||
|
||||
developer.log(
|
||||
'New WS connection! origin: $origin, params: $params',
|
||||
name: kRpcLogPrefix,
|
||||
);
|
||||
|
||||
if (origin.isNotEmpty &&
|
||||
![
|
||||
'https://discord.com',
|
||||
'https://ptb.discord.com',
|
||||
'https://canary.discord.com',
|
||||
].contains(origin)) {
|
||||
developer.log('Disallowed origin: $origin', name: kRpcLogPrefix);
|
||||
socket.sink.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (encoding != 'json') {
|
||||
developer.log(
|
||||
'Unsupported encoding requested: $encoding',
|
||||
name: kRpcLogPrefix,
|
||||
);
|
||||
socket.sink.close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ver != 1) {
|
||||
developer.log('Unsupported version requested: $ver', name: kRpcLogPrefix);
|
||||
socket.sink.close();
|
||||
return;
|
||||
}
|
||||
|
||||
final socketWithMeta = _WsSocketWrapper(socket, clientId, encoding);
|
||||
|
||||
socket.stream.listen(
|
||||
(data) => _onWsMessage(socketWithMeta, data),
|
||||
onError: (e) {
|
||||
developer.log('WS socket error: $e', name: kRpcLogPrefix);
|
||||
},
|
||||
onDone: () {
|
||||
developer.log('WS socket closed', name: kRpcLogPrefix);
|
||||
handlers['close']?.call(socketWithMeta);
|
||||
_wsSockets.remove(socket);
|
||||
},
|
||||
);
|
||||
|
||||
handlers['connection']?.call(socketWithMeta);
|
||||
}
|
||||
|
||||
// Handle incoming WebSocket message
|
||||
Future<void> _onWsMessage(_WsSocketWrapper socket, dynamic data) async {
|
||||
if (data is! String) {
|
||||
developer.log(
|
||||
'Invalid WebSocket message: not a string',
|
||||
name: kRpcLogPrefix,
|
||||
);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final jsonData = await compute(jsonDecode, data);
|
||||
if (jsonData is! Map<String, dynamic>) {
|
||||
developer.log(
|
||||
'Invalid WebSocket message: not a JSON object',
|
||||
name: kRpcLogPrefix,
|
||||
);
|
||||
return;
|
||||
}
|
||||
developer.log('WS message: $jsonData', name: kRpcLogPrefix);
|
||||
handlers['message']?.call(socket, jsonData);
|
||||
} catch (e) {
|
||||
developer.log('WS message parse error: $e', name: kRpcLogPrefix);
|
||||
}
|
||||
}
|
||||
|
||||
// Handle IPC packet
|
||||
void _handleIpcPacket(IpcSocketWrapper socket, IpcPacket packet) {
|
||||
switch (packet.type) {
|
||||
case IpcTypes.ping:
|
||||
developer.log('IPC ping received', name: kRpcIpcLogPrefix);
|
||||
socket.sendPong(packet.data);
|
||||
break;
|
||||
|
||||
case IpcTypes.pong:
|
||||
developer.log('IPC pong received', name: kRpcIpcLogPrefix);
|
||||
break;
|
||||
|
||||
case IpcTypes.handshake:
|
||||
if (socket.handshook) {
|
||||
throw Exception('Already handshook');
|
||||
}
|
||||
socket.handshook = true;
|
||||
_onIpcHandshake(socket, packet.data);
|
||||
break;
|
||||
|
||||
case IpcTypes.frame:
|
||||
if (!socket.handshook) {
|
||||
throw Exception('Need to handshake first');
|
||||
}
|
||||
developer.log('IPC frame: ${packet.data}', name: kRpcIpcLogPrefix);
|
||||
handlers['message']?.call(socket, packet.data);
|
||||
break;
|
||||
|
||||
case IpcTypes.close:
|
||||
socket.close();
|
||||
break;
|
||||
|
||||
default:
|
||||
throw Exception('Invalid packet type: ${packet.type}');
|
||||
}
|
||||
}
|
||||
|
||||
// Handle IPC handshake
|
||||
void _onIpcHandshake(IpcSocketWrapper socket, Map<String, dynamic> params) {
|
||||
developer.log('IPC handshake: $params', name: kRpcIpcLogPrefix);
|
||||
|
||||
final ver = int.tryParse(params['v']?.toString() ?? '1') ?? 1;
|
||||
final clientId = params['client_id']?.toString() ?? '';
|
||||
|
||||
if (ver != 1) {
|
||||
developer.log(
|
||||
'IPC unsupported version requested: $ver',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
socket.closeWithCode(IpcErrorCodes.invalidVersion);
|
||||
return;
|
||||
}
|
||||
|
||||
if (clientId.isEmpty) {
|
||||
developer.log('IPC client ID required', name: kRpcIpcLogPrefix);
|
||||
socket.closeWithCode(IpcErrorCodes.invalidClientId);
|
||||
return;
|
||||
}
|
||||
|
||||
socket.clientId = clientId;
|
||||
|
||||
handlers['connection']?.call(socket);
|
||||
}
|
||||
}
|
||||
|
||||
// WebSocket wrapper
|
||||
class _WsSocketWrapper {
|
||||
final WebSocketChannel channel;
|
||||
final String clientId;
|
||||
final String encoding;
|
||||
|
||||
_WsSocketWrapper(this.channel, this.clientId, this.encoding);
|
||||
|
||||
void send(Map<String, dynamic> msg) {
|
||||
developer.log('WS sending: $msg', name: kRpcLogPrefix);
|
||||
channel.sink.add(jsonEncode(msg));
|
||||
}
|
||||
}
|
||||
|
||||
// State management for server status and activities
|
||||
class ServerState {
|
||||
final String status;
|
||||
final List<String> activities;
|
||||
|
||||
ServerState({required this.status, this.activities = const []});
|
||||
|
||||
ServerState copyWith({String? status, List<String>? activities}) {
|
||||
return ServerState(
|
||||
status: status ?? this.status,
|
||||
activities: activities ?? this.activities,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class ServerStateNotifier extends StateNotifier<ServerState> {
|
||||
final ActivityRpcServer server;
|
||||
|
||||
ServerStateNotifier(this.server)
|
||||
: super(ServerState(status: 'Server not started'));
|
||||
|
||||
Future<void> start() async {
|
||||
if (!Platform.isAndroid && !Platform.isIOS && !kIsWeb) {
|
||||
try {
|
||||
await server.start();
|
||||
state = state.copyWith(status: 'Server running');
|
||||
} catch (e) {
|
||||
state = state.copyWith(status: 'Server failed: $e');
|
||||
}
|
||||
} else {
|
||||
state = state.copyWith(status: 'Server disabled on mobile/web');
|
||||
}
|
||||
}
|
||||
|
||||
void updateStatus(String status) {
|
||||
state = state.copyWith(status: status);
|
||||
}
|
||||
|
||||
void addActivity(String activity) {
|
||||
state = state.copyWith(activities: [...state.activities, activity]);
|
||||
}
|
||||
}
|
||||
|
||||
// Providers
|
||||
final rpcServerStateProvider =
|
||||
StateNotifierProvider<ServerStateNotifier, ServerState>((ref) {
|
||||
final server = ActivityRpcServer({});
|
||||
final notifier = ServerStateNotifier(server);
|
||||
server.updateHandlers({
|
||||
'connection': (socket) {
|
||||
final clientId =
|
||||
socket is _WsSocketWrapper
|
||||
? socket.clientId
|
||||
: (socket as IpcSocketWrapper).clientId;
|
||||
notifier.updateStatus('Client connected (ID: $clientId)');
|
||||
socket.send({
|
||||
'cmd': 'DISPATCH',
|
||||
'data': {
|
||||
'v': 1,
|
||||
'config': {
|
||||
'cdn_host': 'fake.cdn',
|
||||
'api_endpoint': '//fake.api',
|
||||
'environment': 'dev',
|
||||
},
|
||||
'user': {
|
||||
'id': 'fake_user_id',
|
||||
'username': 'FakeUser',
|
||||
'discriminator': '0001',
|
||||
'avatar': null,
|
||||
'bot': false,
|
||||
},
|
||||
},
|
||||
'evt': 'READY',
|
||||
'nonce': '12345',
|
||||
});
|
||||
},
|
||||
'message': (socket, dynamic data) async {
|
||||
if (data['cmd'] == 'SET_ACTIVITY') {
|
||||
notifier.addActivity(
|
||||
'Activity: ${data['args']['activity']['details'] ?? 'Unknown'}',
|
||||
);
|
||||
final label = data['args']['activity']['details'] ?? 'Unknown';
|
||||
final appId = socket.clientId;
|
||||
try {
|
||||
await setRemoteActivityStatus(ref, label, appId);
|
||||
} catch (e) {
|
||||
developer.log(
|
||||
'Failed to set remote activity status: $e',
|
||||
name: kRpcLogPrefix,
|
||||
);
|
||||
}
|
||||
socket.send({
|
||||
'cmd': 'SET_ACTIVITY',
|
||||
'data': data['args']['activity'],
|
||||
'evt': null,
|
||||
'nonce': data['nonce'],
|
||||
});
|
||||
}
|
||||
},
|
||||
'close': (socket) async {
|
||||
notifier.updateStatus('Client disconnected');
|
||||
final appId = socket.clientId;
|
||||
try {
|
||||
await unsetRemoteActivityStatus(ref, appId);
|
||||
} catch (e) {
|
||||
developer.log(
|
||||
'Failed to unset remote activity status: $e',
|
||||
name: kRpcLogPrefix,
|
||||
);
|
||||
}
|
||||
},
|
||||
});
|
||||
return notifier;
|
||||
});
|
||||
|
||||
final rpcServerProvider = Provider<ActivityRpcServer>((ref) {
|
||||
final notifier = ref.watch(rpcServerStateProvider.notifier);
|
||||
return notifier.server;
|
||||
});
|
||||
|
||||
Future<void> setRemoteActivityStatus(
|
||||
Ref ref,
|
||||
String label,
|
||||
String appId,
|
||||
) async {
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.post(
|
||||
'/id/accounts/me/statuses',
|
||||
data: {
|
||||
'is_invisible': false,
|
||||
'is_not_disturb': false,
|
||||
'is_automated': true,
|
||||
'label': label,
|
||||
'app_identifier': appId,
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
Future<void> unsetRemoteActivityStatus(Ref ref, String appId) async {
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.delete(
|
||||
'/id/accounts/me/statuses',
|
||||
queryParameters: {'app': appId},
|
||||
);
|
||||
}
|
||||
297
lib/pods/activity/ipc_server.dart
Normal file
297
lib/pods/activity/ipc_server.dart
Normal file
@@ -0,0 +1,297 @@
|
||||
import 'dart:async';
|
||||
import 'dart:convert';
|
||||
import 'dart:developer' as developer;
|
||||
import 'dart:io';
|
||||
import 'dart:typed_data';
|
||||
import 'package:dart_ipc/dart_ipc.dart';
|
||||
import 'package:path/path.dart' as path;
|
||||
|
||||
const String kRpcIpcLogPrefix = 'arRPC.ipc';
|
||||
|
||||
// IPC Packet Types
|
||||
class IpcTypes {
|
||||
static const int handshake = 0;
|
||||
static const int frame = 1;
|
||||
static const int close = 2;
|
||||
static const int ping = 3;
|
||||
static const int pong = 4;
|
||||
}
|
||||
|
||||
// IPC Close Codes
|
||||
class IpcCloseCodes {
|
||||
static const int closeNormal = 1000;
|
||||
static const int closeUnsupported = 1003;
|
||||
static const int closeAbnormal = 1006;
|
||||
}
|
||||
|
||||
// IPC Error Codes
|
||||
class IpcErrorCodes {
|
||||
static const int invalidClientId = 4000;
|
||||
static const int invalidOrigin = 4001;
|
||||
static const int rateLimited = 4002;
|
||||
static const int tokenRevoked = 4003;
|
||||
static const int invalidVersion = 4004;
|
||||
static const int invalidEncoding = 4005;
|
||||
}
|
||||
|
||||
// IPC Packet structure
|
||||
class IpcPacket {
|
||||
final int type;
|
||||
final Map<String, dynamic> data;
|
||||
|
||||
IpcPacket(this.type, this.data);
|
||||
}
|
||||
|
||||
// Abstract base class for IPC server
|
||||
abstract class IpcServer {
|
||||
final List<IpcSocketWrapper> _sockets = [];
|
||||
|
||||
// Encode IPC packet
|
||||
static Uint8List encodeIpcPacket(int type, Map<String, dynamic> data) {
|
||||
final jsonData = jsonEncode(data);
|
||||
final dataBytes = utf8.encode(jsonData);
|
||||
final dataSize = dataBytes.length;
|
||||
|
||||
final buffer = ByteData(8 + dataSize);
|
||||
buffer.setInt32(0, type, Endian.little);
|
||||
buffer.setInt32(4, dataSize, Endian.little);
|
||||
buffer.buffer.asUint8List().setRange(8, 8 + dataSize, dataBytes);
|
||||
|
||||
return buffer.buffer.asUint8List();
|
||||
}
|
||||
|
||||
Future<void> start();
|
||||
Future<void> stop();
|
||||
|
||||
void addSocket(IpcSocketWrapper socket) {
|
||||
_sockets.add(socket);
|
||||
}
|
||||
|
||||
void removeSocket(IpcSocketWrapper socket) {
|
||||
_sockets.remove(socket);
|
||||
}
|
||||
|
||||
List<IpcSocketWrapper> get sockets => _sockets;
|
||||
|
||||
void Function(
|
||||
IpcSocketWrapper socket,
|
||||
IpcPacket packet,
|
||||
Map<String, Function> handlers,
|
||||
)?
|
||||
handlePacket;
|
||||
}
|
||||
|
||||
// Abstract base class for IPC socket wrapper
|
||||
abstract class IpcSocketWrapper {
|
||||
String clientId = '';
|
||||
bool handshook = false;
|
||||
final List<int> _buffer = [];
|
||||
|
||||
void addData(List<int> data) {
|
||||
_buffer.addAll(data);
|
||||
}
|
||||
|
||||
void send(Map<String, dynamic> msg);
|
||||
void sendPong(dynamic data);
|
||||
void close();
|
||||
void closeWithCode(int code, [String message = '']);
|
||||
|
||||
List<IpcPacket> readPackets() {
|
||||
final packets = <IpcPacket>[];
|
||||
|
||||
while (_buffer.length >= 8) {
|
||||
final buffer = Uint8List.fromList(_buffer);
|
||||
final byteData = ByteData.view(buffer.buffer);
|
||||
|
||||
final type = byteData.getInt32(0, Endian.little);
|
||||
final dataSize = byteData.getInt32(4, Endian.little);
|
||||
|
||||
if (_buffer.length < 8 + dataSize) break;
|
||||
|
||||
final dataBytes = _buffer.sublist(8, 8 + dataSize);
|
||||
final jsonStr = utf8.decode(dataBytes);
|
||||
final jsonData = jsonDecode(jsonStr);
|
||||
|
||||
packets.add(IpcPacket(type, jsonData));
|
||||
|
||||
_buffer.removeRange(0, 8 + dataSize);
|
||||
}
|
||||
|
||||
return packets;
|
||||
}
|
||||
}
|
||||
|
||||
// Multiplatform IPC Server implementation using dart_ipc
|
||||
class MultiPlatformIpcServer extends IpcServer {
|
||||
StreamSubscription? _serverSubscription;
|
||||
|
||||
@override
|
||||
Future<void> start() async {
|
||||
try {
|
||||
final ipcPath = Platform.isWindows
|
||||
? r'\\.\pipe\discord-ipc-0'
|
||||
: await _findAvailableUnixIpcPath();
|
||||
|
||||
final serverSocket = await bind(ipcPath);
|
||||
developer.log(
|
||||
'IPC listening at $ipcPath',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
|
||||
_serverSubscription = serverSocket.listen((socket) {
|
||||
final socketWrapper = MultiPlatformIpcSocketWrapper(socket);
|
||||
addSocket(socketWrapper);
|
||||
developer.log(
|
||||
'New IPC connection!',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
_handleIpcData(socketWrapper);
|
||||
});
|
||||
} catch (e) {
|
||||
throw Exception('Failed to start IPC server: $e');
|
||||
}
|
||||
}
|
||||
|
||||
@override
|
||||
Future<void> stop() async {
|
||||
for (var socket in sockets) {
|
||||
try {
|
||||
socket.close();
|
||||
} catch (e) {
|
||||
developer.log('Error closing IPC socket: $e', name: kRpcIpcLogPrefix);
|
||||
}
|
||||
}
|
||||
sockets.clear();
|
||||
_serverSubscription?.cancel();
|
||||
}
|
||||
|
||||
// Handle incoming IPC data
|
||||
void _handleIpcData(MultiPlatformIpcSocketWrapper socket) {
|
||||
final startTime = DateTime.now();
|
||||
socket.socket.listen((data) {
|
||||
final readStart = DateTime.now();
|
||||
socket.addData(data);
|
||||
final readDuration = DateTime.now().difference(readStart).inMicroseconds;
|
||||
developer.log(
|
||||
'Read data took $readDuration microseconds',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
|
||||
final packets = socket.readPackets();
|
||||
for (final packet in packets) {
|
||||
handlePacket?.call(socket, packet, {});
|
||||
}
|
||||
}, onDone: () {
|
||||
developer.log('IPC connection closed', name: kRpcIpcLogPrefix);
|
||||
socket.close();
|
||||
}, onError: (e) {
|
||||
developer.log('IPC data error: $e', name: kRpcIpcLogPrefix);
|
||||
socket.closeWithCode(IpcCloseCodes.closeUnsupported, e.toString());
|
||||
});
|
||||
final totalDuration = DateTime.now().difference(startTime).inMicroseconds;
|
||||
developer.log(
|
||||
'_handleIpcData took $totalDuration microseconds',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
}
|
||||
|
||||
Future<String> _getMacOsSystemTmpDir() async {
|
||||
final result = await Process.run('getconf', ['DARWIN_USER_TEMP_DIR']);
|
||||
return (result.stdout as String).trim();
|
||||
}
|
||||
|
||||
// Find available IPC socket path for Unix-like systems
|
||||
Future<String> _findAvailableUnixIpcPath() async {
|
||||
// Build list of directories to try, with macOS-specific handling
|
||||
final baseDirs = <String>[];
|
||||
|
||||
if (Platform.isMacOS) {
|
||||
try {
|
||||
final macTempDir = await _getMacOsSystemTmpDir();
|
||||
if (macTempDir.isNotEmpty) {
|
||||
baseDirs.add(macTempDir);
|
||||
}
|
||||
} catch (e) {
|
||||
developer.log(
|
||||
'Failed to get macOS system temp dir: $e',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Add other standard directories
|
||||
final otherDirs = [
|
||||
Platform.environment['XDG_RUNTIME_DIR'],
|
||||
Platform.environment['TMPDIR'],
|
||||
Platform.environment['TMP'],
|
||||
Platform.environment['TEMP'],
|
||||
'/tmp',
|
||||
];
|
||||
|
||||
baseDirs.addAll(
|
||||
otherDirs.where((dir) => dir != null && dir.isNotEmpty).cast<String>(),
|
||||
);
|
||||
|
||||
for (final baseDir in baseDirs) {
|
||||
for (int i = 0; i < 10; i++) {
|
||||
final socketPath = path.join(baseDir, 'discord-ipc-$i');
|
||||
try {
|
||||
final socket = await bind(socketPath);
|
||||
socket.close();
|
||||
try {
|
||||
await File(socketPath).delete();
|
||||
} catch (_) {}
|
||||
developer.log(
|
||||
'IPC socket will be created at: $socketPath',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
return socketPath;
|
||||
} catch (e) {
|
||||
if (i == 0) {
|
||||
developer.log(
|
||||
'IPC path $socketPath not available: $e',
|
||||
name: kRpcIpcLogPrefix,
|
||||
);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
throw Exception(
|
||||
'No available IPC socket paths found in any temp directory',
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
// Multiplatform IPC Socket Wrapper
|
||||
class MultiPlatformIpcSocketWrapper extends IpcSocketWrapper {
|
||||
final dynamic socket;
|
||||
|
||||
MultiPlatformIpcSocketWrapper(this.socket);
|
||||
|
||||
@override
|
||||
void send(Map<String, dynamic> msg) {
|
||||
developer.log('IPC sending: $msg', name: kRpcIpcLogPrefix);
|
||||
final packet = IpcServer.encodeIpcPacket(IpcTypes.frame, msg);
|
||||
socket.add(packet);
|
||||
}
|
||||
|
||||
@override
|
||||
void sendPong(dynamic data) {
|
||||
final packet = IpcServer.encodeIpcPacket(IpcTypes.pong, data ?? {});
|
||||
socket.add(packet);
|
||||
}
|
||||
|
||||
@override
|
||||
void close() {
|
||||
socket.close();
|
||||
}
|
||||
|
||||
@override
|
||||
void closeWithCode(int code, [String message = '']) {
|
||||
final closeData = {'code': code, 'message': message};
|
||||
final packet = IpcServer.encodeIpcPacket(IpcTypes.close, closeData);
|
||||
socket.add(packet);
|
||||
socket.close();
|
||||
}
|
||||
}
|
||||
61
lib/pods/activity/ipc_server.web.dart
Normal file
61
lib/pods/activity/ipc_server.web.dart
Normal file
@@ -0,0 +1,61 @@
|
||||
// Stub implementation for web platform
|
||||
// This file provides empty implementations to avoid import errors on web
|
||||
|
||||
// IPC Packet Types
|
||||
class IpcTypes {
|
||||
static const int handshake = 0;
|
||||
static const int frame = 1;
|
||||
static const int close = 2;
|
||||
static const int ping = 3;
|
||||
static const int pong = 4;
|
||||
}
|
||||
|
||||
// IPC Close Codes
|
||||
class IpcCloseCodes {
|
||||
static const int closeNormal = 1000;
|
||||
static const int closeUnsupported = 1003;
|
||||
static const int closeAbnormal = 1006;
|
||||
}
|
||||
|
||||
// IPC Error Codes
|
||||
class IpcErrorCodes {
|
||||
static const int invalidClientId = 4000;
|
||||
static const int invalidOrigin = 4001;
|
||||
static const int rateLimited = 4002;
|
||||
static const int tokenRevoked = 4003;
|
||||
static const int invalidVersion = 4004;
|
||||
static const int invalidEncoding = 4005;
|
||||
}
|
||||
|
||||
// IPC Packet structure
|
||||
class IpcPacket {
|
||||
final int type;
|
||||
final Map<String, dynamic> data;
|
||||
|
||||
IpcPacket(this.type, this.data);
|
||||
}
|
||||
|
||||
class IpcServer {
|
||||
Future<void> start() async {}
|
||||
Future<void> stop() async {}
|
||||
void Function(dynamic, dynamic, dynamic)? handlePacket;
|
||||
void addSocket(dynamic socket) {}
|
||||
void removeSocket(dynamic socket) {}
|
||||
List<dynamic> get sockets => [];
|
||||
}
|
||||
|
||||
class IpcSocketWrapper {
|
||||
String clientId = '';
|
||||
bool handshook = false;
|
||||
|
||||
void addData(List<int> data) {}
|
||||
void send(Map<String, dynamic> msg) {}
|
||||
void sendPong(dynamic data) {}
|
||||
void close() {}
|
||||
void closeWithCode(int code, [String message = '']) {}
|
||||
List<dynamic> readPackets() => [];
|
||||
}
|
||||
|
||||
class MultiPlatformIpcServer extends IpcServer {}
|
||||
|
||||
class MultiPlatformIpcSocketWrapper extends IpcSocketWrapper {}
|
||||
@@ -9,6 +9,7 @@ import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/models/chat.dart';
|
||||
import 'package:wakelock_plus/wakelock_plus.dart';
|
||||
|
||||
part 'call.g.dart';
|
||||
part 'call.freezed.dart';
|
||||
@@ -54,7 +55,7 @@ sealed class CallParticipantLive with _$CallParticipantLive {
|
||||
bool get hasAudio => remoteParticipant.hasAudio;
|
||||
}
|
||||
|
||||
@riverpod
|
||||
@Riverpod(keepAlive: true)
|
||||
class CallNotifier extends _$CallNotifier {
|
||||
Room? _room;
|
||||
LocalParticipant? _localParticipant;
|
||||
@@ -277,14 +278,27 @@ class CallNotifier extends _$CallNotifier {
|
||||
|
||||
// Listen for connection updates
|
||||
_room!.addListener(() {
|
||||
final wasConnected = state.isConnected;
|
||||
final isNowConnected =
|
||||
_room!.connectionState == ConnectionState.connected;
|
||||
state = state.copyWith(
|
||||
isConnected: _room!.connectionState == ConnectionState.connected,
|
||||
isConnected: isNowConnected,
|
||||
isMicrophoneEnabled: _localParticipant!.isMicrophoneEnabled(),
|
||||
isCameraEnabled: _localParticipant!.isCameraEnabled(),
|
||||
isScreenSharing: _localParticipant!.isScreenShareEnabled(),
|
||||
);
|
||||
// Enable wakelock when call connects
|
||||
if (!wasConnected && isNowConnected) {
|
||||
WakelockPlus.enable();
|
||||
}
|
||||
// Disable wakelock when call disconnects
|
||||
else if (wasConnected && !isNowConnected) {
|
||||
WakelockPlus.disable();
|
||||
}
|
||||
});
|
||||
state = state.copyWith(isConnected: true);
|
||||
// Enable wakelock when call connects
|
||||
WakelockPlus.enable();
|
||||
} else {
|
||||
state = state.copyWith(error: 'Failed to join room');
|
||||
}
|
||||
@@ -344,6 +358,8 @@ class CallNotifier extends _$CallNotifier {
|
||||
isCameraEnabled: false,
|
||||
isScreenSharing: false,
|
||||
);
|
||||
// Disable wakelock when call disconnects
|
||||
WakelockPlus.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -381,5 +397,7 @@ class CallNotifier extends _$CallNotifier {
|
||||
_durationTimer?.cancel();
|
||||
_roomId = null;
|
||||
participantsVolumes = {};
|
||||
// Disable wakelock when disposing
|
||||
WakelockPlus.disable();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,22 +6,19 @@ part of 'call.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$callNotifierHash() => r'18fb807f067eecd3ea42631c1426c3e5f1fb4280';
|
||||
String _$callNotifierHash() => r'eb9bd41b97e9b5e9d54007c8327edb6567458846';
|
||||
|
||||
/// See also [CallNotifier].
|
||||
@ProviderFor(CallNotifier)
|
||||
final callNotifierProvider =
|
||||
AutoDisposeNotifierProvider<CallNotifier, CallState>.internal(
|
||||
CallNotifier.new,
|
||||
name: r'callNotifierProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$callNotifierHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
final callNotifierProvider = NotifierProvider<CallNotifier, CallState>.internal(
|
||||
CallNotifier.new,
|
||||
name: r'callNotifierProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product') ? null : _$callNotifierHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$CallNotifier = AutoDisposeNotifier<CallState>;
|
||||
typedef _$CallNotifier = Notifier<CallState>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
||||
@@ -15,10 +15,12 @@ const kNetworkServerStoreKey = 'app_server_url';
|
||||
|
||||
const kAppbarTransparentStoreKey = 'app_bar_transparent';
|
||||
const kAppBackgroundStoreKey = 'app_has_background';
|
||||
const kAppShowBackgroundImage = 'app_show_background_image';
|
||||
const kAppColorSchemeStoreKey = 'app_color_scheme';
|
||||
const kAppNotifyWithHaptic = 'app_notify_with_haptic';
|
||||
const kAppCustomFonts = 'app_custom_fonts';
|
||||
const kAppAutoTranslate = 'app_auto_translate';
|
||||
const kAppDataSavingMode = 'app_data_saving_mode';
|
||||
const kAppSoundEffects = 'app_sound_effects';
|
||||
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
||||
const kAppWindowSize = 'app_window_size';
|
||||
@@ -54,10 +56,12 @@ final serverUrlProvider = Provider<String>((ref) {
|
||||
sealed class AppSettings with _$AppSettings {
|
||||
const factory AppSettings({
|
||||
required bool autoTranslate,
|
||||
required bool dataSavingMode,
|
||||
required bool soundEffects,
|
||||
required bool aprilFoolFeatures,
|
||||
required bool enterToSend,
|
||||
required bool appBarTransparent,
|
||||
required bool showBackgroundImage,
|
||||
required String? customFonts,
|
||||
required int? appColorScheme, // The color stored via the int type
|
||||
required Size? windowSize, // The window size for desktop platforms
|
||||
@@ -71,10 +75,12 @@ class AppSettingsNotifier extends _$AppSettingsNotifier {
|
||||
final prefs = ref.watch(sharedPreferencesProvider);
|
||||
return AppSettings(
|
||||
autoTranslate: prefs.getBool(kAppAutoTranslate) ?? false,
|
||||
dataSavingMode: prefs.getBool(kAppDataSavingMode) ?? false,
|
||||
soundEffects: prefs.getBool(kAppSoundEffects) ?? true,
|
||||
aprilFoolFeatures: prefs.getBool(kAppAprilFoolFeatures) ?? true,
|
||||
enterToSend: prefs.getBool(kAppEnterToSend) ?? true,
|
||||
appBarTransparent: prefs.getBool(kAppbarTransparentStoreKey) ?? false,
|
||||
showBackgroundImage: prefs.getBool(kAppShowBackgroundImage) ?? true,
|
||||
customFonts: prefs.getString(kAppCustomFonts),
|
||||
appColorScheme: prefs.getInt(kAppColorSchemeStoreKey),
|
||||
windowSize: _getWindowSizeFromPrefs(prefs),
|
||||
@@ -104,6 +110,12 @@ class AppSettingsNotifier extends _$AppSettingsNotifier {
|
||||
state = state.copyWith(autoTranslate: value);
|
||||
}
|
||||
|
||||
void setDataSavingMode(bool value){
|
||||
final prefs = ref.read(sharedPreferencesProvider);
|
||||
prefs.setBool(kAppDataSavingMode, value);
|
||||
state = state.copyWith(dataSavingMode: value);
|
||||
}
|
||||
|
||||
void setSoundEffects(bool value) {
|
||||
final prefs = ref.read(sharedPreferencesProvider);
|
||||
prefs.setBool(kAppSoundEffects, value);
|
||||
@@ -129,6 +141,12 @@ class AppSettingsNotifier extends _$AppSettingsNotifier {
|
||||
ref.read(themeProvider.notifier).reloadTheme();
|
||||
}
|
||||
|
||||
void setShowBackgroundImage(bool value) {
|
||||
final prefs = ref.read(sharedPreferencesProvider);
|
||||
prefs.setBool(kAppShowBackgroundImage, value);
|
||||
state = state.copyWith(showBackgroundImage: value);
|
||||
}
|
||||
|
||||
void setCustomFonts(String? value) {
|
||||
final prefs = ref.read(sharedPreferencesProvider);
|
||||
prefs.setString(kAppCustomFonts, value ?? '');
|
||||
|
||||
@@ -14,7 +14,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$AppSettings {
|
||||
|
||||
bool get autoTranslate; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend; bool get appBarTransparent; String? get customFonts; int? get appColorScheme;// The color stored via the int type
|
||||
bool get autoTranslate; bool get dataSavingMode; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend; bool get appBarTransparent; bool get showBackgroundImage; String? get customFonts; int? get appColorScheme;// The color stored via the int type
|
||||
Size? get windowSize;
|
||||
/// Create a copy of AppSettings
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -26,16 +26,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.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.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
|
||||
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.windowSize, windowSize) || other.windowSize == windowSize));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,customFonts,appColorScheme,windowSize);
|
||||
int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
||||
}
|
||||
|
||||
|
||||
@@ -46,7 +46,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> {
|
||||
factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme, Size? windowSize
|
||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize
|
||||
});
|
||||
|
||||
|
||||
@@ -63,13 +63,15 @@ 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? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) {
|
||||
@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? windowSize = freezed,}) {
|
||||
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
|
||||
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
||||
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
||||
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
||||
as bool,appBarTransparent: null == appBarTransparent ? _self.appBarTransparent : appBarTransparent // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showBackgroundImage: null == showBackgroundImage ? _self.showBackgroundImage : showBackgroundImage // ignore: cast_nullable_to_non_nullable
|
||||
as bool,customFonts: freezed == customFonts ? _self.customFonts : customFonts // ignore: cast_nullable_to_non_nullable
|
||||
as String?,appColorScheme: freezed == appColorScheme ? _self.appColorScheme : appColorScheme // ignore: cast_nullable_to_non_nullable
|
||||
as int?,windowSize: freezed == windowSize ? _self.windowSize : windowSize // ignore: cast_nullable_to_non_nullable
|
||||
@@ -155,10 +157,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme, Size? windowSize)? $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, Size? windowSize)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AppSettings() when $default != null:
|
||||
return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -176,10 +178,10 @@ return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme, Size? windowSize) $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, Size? windowSize) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AppSettings():
|
||||
return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.customFonts,_that.appColorScheme,_that.windowSize);}
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -193,10 +195,10 @@ return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme, Size? windowSize)? $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, Size? windowSize)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _AppSettings() when $default != null:
|
||||
return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
||||
return $default(_that.autoTranslate,_that.dataSavingMode,_that.soundEffects,_that.aprilFoolFeatures,_that.enterToSend,_that.appBarTransparent,_that.showBackgroundImage,_that.customFonts,_that.appColorScheme,_that.windowSize);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -208,14 +210,16 @@ return $default(_that.autoTranslate,_that.soundEffects,_that.aprilFoolFeatures,_
|
||||
|
||||
|
||||
class _AppSettings implements AppSettings {
|
||||
const _AppSettings({required this.autoTranslate, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.customFonts, required this.appColorScheme, required this.windowSize});
|
||||
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.windowSize});
|
||||
|
||||
|
||||
@override final bool autoTranslate;
|
||||
@override final bool dataSavingMode;
|
||||
@override final bool soundEffects;
|
||||
@override final bool aprilFoolFeatures;
|
||||
@override final bool enterToSend;
|
||||
@override final bool appBarTransparent;
|
||||
@override final bool showBackgroundImage;
|
||||
@override final String? customFonts;
|
||||
@override final int? appColorScheme;
|
||||
// The color stored via the int type
|
||||
@@ -231,16 +235,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.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.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme)&&(identical(other.windowSize, windowSize) || other.windowSize == windowSize));
|
||||
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.windowSize, windowSize) || other.windowSize == windowSize));
|
||||
}
|
||||
|
||||
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,customFonts,appColorScheme,windowSize);
|
||||
int get hashCode => Object.hash(runtimeType,autoTranslate,dataSavingMode,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,showBackgroundImage,customFonts,appColorScheme,windowSize);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
||||
return 'AppSettings(autoTranslate: $autoTranslate, dataSavingMode: $dataSavingMode, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, showBackgroundImage: $showBackgroundImage, customFonts: $customFonts, appColorScheme: $appColorScheme, windowSize: $windowSize)';
|
||||
}
|
||||
|
||||
|
||||
@@ -251,7 +255,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith
|
||||
factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme, Size? windowSize
|
||||
bool autoTranslate, bool dataSavingMode, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, bool showBackgroundImage, String? customFonts, int? appColorScheme, Size? windowSize
|
||||
});
|
||||
|
||||
|
||||
@@ -268,13 +272,15 @@ 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? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? customFonts = freezed,Object? appColorScheme = freezed,Object? windowSize = freezed,}) {
|
||||
@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? windowSize = freezed,}) {
|
||||
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
|
||||
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
||||
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
||||
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
||||
as bool,appBarTransparent: null == appBarTransparent ? _self.appBarTransparent : appBarTransparent // ignore: cast_nullable_to_non_nullable
|
||||
as bool,showBackgroundImage: null == showBackgroundImage ? _self.showBackgroundImage : showBackgroundImage // ignore: cast_nullable_to_non_nullable
|
||||
as bool,customFonts: freezed == customFonts ? _self.customFonts : customFonts // ignore: cast_nullable_to_non_nullable
|
||||
as String?,appColorScheme: freezed == appColorScheme ? _self.appColorScheme : appColorScheme // ignore: cast_nullable_to_non_nullable
|
||||
as int?,windowSize: freezed == windowSize ? _self.windowSize : windowSize // ignore: cast_nullable_to_non_nullable
|
||||
|
||||
@@ -7,7 +7,7 @@ part of 'config.dart';
|
||||
// **************************************************************************
|
||||
|
||||
String _$appSettingsNotifierHash() =>
|
||||
r'c4f40a3bc4311c6360c2b5e44f8df5e5d7c1bd75';
|
||||
r'cd18bff2614a94e3523634e6c577cefad0367eba';
|
||||
|
||||
/// See also [AppSettingsNotifier].
|
||||
@ProviderFor(AppSettingsNotifier)
|
||||
|
||||
@@ -1,11 +1,9 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
||||
|
||||
part 'translate.freezed.dart';
|
||||
part 'translate.g.dart';
|
||||
@@ -29,10 +27,17 @@ Future<String> translateString(Ref ref, TranslateQuery query) async {
|
||||
|
||||
@riverpod
|
||||
String? detectStringLanguage(Ref ref, String text) {
|
||||
try {
|
||||
return langdetect.detectLangs(text).firstOrNull?.lang;
|
||||
} catch (err) {
|
||||
log('[Language] Unable to detect text\'s language: $text');
|
||||
return null;
|
||||
bool isChinese(String text) {
|
||||
final chineseRegex = RegExp(r'[\u4e00-\u9fff]');
|
||||
return chineseRegex.hasMatch(text);
|
||||
}
|
||||
|
||||
bool isEnglish(String text) {
|
||||
final englishRegex = RegExp(r'[a-zA-Z]');
|
||||
return englishRegex.hasMatch(text) && !isChinese(text);
|
||||
}
|
||||
|
||||
if (isChinese(text)) return "zh";
|
||||
if (isEnglish(text)) return "en";
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -149,7 +149,7 @@ class _TranslateStringProviderElement
|
||||
}
|
||||
|
||||
String _$detectStringLanguageHash() =>
|
||||
r'697b68464b3d00927cc43ccc1ba8ba93f2a470ed';
|
||||
r'24fbf52edbbffcc8dc4f09f7206f82d69728e703';
|
||||
|
||||
/// See also [detectStringLanguage].
|
||||
@ProviderFor(detectStringLanguage)
|
||||
|
||||
@@ -1,6 +1,12 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:developer';
|
||||
import 'dart:io' show Platform;
|
||||
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter_platform_alert/flutter_platform_alert.dart';
|
||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
@@ -13,13 +19,59 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
||||
UserInfoNotifier(this._ref) : super(const AsyncValue.data(null));
|
||||
|
||||
Future<void> fetchUser() async {
|
||||
final token = _ref.watch(tokenProvider);
|
||||
if (token == null) {
|
||||
log('[UserInfo] No token found, not going to fetch...');
|
||||
return;
|
||||
}
|
||||
try {
|
||||
final client = _ref.read(apiClientProvider);
|
||||
final response = await client.get('/id/accounts/me');
|
||||
final user = SnAccount.fromJson(response.data);
|
||||
state = AsyncValue.data(user);
|
||||
FirebaseAnalytics.instance.setUserId(id: user.id);
|
||||
|
||||
if (kIsWeb || !(Platform.isLinux || Platform.isWindows)) {
|
||||
FirebaseAnalytics.instance.setUserId(id: user.id);
|
||||
}
|
||||
} catch (error, stackTrace) {
|
||||
if (!kIsWeb) {
|
||||
if (error is DioException) {
|
||||
FlutterPlatformAlert.showCustomAlert(
|
||||
windowTitle: 'failedToLoadUserInfo'.tr(),
|
||||
text: [
|
||||
(error.response?.statusCode == 401
|
||||
? 'failedToLoadUserInfoUnauthorized'
|
||||
: 'failedToLoadUserInfoNetwork')
|
||||
.tr()
|
||||
.trim(),
|
||||
'${error.response?.statusCode ?? 'Network Error'}\n${error.response?.headers}',
|
||||
jsonEncode(error.response?.data),
|
||||
].join('\n\n'),
|
||||
iconStyle: IconStyle.error,
|
||||
neutralButtonTitle: 'retry'.tr(),
|
||||
negativeButtonTitle: 'okay'.tr(),
|
||||
).then((value) {
|
||||
if (value == CustomButton.neutralButton) {
|
||||
fetchUser();
|
||||
}
|
||||
});
|
||||
}
|
||||
FlutterPlatformAlert.showCustomAlert(
|
||||
windowTitle: 'failedToLoadUserInfo'.tr(),
|
||||
text:
|
||||
[
|
||||
'failedToLoadUserInfoNetwork'.tr(),
|
||||
error.toString(),
|
||||
].join('\n\n').trim(),
|
||||
iconStyle: IconStyle.error,
|
||||
neutralButtonTitle: 'retry'.tr(),
|
||||
negativeButtonTitle: 'okay'.tr(),
|
||||
).then((value) {
|
||||
if (value == CustomButton.neutralButton) {
|
||||
fetchUser();
|
||||
}
|
||||
});
|
||||
}
|
||||
log(
|
||||
"[UserInfo] Failed to fetch user info...",
|
||||
name: 'UserInfoNotifier',
|
||||
@@ -35,7 +87,9 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
||||
final prefs = _ref.read(sharedPreferencesProvider);
|
||||
await prefs.remove(kTokenPairStoreKey);
|
||||
_ref.invalidate(tokenProvider);
|
||||
FirebaseAnalytics.instance.setUserId(id: null);
|
||||
if (kIsWeb || !(Platform.isLinux || Platform.isWindows)) {
|
||||
FirebaseAnalytics.instance.setUserId(id: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
163
lib/route.dart
163
lib/route.dart
@@ -6,11 +6,20 @@ import 'package:flutter/foundation.dart' show kIsWeb;
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/screens/about.dart';
|
||||
import 'package:island/screens/developers/apps.dart';
|
||||
import 'package:island/screens/account/credits.dart';
|
||||
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_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/posts/post_categories_list.dart';
|
||||
import 'package:island/screens/posts/post_category_detail.dart';
|
||||
import 'package:island/screens/posts/post_search.dart';
|
||||
import 'package:island/widgets/app_wrapper.dart';
|
||||
@@ -29,12 +38,15 @@ import 'package:island/screens/chat/chat.dart';
|
||||
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_screen.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/marketplace.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';
|
||||
import 'package:island/screens/discovery/feeds/feed_detail.dart';
|
||||
import 'package:island/screens/creators/poll/poll_list.dart';
|
||||
import 'package:island/screens/creators/publishers.dart';
|
||||
import 'package:island/screens/creators/webfeed/webfeed_list.dart';
|
||||
@@ -52,6 +64,7 @@ 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';
|
||||
import 'package:island/widgets/post/post_shuffle.dart';
|
||||
|
||||
// Shell route keys for nested navigation
|
||||
final rootNavigatorKey = GlobalKey<NavigatorState>();
|
||||
@@ -76,8 +89,7 @@ bool get _supportsAnalytics =>
|
||||
kIsWeb ||
|
||||
Platform.isAndroid ||
|
||||
Platform.isIOS ||
|
||||
Platform.isMacOS ||
|
||||
Platform.isWindows;
|
||||
Platform.isMacOS;
|
||||
|
||||
// Provider for the router
|
||||
final routerProvider = Provider<GoRouter>((ref) {
|
||||
@@ -286,30 +298,99 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
builder: (context, state) => const DeveloperHubScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerApps',
|
||||
path: '/developers/:name/apps',
|
||||
name: 'developerProjects',
|
||||
path: '/developers/:name/projects',
|
||||
builder:
|
||||
(context, state) => CustomAppsScreen(
|
||||
(context, state) => DevProjectsScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerAppNew',
|
||||
path: '/developers/:name/apps/new',
|
||||
name: 'developerProjectNew',
|
||||
path: '/developers/:name/projects/new',
|
||||
builder:
|
||||
(context, state) => NewCustomAppScreen(
|
||||
(context, state) => NewProjectScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerAppEdit',
|
||||
path: '/developers/:name/apps/:id',
|
||||
name: 'developerProjectEdit',
|
||||
path: '/developers/:name/projects/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditAppScreen(
|
||||
(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: 'developerBotDetail',
|
||||
path: 'bots/:botId',
|
||||
builder:
|
||||
(context, state) => BotDetailScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
botId: state.pathParameters['botId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotNew',
|
||||
path: 'bots/new',
|
||||
builder:
|
||||
(context, state) => NewBotScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'developerBotEdit',
|
||||
path: 'bots/:id/edit',
|
||||
builder:
|
||||
(context, state) => EditBotScreen(
|
||||
publisherName: state.pathParameters['name']!,
|
||||
projectId: state.pathParameters['projectId']!,
|
||||
id: state.pathParameters['id']!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -376,12 +457,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
builder: (context, state) => const PostSearchScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'postDetail',
|
||||
path: '/posts/:id',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id']!;
|
||||
return PostDetailScreen(id: id);
|
||||
},
|
||||
name: 'postShuffle',
|
||||
path: '/posts/shuffle',
|
||||
builder: (context, state) => const PostShuffleScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'postCategories',
|
||||
path: '/posts/categories',
|
||||
builder: (context, state) => const PostCategoriesListScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'postCategoryDetail',
|
||||
@@ -391,6 +474,11 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
return PostCategoryDetailScreen(slug: slug, isCategory: true);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'postTags',
|
||||
path: '/posts/tags',
|
||||
builder: (context, state) => const PostTagsListScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'postTagDetail',
|
||||
path: '/posts/tags/:slug',
|
||||
@@ -402,6 +490,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'postDetail',
|
||||
path: '/posts/:id',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id']!;
|
||||
return PostDetailScreen(id: id);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'publisherProfile',
|
||||
path: '/publishers/:name',
|
||||
@@ -459,6 +555,14 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
return ChatDetailScreen(id: id);
|
||||
},
|
||||
),
|
||||
GoRoute(
|
||||
name: 'searchMessages',
|
||||
path: '/chat/:id/search',
|
||||
builder: (context, state) {
|
||||
final id = state.pathParameters['id']!;
|
||||
return SearchMessagesScreen(roomId: id);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -528,6 +632,22 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
name: 'webFeedMarketplace',
|
||||
path: '/feeds',
|
||||
builder:
|
||||
(context, state) => const MarketplaceWebFeedsScreen(),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'webFeedDetail',
|
||||
path: ':feedId',
|
||||
builder: (context, state) {
|
||||
final feedId = state.pathParameters['feedId']!;
|
||||
return MarketplaceWebFeedDetailScreen(id: feedId);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
GoRoute(
|
||||
name: 'notifications',
|
||||
path: '/account/notifications',
|
||||
@@ -538,6 +658,11 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
path: '/account/wallet',
|
||||
builder: (context, state) => const WalletScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'socialCredits',
|
||||
path: '/account/credits',
|
||||
builder: (context, state) => const SocialCreditsScreen(),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'relationships',
|
||||
path: '/account/relationships',
|
||||
|
||||
@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/services/udid.native.dart';
|
||||
import 'package:island/services/udid.dart' as udid;
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
@@ -68,7 +68,7 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
|
||||
try {
|
||||
final deviceInfoPlugin = DeviceInfoPlugin();
|
||||
_deviceInfo = await deviceInfoPlugin.deviceInfo;
|
||||
_deviceUdid = await getUdid();
|
||||
_deviceUdid = await udid.getUdid();
|
||||
if (mounted) {
|
||||
setState(() {});
|
||||
}
|
||||
@@ -174,12 +174,20 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
|
||||
context,
|
||||
title: 'Device Information',
|
||||
children: [
|
||||
_buildInfoItem(
|
||||
context,
|
||||
icon: Symbols.label,
|
||||
label: 'aboutDeviceName'.tr(),
|
||||
value:
|
||||
_deviceInfo?.data['name'] ?? 'unknown'.tr(),
|
||||
FutureBuilder<String>(
|
||||
future: udid.getDeviceName(),
|
||||
builder: (context, snapshot) {
|
||||
final value =
|
||||
snapshot.hasData
|
||||
? snapshot.data!
|
||||
: 'unknown'.tr();
|
||||
return _buildInfoItem(
|
||||
context,
|
||||
icon: Symbols.label,
|
||||
label: 'aboutDeviceName'.tr(),
|
||||
value: value,
|
||||
);
|
||||
},
|
||||
),
|
||||
_buildInfoItem(
|
||||
context,
|
||||
|
||||
@@ -68,6 +68,7 @@ class AccountScreen extends HookConsumerWidget {
|
||||
body: SingleChildScrollView(
|
||||
padding: getTabbedPadding(context),
|
||||
child: Column(
|
||||
spacing: 4,
|
||||
children: <Widget>[
|
||||
Card(
|
||||
child: Column(
|
||||
@@ -112,20 +113,22 @@ class AccountScreen extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||
textBaseline: TextBaseline.alphabetic,
|
||||
children: [
|
||||
AccountName(
|
||||
account: user.value!,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
Flexible(
|
||||
child: AccountName(
|
||||
account: user.value!,
|
||||
style: TextStyle(
|
||||
fontSize: 16,
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
Text('@${user.value!.name}'),
|
||||
Flexible(child: Text('@${user.value!.name}')),
|
||||
],
|
||||
),
|
||||
Text(
|
||||
(user.value!.profile.bio.isNotEmpty)
|
||||
? user.value!.profile.bio
|
||||
: 'No description yet.',
|
||||
: 'descriptionNone'.tr(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -158,8 +161,16 @@ class AccountScreen extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Symbols.draw, size: 28).padding(bottom: 8),
|
||||
Text('creatorHub').tr().fontSize(16).bold(),
|
||||
Text('creatorHubDescription').tr(),
|
||||
Text(
|
||||
'creatorHub',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
).tr().fontSize(16).bold(),
|
||||
Text(
|
||||
'creatorHubDescription',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
).tr(),
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12),
|
||||
onTap: () {
|
||||
@@ -176,8 +187,16 @@ class AccountScreen extends HookConsumerWidget {
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Icon(Symbols.code, size: 28).padding(bottom: 8),
|
||||
Text('developerPortal').tr().fontSize(16).bold(),
|
||||
Text('developerPortalDescription').tr(),
|
||||
Text(
|
||||
'developerPortal',
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
).tr().fontSize(16).bold(),
|
||||
Text(
|
||||
'developerPortalDescription',
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
).tr(),
|
||||
],
|
||||
).padding(horizontal: 16, vertical: 12),
|
||||
onTap: () {
|
||||
@@ -236,6 +255,26 @@ class AccountScreen extends HookConsumerWidget {
|
||||
context.pushNamed('stickerMarketplace');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.rss_feed),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('webFeeds').tr(),
|
||||
onTap: () {
|
||||
context.pushNamed('webFeedMarketplace');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
leading: const Icon(Symbols.star),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('credits').tr(),
|
||||
onTap: () {
|
||||
context.pushNamed('socialCredits');
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
minTileHeight: 48,
|
||||
title: Text('abuseReport').tr(),
|
||||
@@ -389,6 +428,15 @@ class _UnauthorizedAccountScreen extends StatelessWidget {
|
||||
},
|
||||
child: Text('about').tr(),
|
||||
),
|
||||
TextButton(
|
||||
child: Text('debugOptions').tr(),
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
builder: (context) => DebugSheet(),
|
||||
);
|
||||
},
|
||||
),
|
||||
TextButton(
|
||||
onPressed: () {
|
||||
context.pushNamed('settings');
|
||||
|
||||
152
lib/screens/account/credits.dart
Normal file
152
lib/screens/account/credits.dart
Normal file
@@ -0,0 +1,152 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
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');
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception('Failed to load social credits');
|
||||
}
|
||||
return response.data?.toDouble() ?? 0.0;
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class SocialCreditHistoryNotifier extends _$SocialCreditHistoryNotifier
|
||||
with CursorPagingNotifierMixin<SnSocialCreditRecord> {
|
||||
static const int _pageSize = 20;
|
||||
|
||||
@override
|
||||
Future<CursorPagingData<SnSocialCreditRecord>> build() => fetch(cursor: null);
|
||||
|
||||
@override
|
||||
Future<CursorPagingData<SnSocialCreditRecord>> fetch({
|
||||
required String? cursor,
|
||||
}) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||
|
||||
final queryParams = {'offset': offset, 'take': _pageSize};
|
||||
|
||||
final response = await client.get(
|
||||
'/id/accounts/me/credits/history',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
final List<dynamic> data = response.data;
|
||||
final records =
|
||||
data.map((json) => SnSocialCreditRecord.fromJson(json)).toList();
|
||||
|
||||
final hasMore = offset + records.length < total;
|
||||
final nextCursor = hasMore ? (offset + records.length).toString() : null;
|
||||
|
||||
return CursorPagingData(
|
||||
items: records,
|
||||
hasMore: hasMore,
|
||||
nextCursor: nextCursor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class SocialCreditsScreen extends HookConsumerWidget {
|
||||
const SocialCreditsScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final socialCredits = ref.watch(socialCreditsProvider);
|
||||
|
||||
return AppScaffold(
|
||||
appBar: AppBar(title: Text('socialCredits').tr()),
|
||||
body: Column(
|
||||
children: [
|
||||
Card(
|
||||
margin: EdgeInsets.only(left: 16, right: 16, top: 8),
|
||||
child: socialCredits
|
||||
.when(
|
||||
data:
|
||||
(credits) => Stack(
|
||||
children: [
|
||||
Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Text(
|
||||
credits < 100
|
||||
? 'socialCreditsLevelPoor'.tr()
|
||||
: credits < 150
|
||||
? 'socialCreditsLevelNormal'.tr()
|
||||
: credits < 200
|
||||
? 'socialCreditsLevelGood'.tr()
|
||||
: 'socialCreditsLevelExcellent'.tr(),
|
||||
).tr().bold().fontSize(20),
|
||||
Text(
|
||||
'${credits.toStringAsFixed(2)} pts',
|
||||
).fontSize(14),
|
||||
const Gap(8),
|
||||
LinearProgressIndicator(value: credits / 200),
|
||||
],
|
||||
),
|
||||
Positioned(
|
||||
right: 0,
|
||||
top: 0,
|
||||
child: IconButton(
|
||||
onPressed: () {},
|
||||
icon: const Icon(Symbols.info),
|
||||
tooltip: 'socialCreditsDescription'.tr(),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
error: (_, _) => Text('Error loading credits'),
|
||||
loading: () => const LinearProgressIndicator(),
|
||||
)
|
||||
.padding(horizontal: 20, vertical: 16),
|
||||
),
|
||||
Expanded(
|
||||
child: PagingHelperView(
|
||||
provider: socialCreditHistoryNotifierProvider,
|
||||
futureRefreshable: socialCreditHistoryNotifierProvider.future,
|
||||
notifierRefreshable: socialCreditHistoryNotifierProvider.notifier,
|
||||
contentBuilder:
|
||||
(data, widgetCount, endItemView) => ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: widgetCount,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == widgetCount - 1) {
|
||||
return endItemView;
|
||||
}
|
||||
final record = data.items[index];
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text(record.reason),
|
||||
subtitle: Text(
|
||||
DateFormat.yMMMd().format(record.createdAt),
|
||||
),
|
||||
trailing: Text(
|
||||
record.delta > 0
|
||||
? '+${record.delta}'
|
||||
: '${record.delta}',
|
||||
style: TextStyle(
|
||||
color: record.delta > 0 ? Colors.green : Colors.red,
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
49
lib/screens/account/credits.g.dart
Normal file
49
lib/screens/account/credits.g.dart
Normal file
@@ -0,0 +1,49 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'credits.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$socialCreditsHash() => r'2599844e892127ee4d315caced5c10e4dbaea142';
|
||||
|
||||
/// See also [socialCredits].
|
||||
@ProviderFor(socialCredits)
|
||||
final socialCreditsProvider = AutoDisposeFutureProvider<double>.internal(
|
||||
socialCredits,
|
||||
name: r'socialCreditsProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$socialCreditsHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
typedef SocialCreditsRef = AutoDisposeFutureProviderRef<double>;
|
||||
String _$socialCreditHistoryNotifierHash() =>
|
||||
r'950db020754160f835c64cedf3fa2175e61e4d64';
|
||||
|
||||
/// See also [SocialCreditHistoryNotifier].
|
||||
@ProviderFor(SocialCreditHistoryNotifier)
|
||||
final socialCreditHistoryNotifierProvider = AutoDisposeAsyncNotifierProvider<
|
||||
SocialCreditHistoryNotifier,
|
||||
CursorPagingData<SnSocialCreditRecord>
|
||||
>.internal(
|
||||
SocialCreditHistoryNotifier.new,
|
||||
name: r'socialCreditHistoryNotifierProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$socialCreditHistoryNotifierHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$SocialCreditHistoryNotifier =
|
||||
AutoDisposeAsyncNotifier<CursorPagingData<SnSocialCreditRecord>>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
@@ -6,6 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:google_fonts/google_fonts.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/models/wallet.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
@@ -19,6 +20,7 @@ import 'package:island/widgets/payment/payment_overlay.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
part 'leveling.g.dart';
|
||||
@@ -35,13 +37,49 @@ Future<SnWalletSubscription?> accountStellarSubscription(Ref ref) async {
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class LevelingHistoryNotifier extends _$LevelingHistoryNotifier
|
||||
with CursorPagingNotifierMixin<SnExperienceRecord> {
|
||||
static const int _pageSize = 20;
|
||||
|
||||
@override
|
||||
Future<CursorPagingData<SnExperienceRecord>> build() => fetch(cursor: null);
|
||||
|
||||
@override
|
||||
Future<CursorPagingData<SnExperienceRecord>> fetch({
|
||||
required String? cursor,
|
||||
}) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||
|
||||
final queryParams = {'offset': offset, 'take': _pageSize};
|
||||
|
||||
final response = await client.get(
|
||||
'/id/accounts/me/leveling',
|
||||
queryParameters: queryParams,
|
||||
);
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
final List<dynamic> data = response.data;
|
||||
final records =
|
||||
data.map((json) => SnExperienceRecord.fromJson(json)).toList();
|
||||
|
||||
final hasMore = offset + records.length < total;
|
||||
final nextCursor = hasMore ? (offset + records.length).toString() : null;
|
||||
|
||||
return CursorPagingData(
|
||||
items: records,
|
||||
hasMore: hasMore,
|
||||
nextCursor: nextCursor,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class LevelingScreen extends HookConsumerWidget {
|
||||
const LevelingScreen({super.key});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final user = ref.watch(userInfoProvider);
|
||||
final stellarSubscription = ref.watch(accountStellarSubscriptionProvider);
|
||||
|
||||
if (user.value == null) {
|
||||
return AppScaffold(
|
||||
@@ -50,47 +88,166 @@ class LevelingScreen extends HookConsumerWidget {
|
||||
);
|
||||
}
|
||||
|
||||
final currentLevel = user.value!.profile.level;
|
||||
final currentExp = user.value!.profile.experience;
|
||||
final progress = user.value!.profile.levelingProgress;
|
||||
|
||||
return AppScaffold(
|
||||
appBar: AppBar(title: Text('levelingProgress'.tr())),
|
||||
body: SingleChildScrollView(
|
||||
padding: getTabbedPadding(context, horizontal: 20, vertical: 20),
|
||||
child: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 480),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
// Current Progress Card
|
||||
LevelingProgressCard(
|
||||
level: currentLevel,
|
||||
experience: currentExp,
|
||||
progress: progress,
|
||||
),
|
||||
const Gap(24),
|
||||
|
||||
// Level Stairs Graph
|
||||
Text(
|
||||
'levelProgress'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
return DefaultTabController(
|
||||
length: 2,
|
||||
child: AppScaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('levelingProgress'.tr()),
|
||||
bottom: TabBar(
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Text(
|
||||
'leveling'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||
),
|
||||
),
|
||||
const Gap(16),
|
||||
),
|
||||
Tab(
|
||||
child: Text(
|
||||
'stellarProgram'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: TabBarView(
|
||||
children: [
|
||||
_buildLevelingTab(context, ref, user.value!),
|
||||
_buildStellarProgramTab(context, ref),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
// Stairs visualization with fixed height and horizontal scroll
|
||||
_buildLevelStairs(context, currentLevel),
|
||||
Widget _buildLevelingTab(
|
||||
BuildContext context,
|
||||
WidgetRef ref,
|
||||
SnAccount user,
|
||||
) {
|
||||
final currentLevel = user.profile.level;
|
||||
final currentExp = user.profile.experience;
|
||||
final progress = user.profile.levelingProgress;
|
||||
|
||||
const Gap(24),
|
||||
return Center(
|
||||
child: Container(
|
||||
padding: const EdgeInsets.symmetric(horizontal: 20),
|
||||
constraints: const BoxConstraints(maxWidth: 480),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
const SliverGap(20),
|
||||
|
||||
// Membership section
|
||||
_buildMembershipSection(context, ref, stellarSubscription),
|
||||
const Gap(16),
|
||||
],
|
||||
// Current Progress Card
|
||||
SliverToBoxAdapter(
|
||||
child: LevelingProgressCard(
|
||||
level: currentLevel,
|
||||
experience: currentExp,
|
||||
progress: progress,
|
||||
),
|
||||
),
|
||||
const SliverGap(24),
|
||||
|
||||
// Level Stairs Graph
|
||||
SliverToBoxAdapter(
|
||||
child: Text(
|
||||
'levelProgress'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SliverGap(16),
|
||||
|
||||
// Stairs visualization with fixed height and horizontal scroll
|
||||
SliverToBoxAdapter(child: _buildLevelStairs(context, currentLevel)),
|
||||
const SliverGap(24),
|
||||
|
||||
// Leveling History
|
||||
SliverToBoxAdapter(
|
||||
child: Text(
|
||||
'levelingHistory'.tr(),
|
||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
||||
fontWeight: FontWeight.bold,
|
||||
),
|
||||
),
|
||||
),
|
||||
const SliverGap(8),
|
||||
PagingHelperSliverView(
|
||||
provider: levelingHistoryNotifierProvider,
|
||||
futureRefreshable: levelingHistoryNotifierProvider.future,
|
||||
notifierRefreshable: levelingHistoryNotifierProvider.notifier,
|
||||
contentBuilder:
|
||||
(data, widgetCount, endItemView) => SliverList.builder(
|
||||
itemCount: widgetCount,
|
||||
itemBuilder: (context, index) {
|
||||
if (index == widgetCount - 1) {
|
||||
return endItemView;
|
||||
}
|
||||
final record = data.items[index];
|
||||
return ListTile(
|
||||
title: Column(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Text(record.reason),
|
||||
Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Text(
|
||||
record.createdAt.formatRelative(context),
|
||||
).fontSize(13),
|
||||
Text('·').fontSize(13).bold(),
|
||||
Text(
|
||||
record.createdAt.formatSystem(),
|
||||
).fontSize(13),
|
||||
],
|
||||
).opacity(0.8),
|
||||
],
|
||||
),
|
||||
subtitle: Row(
|
||||
spacing: 8,
|
||||
children: [
|
||||
Text(
|
||||
'${record.delta > 0 ? '+' : ''}${record.delta} EXP',
|
||||
),
|
||||
if (record.bonusMultiplier != 1.0)
|
||||
Text('x${record.bonusMultiplier}'),
|
||||
],
|
||||
),
|
||||
minTileHeight: 56,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 4),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
|
||||
SliverGap(getTabbedPadding(context, vertical: 20).vertical),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Widget _buildStellarProgramTab(BuildContext context, WidgetRef ref) {
|
||||
final stellarSubscription = ref.watch(accountStellarSubscriptionProvider);
|
||||
|
||||
return SingleChildScrollView(
|
||||
padding: getTabbedPadding(context, horizontal: 20, vertical: 20),
|
||||
child: Center(
|
||||
child: ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 480),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
_buildMembershipSection(context, ref, stellarSubscription),
|
||||
const Gap(16),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
@@ -632,11 +789,8 @@ class LevelingScreen extends HookConsumerWidget {
|
||||
if (context.mounted) showLoadingModal(context);
|
||||
|
||||
if (paidOrder != null) {
|
||||
await client.post(
|
||||
'/id/subscriptions/order/handle',
|
||||
data: {'order_id': paidOrder.id},
|
||||
);
|
||||
|
||||
// Wait for server to handle order
|
||||
await Future.delayed(const Duration(seconds: 1));
|
||||
ref.invalidate(accountStellarSubscriptionProvider);
|
||||
ref.read(userInfoProvider.notifier).fetchUser();
|
||||
if (context.mounted) {
|
||||
|
||||
@@ -27,5 +27,26 @@ final accountStellarSubscriptionProvider =
|
||||
// ignore: unused_element
|
||||
typedef AccountStellarSubscriptionRef =
|
||||
AutoDisposeFutureProviderRef<SnWalletSubscription?>;
|
||||
String _$levelingHistoryNotifierHash() =>
|
||||
r'e795f9b7911c9e50f15c095ea237cb0e87bf1e89';
|
||||
|
||||
/// See also [LevelingHistoryNotifier].
|
||||
@ProviderFor(LevelingHistoryNotifier)
|
||||
final levelingHistoryNotifierProvider = AutoDisposeAsyncNotifierProvider<
|
||||
LevelingHistoryNotifier,
|
||||
CursorPagingData<SnExperienceRecord>
|
||||
>.internal(
|
||||
LevelingHistoryNotifier.new,
|
||||
name: r'levelingHistoryNotifierProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$levelingHistoryNotifierHash,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
);
|
||||
|
||||
typedef _$LevelingHistoryNotifier =
|
||||
AutoDisposeAsyncNotifier<CursorPagingData<SnExperienceRecord>>;
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/auth.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
@@ -14,7 +15,6 @@ import 'package:island/screens/account/me/settings_connections.dart';
|
||||
import 'package:island/screens/account/me/settings_contacts.dart';
|
||||
import 'package:island/screens/auth/captcha.dart';
|
||||
import 'package:island/screens/auth/login.dart';
|
||||
import 'package:island/services/responsive.dart';
|
||||
import 'package:island/widgets/account/account_devices.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
@@ -57,7 +57,6 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final isDesktop =
|
||||
!kIsWeb && (Platform.isWindows || Platform.isMacOS || Platform.isLinux);
|
||||
final isWide = isWideScreen(context);
|
||||
|
||||
Future<void> requestAccountDeletion() async {
|
||||
final confirm = await showConfirmAlert(
|
||||
@@ -440,51 +439,19 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
||||
|
||||
// Create a responsive layout based on screen width
|
||||
Widget buildSettingsList() {
|
||||
if (isWide) {
|
||||
// Two-column layout for wide screens
|
||||
return Row(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_SettingsSection(
|
||||
title: 'accountSecurityTitle',
|
||||
children: securitySettings,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_SettingsSection(
|
||||
title: 'accountDangerZoneTitle',
|
||||
children: dangerZoneSettings,
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
} else {
|
||||
// Single column layout for narrow screens
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_SettingsSection(
|
||||
title: 'accountSecurityTitle',
|
||||
children: securitySettings,
|
||||
),
|
||||
_SettingsSection(
|
||||
title: 'accountDangerZoneTitle',
|
||||
children: dangerZoneSettings,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
return Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
_SettingsSection(
|
||||
title: 'accountSecurityTitle',
|
||||
children: securitySettings,
|
||||
),
|
||||
_SettingsSection(
|
||||
title: 'accountDangerZoneTitle',
|
||||
children: dangerZoneSettings,
|
||||
),
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
return AppScaffold(
|
||||
@@ -513,6 +480,7 @@ class AccountSettingsScreen extends HookConsumerWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
const Gap(8),
|
||||
]
|
||||
: null,
|
||||
),
|
||||
|
||||
@@ -21,6 +21,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
const kServerSupportedLanguages = {'en-US': 'en-us', 'zh-CN': 'zh-hans'};
|
||||
const kServerSupportedRegions = ['US', 'JP', 'CN'];
|
||||
|
||||
class UpdateProfileScreen extends HookConsumerWidget {
|
||||
const UpdateProfileScreen({super.key});
|
||||
@@ -97,6 +98,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
final usernameController = useTextEditingController(text: user.value!.name);
|
||||
final nicknameController = useTextEditingController(text: user.value!.nick);
|
||||
final language = useState(user.value!.language);
|
||||
final region = useState(user.value!.region);
|
||||
final links = useState<List<ProfileLink>>(user.value!.profile.links);
|
||||
|
||||
void updateBasicInfo() async {
|
||||
@@ -111,6 +113,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
'name': usernameController.text,
|
||||
'nick': nicknameController.text,
|
||||
'language': language.value,
|
||||
'region': region.value,
|
||||
},
|
||||
);
|
||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||
@@ -291,6 +294,32 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
],
|
||||
),
|
||||
),
|
||||
DropdownButtonFormField2<String>(
|
||||
decoration: InputDecoration(
|
||||
labelText: 'region'.tr(),
|
||||
helperText: 'accountRegionHint'.tr(),
|
||||
),
|
||||
items: [
|
||||
...kServerSupportedRegions.map(
|
||||
(e) => DropdownMenuItem(value: e, child: Text(e)),
|
||||
),
|
||||
if (!kServerSupportedRegions.contains(region.value))
|
||||
DropdownMenuItem(
|
||||
value: region.value,
|
||||
child: Text(region.value),
|
||||
),
|
||||
],
|
||||
value: region.value,
|
||||
onChanged: (value) {
|
||||
region.value = value ?? region.value;
|
||||
},
|
||||
customButton: Row(
|
||||
children: [
|
||||
Expanded(child: Text(region.value)),
|
||||
Icon(Symbols.arrow_drop_down),
|
||||
],
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: TextButton.icon(
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:flutter_svg/flutter_svg.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/auth.dart';
|
||||
import 'package:island/pods/config.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/screens/account/me/account_settings.dart';
|
||||
import 'package:island/screens/auth/oidc.native.dart';
|
||||
import 'package:island/services/text.dart';
|
||||
import 'package:island/utils/text.dart';
|
||||
import 'package:island/services/time.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
@@ -16,6 +18,7 @@ import 'package:island/widgets/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:sign_in_with_apple/sign_in_with_apple.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
|
||||
// Helper function to get provider icon and localized name
|
||||
Widget getProviderIcon(String provider, {double size = 24, Color? color}) {
|
||||
@@ -165,9 +168,7 @@ class AccountConnectionNewSheet extends HookConsumerWidget {
|
||||
scopes: [AppleIDAuthorizationScopes.email],
|
||||
webAuthenticationOptions: WebAuthenticationOptions(
|
||||
clientId: 'dev.solsynth.solarpass',
|
||||
redirectUri: Uri.parse(
|
||||
'https://id.solian.app/auth/callback/apple',
|
||||
),
|
||||
redirectUri: Uri.parse('https://id.solian.app/auth/callback'),
|
||||
),
|
||||
);
|
||||
|
||||
@@ -195,17 +196,25 @@ class AccountConnectionNewSheet extends HookConsumerWidget {
|
||||
case 'github':
|
||||
case 'discord':
|
||||
case 'afdian':
|
||||
await Navigator.of(context, rootNavigator: true).push(
|
||||
MaterialPageRoute(
|
||||
builder:
|
||||
(context) => OidcScreen(
|
||||
provider: selectedProvider.value.toLowerCase(),
|
||||
title:
|
||||
'Connect with ${selectedProvider.value.capitalizeEachWord()}',
|
||||
),
|
||||
),
|
||||
);
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
if (kIsWeb) {
|
||||
final serverUrl = ref.watch(serverUrlProvider);
|
||||
final accessToken = ref.watch(tokenProvider);
|
||||
launchUrlString(
|
||||
'$serverUrl/id/auth/login/${selectedProvider.value}?tk=${accessToken!.token}',
|
||||
);
|
||||
} else {
|
||||
await Navigator.of(context, rootNavigator: true).push(
|
||||
MaterialPageRoute(
|
||||
builder:
|
||||
(context) => OidcScreen(
|
||||
provider: selectedProvider.value.toLowerCase(),
|
||||
title:
|
||||
'Connect with ${selectedProvider.value.capitalizeEachWord()}',
|
||||
),
|
||||
),
|
||||
);
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
showSnackBar('accountConnectionAddError'.tr());
|
||||
|
||||
@@ -62,6 +62,32 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> makeContactMethodPublic() async {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.post('/id/accounts/me/contacts/${contact.id}/public');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
if (context.mounted) hideLoadingModal(context);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> makeContactMethodPrivate() async {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete('/id/accounts/me/contacts/${contact.id}/public');
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
if (context.mounted) hideLoadingModal(context);
|
||||
}
|
||||
}
|
||||
|
||||
return SheetScaffold(
|
||||
titleText: 'contactMethod'.tr(),
|
||||
child: Column(
|
||||
@@ -111,6 +137,27 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
backgroundColor: Theme.of(context).colorScheme.tertiary,
|
||||
),
|
||||
),
|
||||
if (contact.isPublic)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Badge(
|
||||
label: Text('contactMethodPublic'.tr()),
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
if (!contact.isPublic)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(left: 8.0),
|
||||
child: Badge(
|
||||
label: Text('contactMethodPrivate'.tr()),
|
||||
textColor: Theme.of(context).colorScheme.onSurface,
|
||||
backgroundColor:
|
||||
Theme.of(
|
||||
context,
|
||||
).colorScheme.surfaceContainerHighest,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
@@ -130,6 +177,20 @@ class ContactMethodSheet extends HookConsumerWidget {
|
||||
onTap: setContactMethodAsPrimary,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
||||
),
|
||||
if (contact.verifiedAt != null && !contact.isPublic)
|
||||
ListTile(
|
||||
leading: const Icon(Symbols.public),
|
||||
title: Text('contactMethodMakePublic').tr(),
|
||||
onTap: makeContactMethodPublic,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
||||
),
|
||||
if (contact.verifiedAt != null && contact.isPublic)
|
||||
ListTile(
|
||||
leading: const Icon(Symbols.visibility_off),
|
||||
title: Text('contactMethodMakePrivate').tr(),
|
||||
onTap: makeContactMethodPrivate,
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 20),
|
||||
),
|
||||
ListTile(
|
||||
leading: const Icon(Symbols.delete),
|
||||
title: Text('contactMethodDelete').tr(),
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -639,5 +639,250 @@ class _AccountRelationshipProviderElement
|
||||
String get uname => (origin as AccountRelationshipProvider).uname;
|
||||
}
|
||||
|
||||
String _$accountBotDeveloperHash() =>
|
||||
r'673534770640a8cf1484ea0af0f4d0ef283ef157';
|
||||
|
||||
/// See also [accountBotDeveloper].
|
||||
@ProviderFor(accountBotDeveloper)
|
||||
const accountBotDeveloperProvider = AccountBotDeveloperFamily();
|
||||
|
||||
/// See also [accountBotDeveloper].
|
||||
class AccountBotDeveloperFamily extends Family<AsyncValue<SnDeveloper?>> {
|
||||
/// See also [accountBotDeveloper].
|
||||
const AccountBotDeveloperFamily();
|
||||
|
||||
/// See also [accountBotDeveloper].
|
||||
AccountBotDeveloperProvider call(String uname) {
|
||||
return AccountBotDeveloperProvider(uname);
|
||||
}
|
||||
|
||||
@override
|
||||
AccountBotDeveloperProvider getProviderOverride(
|
||||
covariant AccountBotDeveloperProvider provider,
|
||||
) {
|
||||
return call(provider.uname);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'accountBotDeveloperProvider';
|
||||
}
|
||||
|
||||
/// See also [accountBotDeveloper].
|
||||
class AccountBotDeveloperProvider
|
||||
extends AutoDisposeFutureProvider<SnDeveloper?> {
|
||||
/// See also [accountBotDeveloper].
|
||||
AccountBotDeveloperProvider(String uname)
|
||||
: this._internal(
|
||||
(ref) => accountBotDeveloper(ref as AccountBotDeveloperRef, uname),
|
||||
from: accountBotDeveloperProvider,
|
||||
name: r'accountBotDeveloperProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$accountBotDeveloperHash,
|
||||
dependencies: AccountBotDeveloperFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
AccountBotDeveloperFamily._allTransitiveDependencies,
|
||||
uname: uname,
|
||||
);
|
||||
|
||||
AccountBotDeveloperProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.uname,
|
||||
}) : super.internal();
|
||||
|
||||
final String uname;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<SnDeveloper?> Function(AccountBotDeveloperRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: AccountBotDeveloperProvider._internal(
|
||||
(ref) => create(ref as AccountBotDeveloperRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
uname: uname,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<SnDeveloper?> createElement() {
|
||||
return _AccountBotDeveloperProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is AccountBotDeveloperProvider && other.uname == uname;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, uname.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin AccountBotDeveloperRef on AutoDisposeFutureProviderRef<SnDeveloper?> {
|
||||
/// The parameter `uname` of this provider.
|
||||
String get uname;
|
||||
}
|
||||
|
||||
class _AccountBotDeveloperProviderElement
|
||||
extends AutoDisposeFutureProviderElement<SnDeveloper?>
|
||||
with AccountBotDeveloperRef {
|
||||
_AccountBotDeveloperProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get uname => (origin as AccountBotDeveloperProvider).uname;
|
||||
}
|
||||
|
||||
String _$accountPublishersHash() => r'25f5695b4a5154163d77f1769876d826bf736609';
|
||||
|
||||
/// See also [accountPublishers].
|
||||
@ProviderFor(accountPublishers)
|
||||
const accountPublishersProvider = AccountPublishersFamily();
|
||||
|
||||
/// See also [accountPublishers].
|
||||
class AccountPublishersFamily extends Family<AsyncValue<List<SnPublisher>>> {
|
||||
/// See also [accountPublishers].
|
||||
const AccountPublishersFamily();
|
||||
|
||||
/// See also [accountPublishers].
|
||||
AccountPublishersProvider call(String id) {
|
||||
return AccountPublishersProvider(id);
|
||||
}
|
||||
|
||||
@override
|
||||
AccountPublishersProvider getProviderOverride(
|
||||
covariant AccountPublishersProvider provider,
|
||||
) {
|
||||
return call(provider.id);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'accountPublishersProvider';
|
||||
}
|
||||
|
||||
/// See also [accountPublishers].
|
||||
class AccountPublishersProvider
|
||||
extends AutoDisposeFutureProvider<List<SnPublisher>> {
|
||||
/// See also [accountPublishers].
|
||||
AccountPublishersProvider(String id)
|
||||
: this._internal(
|
||||
(ref) => accountPublishers(ref as AccountPublishersRef, id),
|
||||
from: accountPublishersProvider,
|
||||
name: r'accountPublishersProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$accountPublishersHash,
|
||||
dependencies: AccountPublishersFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
AccountPublishersFamily._allTransitiveDependencies,
|
||||
id: id,
|
||||
);
|
||||
|
||||
AccountPublishersProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.id,
|
||||
}) : super.internal();
|
||||
|
||||
final String id;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<List<SnPublisher>> Function(AccountPublishersRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: AccountPublishersProvider._internal(
|
||||
(ref) => create(ref as AccountPublishersRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
id: id,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<List<SnPublisher>> createElement() {
|
||||
return _AccountPublishersProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is AccountPublishersProvider && other.id == id;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, id.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin AccountPublishersRef on AutoDisposeFutureProviderRef<List<SnPublisher>> {
|
||||
/// The parameter `id` of this provider.
|
||||
String get id;
|
||||
}
|
||||
|
||||
class _AccountPublishersProviderElement
|
||||
extends AutoDisposeFutureProviderElement<List<SnPublisher>>
|
||||
with AccountPublishersRef {
|
||||
_AccountPublishersProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get id => (origin as AccountPublishersProvider).id;
|
||||
}
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:flutter/services.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/widgets/account/account_pfc.dart';
|
||||
import 'package:island/widgets/account/account_picker.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
@@ -99,7 +100,10 @@ class RelationshipListTile extends StatelessWidget {
|
||||
|
||||
return ListTile(
|
||||
contentPadding: const EdgeInsets.only(left: 16, right: 12),
|
||||
leading: ProfilePictureWidget(fileId: account.profile.picture?.id),
|
||||
leading: AccountPfcGestureDetector(
|
||||
uname: account.name,
|
||||
child: ProfilePictureWidget(fileId: account.profile.picture?.id),
|
||||
),
|
||||
title: Row(
|
||||
spacing: 6,
|
||||
children: [
|
||||
|
||||
@@ -1,9 +1,6 @@
|
||||
import 'dart:convert';
|
||||
import 'dart:io';
|
||||
import 'dart:math' as math;
|
||||
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:device_info_plus/device_info_plus.dart';
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/foundation.dart';
|
||||
@@ -42,22 +39,6 @@ final Map<int, (String, String, IconData)> kFactorTypes = {
|
||||
4: ('authFactorPin', 'authFactorPinDescription', Symbols.nest_secure_alarm),
|
||||
};
|
||||
|
||||
Future<String?> getDeviceName() async {
|
||||
if (kIsWeb) return null;
|
||||
String? name;
|
||||
if (Platform.isIOS) {
|
||||
final deviceInfo = await DeviceInfoPlugin().iosInfo;
|
||||
name = deviceInfo.name;
|
||||
} else if (Platform.isAndroid) {
|
||||
final deviceInfo = await DeviceInfoPlugin().androidInfo;
|
||||
name = deviceInfo.name;
|
||||
} else if (Platform.isWindows) {
|
||||
final deviceInfo = await DeviceInfoPlugin().windowsInfo;
|
||||
name = deviceInfo.computerName;
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
class LoginScreen extends HookConsumerWidget {
|
||||
const LoginScreen({super.key});
|
||||
|
||||
@@ -700,45 +681,48 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
onSubmitted: isBusy.value ? null : (_) => performNewTicket(),
|
||||
).padding(horizontal: 7),
|
||||
Row(
|
||||
spacing: 6,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text("loginOr").tr().fontSize(11).opacity(0.85),
|
||||
const Gap(8),
|
||||
Spacer(),
|
||||
IconButton.filledTonal(
|
||||
onPressed: () => withOidc('github'),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: getProviderIcon(
|
||||
"github",
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
if (!kIsWeb)
|
||||
Row(
|
||||
spacing: 6,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: <Widget>[
|
||||
Text("loginOr").tr().fontSize(11).opacity(0.85),
|
||||
const Gap(8),
|
||||
Spacer(),
|
||||
IconButton.filledTonal(
|
||||
onPressed: () => withOidc('github'),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: getProviderIcon(
|
||||
"github",
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
),
|
||||
tooltip: 'GitHub',
|
||||
),
|
||||
tooltip: 'GitHub',
|
||||
),
|
||||
IconButton.filledTonal(
|
||||
onPressed: () => withOidc('google'),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: getProviderIcon(
|
||||
"google",
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
IconButton.filledTonal(
|
||||
onPressed: () => withOidc('google'),
|
||||
padding: EdgeInsets.zero,
|
||||
icon: getProviderIcon(
|
||||
"google",
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
),
|
||||
tooltip: 'Google',
|
||||
),
|
||||
tooltip: 'Google',
|
||||
),
|
||||
IconButton.filledTonal(
|
||||
onPressed: withApple,
|
||||
padding: EdgeInsets.zero,
|
||||
icon: getProviderIcon(
|
||||
"apple",
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
IconButton.filledTonal(
|
||||
onPressed: withApple,
|
||||
padding: EdgeInsets.zero,
|
||||
icon: getProviderIcon(
|
||||
"apple",
|
||||
size: 16,
|
||||
color: Theme.of(context).colorScheme.onPrimaryContainer,
|
||||
),
|
||||
tooltip: 'Apple Account',
|
||||
),
|
||||
tooltip: 'Apple Account',
|
||||
),
|
||||
],
|
||||
).padding(horizontal: 8, vertical: 8),
|
||||
],
|
||||
).padding(horizontal: 8, vertical: 8)
|
||||
else
|
||||
const Gap(12),
|
||||
Row(
|
||||
mainAxisAlignment: MainAxisAlignment.spaceBetween,
|
||||
children: [
|
||||
|
||||
@@ -79,33 +79,38 @@ class ChatRoomListTile extends HookConsumerWidget {
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Badge(
|
||||
label: Text(data.lastMessage.sender.account.nick),
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
Expanded(
|
||||
child: Text(
|
||||
(data.lastMessage.content?.isNotEmpty ?? false)
|
||||
? data.lastMessage.content!
|
||||
: 'messageNone'.tr(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
if (data.lastMessage == null)
|
||||
Text(room.description ?? 'descriptionNone'.tr(), maxLines: 1)
|
||||
else
|
||||
Row(
|
||||
spacing: 4,
|
||||
children: [
|
||||
Badge(
|
||||
label: Text(data.lastMessage!.sender.account.nick),
|
||||
textColor: Theme.of(context).colorScheme.onPrimary,
|
||||
backgroundColor: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
RelativeTime(context).format(data.lastMessage.createdAt),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
Expanded(
|
||||
child: Text(
|
||||
(data.lastMessage!.content?.isNotEmpty ?? false)
|
||||
? data.lastMessage!.content!
|
||||
: 'messageNone'.tr(),
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
Align(
|
||||
alignment: Alignment.centerRight,
|
||||
child: Text(
|
||||
RelativeTime(
|
||||
context,
|
||||
).format(data.lastMessage!.createdAt),
|
||||
style: Theme.of(context).textTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
||||
@@ -4,6 +4,7 @@ import "dart:developer" as developer;
|
||||
import "dart:io";
|
||||
import "package:dio/dio.dart";
|
||||
import "package:easy_localization/easy_localization.dart";
|
||||
import "package:file_picker/file_picker.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:go_router/go_router.dart";
|
||||
@@ -72,6 +73,207 @@ class _AppLifecycleObserver extends WidgetsBindingObserver {
|
||||
}
|
||||
}
|
||||
|
||||
class _PublicRoomPreview extends HookConsumerWidget {
|
||||
final String id;
|
||||
final SnChatRoom room;
|
||||
|
||||
const _PublicRoomPreview({required this.id, required this.room});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final messages = ref.watch(messagesNotifierProvider(id));
|
||||
final messagesNotifier = ref.read(messagesNotifierProvider(id).notifier);
|
||||
final scrollController = useScrollController();
|
||||
|
||||
final listController = useMemoized(() => ListController(), []);
|
||||
|
||||
var isLoading = false;
|
||||
|
||||
// Add scroll listener for pagination
|
||||
useEffect(() {
|
||||
void onScroll() {
|
||||
if (scrollController.position.pixels >=
|
||||
scrollController.position.maxScrollExtent - 200) {
|
||||
if (isLoading) return;
|
||||
isLoading = true;
|
||||
messagesNotifier.loadMore().then((_) => isLoading = false);
|
||||
}
|
||||
}
|
||||
|
||||
scrollController.addListener(onScroll);
|
||||
return () => scrollController.removeListener(onScroll);
|
||||
}, [scrollController]);
|
||||
|
||||
Widget chatMessageListWidget(List<LocalChatMessage> messageList) =>
|
||||
SuperListView.builder(
|
||||
listController: listController,
|
||||
padding: EdgeInsets.symmetric(vertical: 16),
|
||||
controller: scrollController,
|
||||
reverse: true, // Show newest messages at the bottom
|
||||
itemCount: messageList.length,
|
||||
findChildIndexCallback: (key) {
|
||||
final valueKey = key as ValueKey;
|
||||
final messageId = valueKey.value as String;
|
||||
return messageList.indexWhere((m) => m.id == messageId);
|
||||
},
|
||||
extentEstimation: (_, _) => 40,
|
||||
itemBuilder: (context, index) {
|
||||
final message = messageList[index];
|
||||
final nextMessage =
|
||||
index < messageList.length - 1 ? messageList[index + 1] : null;
|
||||
final isLastInGroup =
|
||||
nextMessage == null ||
|
||||
nextMessage.senderId != message.senderId ||
|
||||
nextMessage.createdAt
|
||||
.difference(message.createdAt)
|
||||
.inMinutes
|
||||
.abs() >
|
||||
3;
|
||||
|
||||
return MessageItem(
|
||||
message: message,
|
||||
isCurrentUser: false, // User is not a member, so not current user
|
||||
onAction: null, // No actions allowed in preview mode
|
||||
onJump: (_) {}, // No jump functionality in preview
|
||||
progress: null,
|
||||
showAvatar: isLastInGroup,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
final compactHeader = isWideScreen(context);
|
||||
|
||||
Widget comfortHeaderWidget() => Column(
|
||||
spacing: 4,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 26,
|
||||
width: 26,
|
||||
child:
|
||||
(room.type == 1 && room.picture?.id == null)
|
||||
? SplitAvatarWidget(
|
||||
filesId:
|
||||
room.members!
|
||||
.map((e) => e.account.profile.picture?.id)
|
||||
.toList(),
|
||||
)
|
||||
: room.picture?.id != null
|
||||
? ProfilePictureWidget(
|
||||
fileId: room.picture?.id,
|
||||
fallbackIcon: Symbols.chat,
|
||||
)
|
||||
: CircleAvatar(
|
||||
child: Text(
|
||||
room.name![0].toUpperCase(),
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
(room.type == 1 && room.name == null)
|
||||
? room.members!.map((e) => e.account.nick).join(', ')
|
||||
: room.name!,
|
||||
).fontSize(15),
|
||||
],
|
||||
);
|
||||
|
||||
Widget compactHeaderWidget() => Row(
|
||||
spacing: 8,
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
children: [
|
||||
SizedBox(
|
||||
height: 26,
|
||||
width: 26,
|
||||
child:
|
||||
(room.type == 1 && room.picture?.id == null)
|
||||
? SplitAvatarWidget(
|
||||
filesId:
|
||||
room.members!
|
||||
.map((e) => e.account.profile.picture?.id)
|
||||
.toList(),
|
||||
)
|
||||
: room.picture?.id != null
|
||||
? ProfilePictureWidget(
|
||||
fileId: room.picture?.id,
|
||||
fallbackIcon: Symbols.chat,
|
||||
)
|
||||
: CircleAvatar(
|
||||
child: Text(
|
||||
room.name![0].toUpperCase(),
|
||||
style: const TextStyle(fontSize: 12),
|
||||
),
|
||||
),
|
||||
),
|
||||
Text(
|
||||
(room.type == 1 && room.name == null)
|
||||
? room.members!.map((e) => e.account.nick).join(', ')
|
||||
: room.name!,
|
||||
).fontSize(19),
|
||||
],
|
||||
);
|
||||
|
||||
return AppScaffold(
|
||||
appBar: AppBar(
|
||||
leading: !compactHeader ? const Center(child: PageBackButton()) : null,
|
||||
automaticallyImplyLeading: false,
|
||||
toolbarHeight: compactHeader ? null : 64,
|
||||
title: compactHeader ? compactHeaderWidget() : comfortHeaderWidget(),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Icons.more_vert),
|
||||
onPressed: () {
|
||||
context.pushNamed('chatDetail', pathParameters: {'id': id});
|
||||
},
|
||||
),
|
||||
const Gap(8),
|
||||
],
|
||||
),
|
||||
body: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
children: [
|
||||
Expanded(
|
||||
child: messages.when(
|
||||
data:
|
||||
(messageList) =>
|
||||
messageList.isEmpty
|
||||
? Center(child: Text('No messages yet'.tr()))
|
||||
: chatMessageListWidget(messageList),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(error, _) => ResponseErrorWidget(
|
||||
error: error,
|
||||
onRetry: () => messagesNotifier.loadInitial(),
|
||||
),
|
||||
),
|
||||
),
|
||||
// Join button at the bottom for public rooms
|
||||
Container(
|
||||
padding: const EdgeInsets.all(16),
|
||||
child: FilledButton.tonalIcon(
|
||||
onPressed: () async {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.post('/sphere/chat/${room.id}/members/me');
|
||||
ref.invalidate(chatroomIdentityProvider(id));
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
if (context.mounted) hideLoadingModal(context);
|
||||
}
|
||||
},
|
||||
label: Text('chatJoin').tr(),
|
||||
icon: const Icon(Icons.add),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
class MessagesNotifier extends _$MessagesNotifier {
|
||||
late final Dio _apiClient;
|
||||
@@ -82,9 +284,11 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
final Map<String, LocalChatMessage> _pendingMessages = {};
|
||||
final Map<String, Map<int, double>> _fileUploadProgress = {};
|
||||
int? _totalCount;
|
||||
String? _searchQuery;
|
||||
bool? _withLinks;
|
||||
bool? _withAttachments;
|
||||
|
||||
late final String _roomId;
|
||||
int _currentPage = 0;
|
||||
static const int _pageSize = 20;
|
||||
bool _hasMore = true;
|
||||
bool _isSyncing = false;
|
||||
@@ -96,28 +300,42 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
_database = ref.watch(databaseProvider);
|
||||
final room = await ref.watch(chatroomProvider(roomId).future);
|
||||
final identity = await ref.watch(chatroomIdentityProvider(roomId).future);
|
||||
if (room == null || identity == null) {
|
||||
throw Exception('Room or identity not found');
|
||||
|
||||
if (room == null) {
|
||||
throw Exception('Room not found');
|
||||
}
|
||||
_room = room;
|
||||
_identity = identity;
|
||||
|
||||
// Allow building even if identity is null for public rooms
|
||||
if (identity != null) {
|
||||
_identity = identity;
|
||||
}
|
||||
|
||||
developer.log(
|
||||
'MessagesNotifier built for room $roomId',
|
||||
name: 'MessagesNotifier',
|
||||
);
|
||||
|
||||
ref.listen(appLifecycleStateProvider, (_, next) {
|
||||
if (next.hasValue && next.value == AppLifecycleState.resumed) {
|
||||
developer.log(
|
||||
'App resumed, syncing messages',
|
||||
name: 'MessagesNotifier',
|
||||
);
|
||||
syncMessages();
|
||||
}
|
||||
});
|
||||
// Only setup sync and lifecycle listeners if user is a member
|
||||
if (identity != null) {
|
||||
ref.listen(appLifecycleStateProvider, (_, next) {
|
||||
if (next.hasValue && next.value == AppLifecycleState.resumed) {
|
||||
developer.log(
|
||||
'App resumed, syncing messages',
|
||||
name: 'MessagesNotifier',
|
||||
);
|
||||
syncMessages();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return await loadInitial();
|
||||
loadInitial();
|
||||
return [];
|
||||
}
|
||||
|
||||
List<LocalChatMessage> _sortMessages(List<LocalChatMessage> messages) {
|
||||
messages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
return messages;
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> _getCachedMessages({
|
||||
@@ -128,13 +346,32 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
'Getting cached messages from offset $offset, take $take',
|
||||
name: 'MessagesNotifier',
|
||||
);
|
||||
final dbMessages = await _database.getMessagesForRoom(
|
||||
_roomId,
|
||||
offset: offset,
|
||||
limit: take,
|
||||
);
|
||||
final dbLocalMessages =
|
||||
dbMessages.map(_database.companionToMessage).toList();
|
||||
final List<LocalChatMessage> dbMessages;
|
||||
if (_searchQuery != null && _searchQuery!.isNotEmpty) {
|
||||
dbMessages = await _database.searchMessages(_roomId, _searchQuery ?? '');
|
||||
} else {
|
||||
final chatMessagesFromDb = await _database.getMessagesForRoom(
|
||||
_roomId,
|
||||
offset: offset,
|
||||
limit: take,
|
||||
);
|
||||
dbMessages =
|
||||
chatMessagesFromDb.map(_database.companionToMessage).toList();
|
||||
}
|
||||
|
||||
List<LocalChatMessage> filteredMessages = dbMessages;
|
||||
|
||||
if (_withLinks == true) {
|
||||
filteredMessages =
|
||||
filteredMessages.where((msg) => _hasLink(msg)).toList();
|
||||
}
|
||||
|
||||
if (_withAttachments == true) {
|
||||
filteredMessages =
|
||||
filteredMessages.where((msg) => _hasAttachment(msg)).toList();
|
||||
}
|
||||
|
||||
final dbLocalMessages = filteredMessages;
|
||||
|
||||
if (offset == 0) {
|
||||
final pendingForRoom =
|
||||
@@ -143,7 +380,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
.toList();
|
||||
|
||||
final allMessages = [...pendingForRoom, ...dbLocalMessages];
|
||||
allMessages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
_sortMessages(allMessages); // Use the helper function
|
||||
|
||||
final uniqueMessages = <LocalChatMessage>[];
|
||||
final seenIds = <String>{};
|
||||
@@ -218,7 +455,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
_isSyncing = true;
|
||||
|
||||
developer.log('Starting message sync', name: 'MessagesNotifier');
|
||||
ref.read(isSyncingProvider.notifier).state = true;
|
||||
Future.microtask(() => ref.read(isSyncingProvider.notifier).state = true);
|
||||
try {
|
||||
final dbMessages = await _database.getMessagesForRoom(
|
||||
_room.id,
|
||||
@@ -279,7 +516,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
developer.log('Finished message sync', name: 'MessagesNotifier');
|
||||
ref.read(isSyncingProvider.notifier).state = false;
|
||||
Future.microtask(
|
||||
() => ref.read(isSyncingProvider.notifier).state = false,
|
||||
);
|
||||
_isSyncing = false;
|
||||
}
|
||||
}
|
||||
@@ -290,7 +529,9 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
bool synced = false,
|
||||
}) async {
|
||||
try {
|
||||
if (offset == 0 && !synced) {
|
||||
if (offset == 0 &&
|
||||
!synced &&
|
||||
(_searchQuery == null || _searchQuery!.isEmpty)) {
|
||||
_fetchAndCacheMessages(offset: 0, take: take).catchError((_) {
|
||||
return <LocalChatMessage>[];
|
||||
});
|
||||
@@ -305,7 +546,11 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
return localMessages;
|
||||
}
|
||||
|
||||
return await _fetchAndCacheMessages(offset: offset, take: take);
|
||||
if (_searchQuery == null || _searchQuery!.isEmpty) {
|
||||
return await _fetchAndCacheMessages(offset: offset, take: take);
|
||||
} else {
|
||||
return []; // If searching, and no local messages, don't fetch from network
|
||||
}
|
||||
} catch (e) {
|
||||
final localMessages = await _getCachedMessages(
|
||||
offset: offset,
|
||||
@@ -319,43 +564,46 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> loadInitial() async {
|
||||
developer.log('Loading initial messages', name: 'MessagesNotifier');
|
||||
Future<void> loadInitial() async {
|
||||
developer.log('Loading initial messages', name: 'MessagesNotifier');
|
||||
if (_searchQuery == null || _searchQuery!.isEmpty) {
|
||||
syncMessages();
|
||||
final messages = await _getCachedMessages(offset: 0, take: 100);
|
||||
_currentPage = 0;
|
||||
_hasMore = messages.length == _pageSize;
|
||||
return messages;
|
||||
}
|
||||
|
||||
Future<void> loadMore() async {
|
||||
if (!_hasMore || state is AsyncLoading) return;
|
||||
developer.log('Loading more messages', name: 'MessagesNotifier');
|
||||
final messages = await _getCachedMessages(offset: 0, take: _pageSize);
|
||||
|
||||
try {
|
||||
final currentMessages = state.value ?? [];
|
||||
_currentPage++;
|
||||
final newMessages = await listMessages(
|
||||
offset: _currentPage * _pageSize,
|
||||
take: _pageSize,
|
||||
);
|
||||
_hasMore = messages.length == _pageSize;
|
||||
|
||||
if (newMessages.isEmpty || newMessages.length < _pageSize) {
|
||||
_hasMore = false;
|
||||
}
|
||||
state = AsyncValue.data(messages);
|
||||
}
|
||||
|
||||
state = AsyncValue.data([...currentMessages, ...newMessages]);
|
||||
} catch (err, stackTrace) {
|
||||
developer.log(
|
||||
'Error loading more messages',
|
||||
name: 'MessagesNotifier',
|
||||
error: err,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
showErrorAlert(err);
|
||||
_currentPage--;
|
||||
Future<void> loadMore() async {
|
||||
if (!_hasMore || state is AsyncLoading) return;
|
||||
developer.log('Loading more messages', name: 'MessagesNotifier');
|
||||
|
||||
try {
|
||||
final currentMessages = state.value ?? [];
|
||||
final offset = currentMessages.length;
|
||||
|
||||
final newMessages = await listMessages(offset: offset, take: _pageSize);
|
||||
|
||||
if (newMessages.isEmpty || newMessages.length < _pageSize) {
|
||||
_hasMore = false;
|
||||
}
|
||||
|
||||
state = AsyncValue.data(
|
||||
_sortMessages([...currentMessages, ...newMessages]),
|
||||
);
|
||||
} catch (err, stackTrace) {
|
||||
developer.log(
|
||||
'Error loading more messages',
|
||||
name: 'MessagesNotifier',
|
||||
error: err,
|
||||
stackTrace: stackTrace,
|
||||
);
|
||||
showErrorAlert(err);
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> sendMessage(
|
||||
String content,
|
||||
@@ -455,10 +703,13 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
|
||||
final currentMessages = state.value ?? [];
|
||||
if (editingTo != null) {
|
||||
final newMessages = currentMessages
|
||||
.where((m) => m.id != localMessage.id) // remove pending message
|
||||
.map((m) => m.id == editingTo.id ? updatedMessage : m) // update original message
|
||||
.toList();
|
||||
final newMessages =
|
||||
currentMessages
|
||||
.where((m) => m.id != localMessage.id) // remove pending message
|
||||
.map(
|
||||
(m) => m.id == editingTo.id ? updatedMessage : m,
|
||||
) // update original message
|
||||
.toList();
|
||||
state = AsyncValue.data(newMessages);
|
||||
} else {
|
||||
final newMessages =
|
||||
@@ -566,7 +817,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
}
|
||||
return m;
|
||||
}).toList();
|
||||
state = AsyncValue.data(newMessages);
|
||||
state = AsyncValue.data(_sortMessages(newMessages));
|
||||
showErrorAlert(e);
|
||||
}
|
||||
}
|
||||
@@ -626,7 +877,7 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
if (index >= 0) {
|
||||
final newList = [...currentMessages];
|
||||
newList[index] = updatedMessage;
|
||||
state = AsyncValue.data(newList);
|
||||
state = AsyncValue.data(_sortMessages(newList));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -686,6 +937,20 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
}
|
||||
}
|
||||
|
||||
void searchMessages(String query, {bool? withLinks, bool? withAttachments}) {
|
||||
_searchQuery = query.trim();
|
||||
_withLinks = withLinks;
|
||||
_withAttachments = withAttachments;
|
||||
loadInitial();
|
||||
}
|
||||
|
||||
void clearSearch() {
|
||||
_searchQuery = null;
|
||||
_withLinks = null;
|
||||
_withAttachments = null;
|
||||
loadInitial();
|
||||
}
|
||||
|
||||
Future<LocalChatMessage?> fetchMessageById(String messageId) async {
|
||||
developer.log(
|
||||
'Fetching message by id $messageId',
|
||||
@@ -715,6 +980,18 @@ class MessagesNotifier extends _$MessagesNotifier {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
bool _hasLink(LocalChatMessage message) {
|
||||
final content = message.toRemoteMessage().content;
|
||||
if (content == null) return false;
|
||||
final urlRegex = RegExp(r'https?://[^\s/$.?#].[^\s]*');
|
||||
return urlRegex.hasMatch(content);
|
||||
}
|
||||
|
||||
bool _hasAttachment(LocalChatMessage message) {
|
||||
final remoteMessage = message.toRemoteMessage();
|
||||
return remoteMessage.attachments.isNotEmpty;
|
||||
}
|
||||
}
|
||||
|
||||
class ChatRoomScreen extends HookConsumerWidget {
|
||||
@@ -734,57 +1011,77 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
);
|
||||
} else if (chatIdentity.value == null) {
|
||||
// Identity was not found, user was not joined
|
||||
return AppScaffold(
|
||||
appBar: AppBar(leading: const PageBackButton()),
|
||||
body: Center(
|
||||
child:
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 280),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
chatRoom.value?.isCommunity == true
|
||||
? Symbols.person_add
|
||||
: Symbols.person_remove,
|
||||
size: 36,
|
||||
fill: 1,
|
||||
).padding(bottom: 4),
|
||||
Text('chatNotJoined').tr(),
|
||||
if (chatRoom.value?.isCommunity != true)
|
||||
Text(
|
||||
'chatUnableJoin',
|
||||
textAlign: TextAlign.center,
|
||||
).tr().bold()
|
||||
else
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: () async {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
if (chatRoom.value == null) {
|
||||
hideLoadingModal(context);
|
||||
return;
|
||||
}
|
||||
|
||||
await apiClient.post(
|
||||
'/sphere/chat/${chatRoom.value!.id}/members/me',
|
||||
);
|
||||
ref.invalidate(chatroomIdentityProvider(id));
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
if (context.mounted) hideLoadingModal(context);
|
||||
}
|
||||
},
|
||||
label: Text('chatJoin').tr(),
|
||||
icon: const Icon(Icons.add),
|
||||
).padding(top: 8),
|
||||
],
|
||||
),
|
||||
).center(),
|
||||
),
|
||||
return chatRoom.when(
|
||||
data: (room) {
|
||||
if (room!.isPublic) {
|
||||
// Show public room preview with messages but no input
|
||||
return _PublicRoomPreview(id: id, room: room);
|
||||
} else {
|
||||
// Show regular "not joined" screen for private rooms
|
||||
return AppScaffold(
|
||||
appBar: AppBar(leading: const PageBackButton()),
|
||||
body: Center(
|
||||
child:
|
||||
ConstrainedBox(
|
||||
constraints: const BoxConstraints(maxWidth: 280),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.center,
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Icon(
|
||||
room.isCommunity == true
|
||||
? Symbols.person_add
|
||||
: Symbols.person_remove,
|
||||
size: 36,
|
||||
fill: 1,
|
||||
).padding(bottom: 4),
|
||||
Text('chatNotJoined').tr(),
|
||||
if (room.isCommunity != true)
|
||||
Text(
|
||||
'chatUnableJoin',
|
||||
textAlign: TextAlign.center,
|
||||
).tr().bold()
|
||||
else
|
||||
FilledButton.tonalIcon(
|
||||
onPressed: () async {
|
||||
try {
|
||||
showLoadingModal(context);
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
await apiClient.post(
|
||||
'/sphere/chat/${room.id}/members/me',
|
||||
);
|
||||
ref.invalidate(chatroomIdentityProvider(id));
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
if (context.mounted) {
|
||||
hideLoadingModal(context);
|
||||
}
|
||||
}
|
||||
},
|
||||
label: Text('chatJoin').tr(),
|
||||
icon: const Icon(Icons.add),
|
||||
).padding(top: 8),
|
||||
],
|
||||
),
|
||||
).center(),
|
||||
),
|
||||
);
|
||||
}
|
||||
},
|
||||
loading:
|
||||
() => AppScaffold(
|
||||
appBar: AppBar(leading: const PageBackButton()),
|
||||
body: CircularProgressIndicator().center(),
|
||||
),
|
||||
error:
|
||||
(error, _) => AppScaffold(
|
||||
appBar: AppBar(leading: const PageBackButton()),
|
||||
body: ResponseErrorWidget(
|
||||
error: error,
|
||||
onRetry: () => ref.refresh(chatroomProvider(id)),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -953,26 +1250,32 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
}, [id]);
|
||||
|
||||
Future<void> pickPhotoMedia() async {
|
||||
final result = await ref
|
||||
.watch(imagePickerProvider)
|
||||
.pickMultiImage(requestFullMetadata: true);
|
||||
if (result.isEmpty) return;
|
||||
final result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.image,
|
||||
allowMultiple: true,
|
||||
allowCompression: false,
|
||||
);
|
||||
if (result == null || result.count == 0) return;
|
||||
attachments.value = [
|
||||
...attachments.value,
|
||||
...result.map(
|
||||
(e) => UniversalFile(data: e, type: UniversalFileType.image),
|
||||
...result.files.map(
|
||||
(e) => UniversalFile(data: e.xFile, type: UniversalFileType.image),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
Future<void> pickVideoMedia() async {
|
||||
final result = await ref
|
||||
.watch(imagePickerProvider)
|
||||
.pickVideo(source: ImageSource.gallery);
|
||||
if (result == null) return;
|
||||
final result = await FilePicker.platform.pickFiles(
|
||||
type: FileType.video,
|
||||
allowMultiple: true,
|
||||
allowCompression: false,
|
||||
);
|
||||
if (result == null || result.count == 0) return;
|
||||
attachments.value = [
|
||||
...attachments.value,
|
||||
UniversalFile(data: result, type: UniversalFileType.video),
|
||||
...result.files.map(
|
||||
(e) => UniversalFile(data: e.xFile, type: UniversalFileType.video),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
@@ -1089,6 +1392,8 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
],
|
||||
);
|
||||
|
||||
const messageKeyPrefix = 'message-';
|
||||
|
||||
Widget chatMessageListWidget(List<LocalChatMessage> messageList) =>
|
||||
SuperListView.builder(
|
||||
listController: listController,
|
||||
@@ -1098,7 +1403,9 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
itemCount: messageList.length,
|
||||
findChildIndexCallback: (key) {
|
||||
final valueKey = key as ValueKey;
|
||||
final messageId = valueKey.value as String;
|
||||
final messageId = (valueKey.value as String).substring(
|
||||
messageKeyPrefix.length,
|
||||
);
|
||||
return messageList.indexWhere((m) => m.id == messageId);
|
||||
},
|
||||
extentEstimation: (_, _) => 40,
|
||||
@@ -1115,10 +1422,13 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
.abs() >
|
||||
3;
|
||||
|
||||
final key = ValueKey('$messageKeyPrefix${message.id}');
|
||||
|
||||
return chatIdentity.when(
|
||||
skipError: true,
|
||||
data:
|
||||
(identity) => MessageItem(
|
||||
key: key,
|
||||
message: message,
|
||||
isCurrentUser: identity?.id == message.senderId,
|
||||
onAction: (action) {
|
||||
@@ -1161,6 +1471,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
),
|
||||
loading:
|
||||
() => MessageItem(
|
||||
key: key,
|
||||
message: message,
|
||||
isCurrentUser: false,
|
||||
onAction: null,
|
||||
@@ -1168,7 +1479,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
||||
showAvatar: false,
|
||||
onJump: (_) {},
|
||||
),
|
||||
error: (_, _) => const SizedBox.shrink(),
|
||||
error: (_, _) => SizedBox.shrink(key: key),
|
||||
);
|
||||
},
|
||||
);
|
||||
@@ -1549,7 +1860,7 @@ class _ChatInput extends HookConsumerWidget {
|
||||
children: [
|
||||
IconButton(
|
||||
tooltip: 'stickers'.tr(),
|
||||
icon: const Icon(Symbols.emoji_symbols),
|
||||
icon: const Icon(Symbols.add_reaction),
|
||||
onPressed: () {
|
||||
final size = MediaQuery.of(context).size;
|
||||
showStickerPickerPopover(
|
||||
@@ -1659,8 +1970,13 @@ class _ChatInput extends HookConsumerWidget {
|
||||
horizontal: 12,
|
||||
vertical: 4,
|
||||
),
|
||||
counterText:
|
||||
messageController.text.length > 1024
|
||||
? '${messageController.text.length}/4096'
|
||||
: null,
|
||||
),
|
||||
maxLines: null,
|
||||
maxLines: 3,
|
||||
minLines: 1,
|
||||
onTapOutside:
|
||||
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||
),
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'room.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$messagesNotifierHash() => r'32afe6ea24086d869cc47bd3389c8fd734409ca0';
|
||||
String _$messagesNotifierHash() => r'fc3b66dfb8dd3fc55d142dae5c5e7bdc67eca5d4';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
||||
@@ -9,6 +9,7 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/chat.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/screens/chat/chat.dart';
|
||||
import 'package:island/widgets/account/account_pfc.dart';
|
||||
import 'package:island/widgets/account/account_picker.dart';
|
||||
import 'package:island/widgets/account/status.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
@@ -19,10 +20,17 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
import 'package:island/pods/database.dart';
|
||||
|
||||
part 'room_detail.freezed.dart';
|
||||
part 'room_detail.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<int> totalMessagesCount(Ref ref, String roomId) async {
|
||||
final database = ref.watch(databaseProvider);
|
||||
return database.getTotalMessagesForRoom(roomId);
|
||||
}
|
||||
|
||||
class ChatDetailScreen extends HookConsumerWidget {
|
||||
final String id;
|
||||
const ChatDetailScreen({super.key, required this.id});
|
||||
@@ -31,6 +39,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final roomState = ref.watch(chatroomProvider(id));
|
||||
final roomIdentity = ref.watch(chatroomIdentityProvider(id));
|
||||
final totalMessages = ref.watch(totalMessagesCountProvider(id));
|
||||
|
||||
const kNotifyLevelText = [
|
||||
'chatNotifyLevelAll',
|
||||
@@ -131,7 +140,7 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
const Text('chatBreakDescription').tr(),
|
||||
const Gap(16),
|
||||
ListTile(
|
||||
title: const Text('Clear').tr(),
|
||||
title: const Text('chatBreakClearButton').tr(),
|
||||
subtitle: const Text('chatBreakClear').tr(),
|
||||
leading: const Icon(Icons.notifications_active),
|
||||
onTap: () {
|
||||
@@ -143,8 +152,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('5m'),
|
||||
subtitle: const Text('chatBreakHour').tr(args: ['5m']),
|
||||
title: const Text('chatBreak5m').tr(),
|
||||
subtitle: const Text(
|
||||
'chatBreakHour',
|
||||
).tr(args: ['chatBreak5m'.tr()]),
|
||||
leading: const Icon(Symbols.circle),
|
||||
onTap: () {
|
||||
setChatBreak(now.add(const Duration(minutes: 5)));
|
||||
@@ -155,8 +166,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('10m'),
|
||||
subtitle: const Text('chatBreakHour').tr(args: ['10m']),
|
||||
title: const Text('chatBreak10m').tr(),
|
||||
subtitle: const Text(
|
||||
'chatBreakHour',
|
||||
).tr(args: ['chatBreak10m'.tr()]),
|
||||
leading: const Icon(Symbols.circle),
|
||||
onTap: () {
|
||||
setChatBreak(now.add(const Duration(minutes: 10)));
|
||||
@@ -167,8 +180,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('15m'),
|
||||
subtitle: const Text('chatBreakHour').tr(args: ['15m']),
|
||||
title: const Text('chatBreak15m').tr(),
|
||||
subtitle: const Text(
|
||||
'chatBreakHour',
|
||||
).tr(args: ['chatBreak15m'.tr()]),
|
||||
leading: const Icon(Symbols.timer_3),
|
||||
onTap: () {
|
||||
setChatBreak(now.add(const Duration(minutes: 15)));
|
||||
@@ -179,8 +194,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
title: const Text('30m'),
|
||||
subtitle: const Text('chatBreakHour').tr(args: ['30m']),
|
||||
title: const Text('chatBreak30m').tr(),
|
||||
subtitle: const Text(
|
||||
'chatBreakHour',
|
||||
).tr(args: ['chatBreak30m'.tr()]),
|
||||
leading: const Icon(Symbols.timer),
|
||||
onTap: () {
|
||||
setChatBreak(now.add(const Duration(minutes: 30)));
|
||||
@@ -194,8 +211,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
TextField(
|
||||
controller: durationController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'Custom (minutes)'.tr(),
|
||||
hintText: 'Enter minutes'.tr(),
|
||||
labelText: 'chatBreakCustomMinutes'.tr(),
|
||||
hintText: 'chatBreakEnterMinutes'.tr(),
|
||||
border: const OutlineInputBorder(),
|
||||
suffixIcon: IconButton(
|
||||
icon: const Icon(Icons.check),
|
||||
@@ -238,7 +255,10 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
return AppScaffold(
|
||||
body: roomState.when(
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => Center(child: Text('Error: $error')),
|
||||
error:
|
||||
(error, _) => Center(
|
||||
child: Text('errorGeneric'.tr(args: [error.toString()])),
|
||||
),
|
||||
data:
|
||||
(currentRoom) => CustomScrollView(
|
||||
slivers: [
|
||||
@@ -358,6 +378,36 @@ class ChatDetailScreen extends HookConsumerWidget {
|
||||
: const Text('chatBreakNone').tr(),
|
||||
onTap: () => showChatBreakDialog(),
|
||||
),
|
||||
ListTile(
|
||||
contentPadding: EdgeInsets.symmetric(
|
||||
horizontal: 24,
|
||||
),
|
||||
leading: const Icon(Icons.search),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
title: const Text('searchMessages').tr(),
|
||||
subtitle: totalMessages.when(
|
||||
data:
|
||||
(count) => Text(
|
||||
'messagesCount'.tr(
|
||||
args: [count.toString()],
|
||||
),
|
||||
),
|
||||
loading:
|
||||
() => const CircularProgressIndicator(),
|
||||
error:
|
||||
(err, stack) => Text(
|
||||
'errorGeneric'.tr(
|
||||
args: [err.toString()],
|
||||
),
|
||||
),
|
||||
),
|
||||
onTap: () {
|
||||
context.pushNamed(
|
||||
'searchMessages',
|
||||
pathParameters: {'id': id},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
error: (_, _) => const SizedBox.shrink(),
|
||||
@@ -666,15 +716,22 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
final member = data.items[index];
|
||||
return ListTile(
|
||||
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
||||
leading: ProfilePictureWidget(
|
||||
fileId: member.account.profile.picture?.id,
|
||||
leading: AccountPfcGestureDetector(
|
||||
uname: member.account.name,
|
||||
child: ProfilePictureWidget(
|
||||
fileId: member.account.profile.picture?.id,
|
||||
),
|
||||
),
|
||||
title: Row(
|
||||
spacing: 6,
|
||||
children: [
|
||||
Flexible(child: Text(member.account.nick)),
|
||||
if (member.status != null)
|
||||
AccountStatusLabel(status: member.status!),
|
||||
AccountStatusLabel(
|
||||
status: member.status!,
|
||||
maxLines: 1,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
if (member.joinedAt == null)
|
||||
const Icon(Symbols.pending_actions, size: 20),
|
||||
],
|
||||
@@ -848,7 +905,7 @@ class _ChatMemberRoleSheet extends HookConsumerWidget {
|
||||
try {
|
||||
final newRole = int.parse(roleController.text);
|
||||
if (newRole < 0 || newRole > 100) {
|
||||
throw 'Role must be between 0 and 100';
|
||||
throw 'roleValidationHint'.tr();
|
||||
}
|
||||
|
||||
final apiClient = ref.read(apiClientProvider);
|
||||
|
||||
@@ -6,8 +6,8 @@ part of 'room_detail.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$chatMemberListNotifierHash() =>
|
||||
r'c8fbf4b95df6dae24b1ba21063e9a43351832974';
|
||||
String _$totalMessagesCountHash() =>
|
||||
r'd55f1507aba2acdce5e468c1c2e15dba7640c571';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
@@ -30,6 +30,128 @@ class _SystemHash {
|
||||
}
|
||||
}
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
@ProviderFor(totalMessagesCount)
|
||||
const totalMessagesCountProvider = TotalMessagesCountFamily();
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
class TotalMessagesCountFamily extends Family<AsyncValue<int>> {
|
||||
/// See also [totalMessagesCount].
|
||||
const TotalMessagesCountFamily();
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
TotalMessagesCountProvider call(String roomId) {
|
||||
return TotalMessagesCountProvider(roomId);
|
||||
}
|
||||
|
||||
@override
|
||||
TotalMessagesCountProvider getProviderOverride(
|
||||
covariant TotalMessagesCountProvider provider,
|
||||
) {
|
||||
return call(provider.roomId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'totalMessagesCountProvider';
|
||||
}
|
||||
|
||||
/// See also [totalMessagesCount].
|
||||
class TotalMessagesCountProvider extends AutoDisposeFutureProvider<int> {
|
||||
/// See also [totalMessagesCount].
|
||||
TotalMessagesCountProvider(String roomId)
|
||||
: this._internal(
|
||||
(ref) => totalMessagesCount(ref as TotalMessagesCountRef, roomId),
|
||||
from: totalMessagesCountProvider,
|
||||
name: r'totalMessagesCountProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$totalMessagesCountHash,
|
||||
dependencies: TotalMessagesCountFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
TotalMessagesCountFamily._allTransitiveDependencies,
|
||||
roomId: roomId,
|
||||
);
|
||||
|
||||
TotalMessagesCountProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.roomId,
|
||||
}) : super.internal();
|
||||
|
||||
final String roomId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<int> Function(TotalMessagesCountRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: TotalMessagesCountProvider._internal(
|
||||
(ref) => create(ref as TotalMessagesCountRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
roomId: roomId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<int> createElement() {
|
||||
return _TotalMessagesCountProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is TotalMessagesCountProvider && other.roomId == roomId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, roomId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin TotalMessagesCountRef on AutoDisposeFutureProviderRef<int> {
|
||||
/// The parameter `roomId` of this provider.
|
||||
String get roomId;
|
||||
}
|
||||
|
||||
class _TotalMessagesCountProviderElement
|
||||
extends AutoDisposeFutureProviderElement<int>
|
||||
with TotalMessagesCountRef {
|
||||
_TotalMessagesCountProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get roomId => (origin as TotalMessagesCountProvider).roomId;
|
||||
}
|
||||
|
||||
String _$chatMemberListNotifierHash() =>
|
||||
r'3ea30150278523e9f6b23f9200ea9a9fbae9c973';
|
||||
|
||||
abstract class _$ChatMemberListNotifier
|
||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> {
|
||||
late final String roomId;
|
||||
|
||||
139
lib/screens/chat/search_messages_screen.dart
Normal file
139
lib/screens/chat/search_messages_screen.dart
Normal file
@@ -0,0 +1,139 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/screens/chat/room.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/chat/message_item.dart';
|
||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||
|
||||
class SearchMessagesScreen extends HookConsumerWidget {
|
||||
final String roomId;
|
||||
|
||||
const SearchMessagesScreen({super.key, required this.roomId});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final searchController = useTextEditingController();
|
||||
final withLinks = useState(false);
|
||||
final withAttachments = useState(false);
|
||||
|
||||
final messagesNotifier = ref.read(
|
||||
messagesNotifierProvider(roomId).notifier,
|
||||
);
|
||||
final messages = ref.watch(messagesNotifierProvider(roomId));
|
||||
|
||||
useEffect(() {
|
||||
// Clear search when screen is disposed
|
||||
return () {
|
||||
messagesNotifier.clearSearch();
|
||||
};
|
||||
}, []);
|
||||
|
||||
return AppScaffold(
|
||||
appBar: AppBar(title: const Text('searchMessages').tr()),
|
||||
body: Column(
|
||||
children: [
|
||||
Column(
|
||||
children: [
|
||||
TextField(
|
||||
controller: searchController,
|
||||
decoration: InputDecoration(
|
||||
hintText: 'searchMessagesHint'.tr(),
|
||||
border: InputBorder.none,
|
||||
isDense: true,
|
||||
contentPadding: EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 16,
|
||||
top: 12,
|
||||
bottom: 16,
|
||||
),
|
||||
suffix: IconButton(
|
||||
iconSize: 18,
|
||||
visualDensity: VisualDensity.compact,
|
||||
icon: const Icon(Icons.clear),
|
||||
onPressed: () {
|
||||
searchController.clear();
|
||||
messagesNotifier.clearSearch();
|
||||
},
|
||||
),
|
||||
),
|
||||
onChanged: (query) {
|
||||
messagesNotifier.searchMessages(
|
||||
query,
|
||||
withLinks: withLinks.value,
|
||||
withAttachments: withAttachments.value,
|
||||
);
|
||||
},
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Expanded(
|
||||
child: CheckboxListTile(
|
||||
secondary: const Icon(Symbols.link),
|
||||
title: const Text('searchLinks').tr(),
|
||||
value: withLinks.value,
|
||||
onChanged: (bool? value) {
|
||||
withLinks.value = value!;
|
||||
messagesNotifier.searchMessages(
|
||||
searchController.text,
|
||||
withLinks: withLinks.value,
|
||||
withAttachments: withAttachments.value,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
Expanded(
|
||||
child: CheckboxListTile(
|
||||
secondary: const Icon(Symbols.file_copy),
|
||||
title: const Text('searchAttachments').tr(),
|
||||
value: withAttachments.value,
|
||||
onChanged: (bool? value) {
|
||||
withAttachments.value = value!;
|
||||
messagesNotifier.searchMessages(
|
||||
searchController.text,
|
||||
withLinks: withLinks.value,
|
||||
withAttachments: withAttachments.value,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child: messages.when(
|
||||
data:
|
||||
(messageList) =>
|
||||
messageList.isEmpty
|
||||
? Center(child: Text('noMessagesFound'.tr()))
|
||||
: SuperListView.builder(
|
||||
padding: const EdgeInsets.symmetric(vertical: 16),
|
||||
reverse: true, // Show newest messages at the bottom
|
||||
itemCount: messageList.length,
|
||||
itemBuilder: (context, index) {
|
||||
final message = messageList[index];
|
||||
// Simplified MessageItem for search results, no grouping logic
|
||||
return MessageItem(
|
||||
message: message,
|
||||
isCurrentUser:
|
||||
false, // Or determine based on actual user
|
||||
onAction: null,
|
||||
onJump: (_) {},
|
||||
progress: null,
|
||||
showAvatar: true,
|
||||
);
|
||||
},
|
||||
),
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error: (error, _) => Center(child: Text('errorGeneric'.tr(args: [error.toString()]))),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ import 'package:island/models/publisher.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/screens/creators/publishers.dart';
|
||||
import 'package:island/services/responsive.dart';
|
||||
import 'package:island/services/text.dart';
|
||||
import 'package:island/utils/text.dart';
|
||||
import 'package:island/widgets/account/account_picker.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
@@ -9,6 +10,8 @@ import 'package:island/widgets/poll/poll_feedback.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||
import 'package:island/widgets/extended_refresh_indicator.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
part 'poll_list.g.dart';
|
||||
|
||||
@@ -86,7 +89,7 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
||||
onPressed: () => _createPoll(context),
|
||||
child: const Icon(Icons.add),
|
||||
),
|
||||
body: RefreshIndicator(
|
||||
body: ExtendedRefreshIndicator(
|
||||
onRefresh: () => ref.refresh(pollListNotifierProvider(pubName).future),
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
@@ -116,14 +119,14 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
||||
}
|
||||
}
|
||||
|
||||
class _CreatorPollItem extends StatelessWidget {
|
||||
class _CreatorPollItem extends HookConsumerWidget {
|
||||
final String pubName;
|
||||
const _CreatorPollItem({required this.pollWithStats, required this.pubName});
|
||||
|
||||
final SnPollWithStats pollWithStats;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final theme = Theme.of(context);
|
||||
final ended = pollWithStats.endedAt;
|
||||
final endedText =
|
||||
@@ -166,7 +169,7 @@ class _CreatorPollItem extends StatelessWidget {
|
||||
children: [
|
||||
const Icon(Symbols.edit),
|
||||
const Gap(16),
|
||||
Text('Edit'),
|
||||
Text('edit').tr(),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
@@ -176,6 +179,61 @@ class _CreatorPollItem extends StatelessWidget {
|
||||
);
|
||||
},
|
||||
),
|
||||
PopupMenuItem(
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Symbols.delete, color: Colors.red),
|
||||
const Gap(16),
|
||||
Text('delete').tr().textColor(Colors.red),
|
||||
],
|
||||
),
|
||||
onTap: () async {
|
||||
final confirmed = await showDialog<bool>(
|
||||
context: context,
|
||||
builder:
|
||||
(context) => AlertDialog(
|
||||
title: Text('Delete Poll'),
|
||||
content: Text(
|
||||
'Are you sure you want to delete this poll?',
|
||||
),
|
||||
actions: [
|
||||
TextButton(
|
||||
onPressed:
|
||||
() => Navigator.of(context).pop(false),
|
||||
child: Text('Cancel'),
|
||||
),
|
||||
TextButton(
|
||||
onPressed:
|
||||
() => Navigator.of(context).pop(true),
|
||||
child: Text('Delete'),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
if (confirmed == true) {
|
||||
try {
|
||||
final client = ref.read(apiClientProvider);
|
||||
await client.delete(
|
||||
'/sphere/polls/${pollWithStats.id}',
|
||||
);
|
||||
ref.invalidate(pollListNotifierProvider(pubName));
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(
|
||||
content: Text('Poll deleted successfully'),
|
||||
),
|
||||
);
|
||||
}
|
||||
} catch (e) {
|
||||
if (context.mounted) {
|
||||
ScaffoldMessenger.of(context).showSnackBar(
|
||||
SnackBar(content: Text('Failed to delete poll')),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
onTap: () {
|
||||
|
||||
@@ -106,11 +106,7 @@ class StickerPacksNotifier extends _$StickerPacksNotifier
|
||||
try {
|
||||
final response = await client.get(
|
||||
'/sphere/stickers',
|
||||
queryParameters: {
|
||||
'offset': offset,
|
||||
'take': _pageSize,
|
||||
'pubName': pubName,
|
||||
},
|
||||
queryParameters: {'offset': offset, 'take': _pageSize, 'pub': pubName},
|
||||
);
|
||||
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
|
||||
@@ -148,7 +148,7 @@ class _StickerPackProviderElement
|
||||
}
|
||||
|
||||
String _$stickerPacksNotifierHash() =>
|
||||
r'0a8edcf9c35396c411f1214f5e77b1e8fac6a3e6';
|
||||
r'30024b35235f3085a5b1ec2204d0a974ee907e22';
|
||||
|
||||
abstract class _$StickerPacksNotifier
|
||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnStickerPack>> {
|
||||
|
||||
@@ -4,6 +4,7 @@ import 'package:go_router/go_router.dart';
|
||||
import 'package:island/pods/webfeed.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/empty_state.dart';
|
||||
import 'package:island/widgets/extended_refresh_indicator.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
||||
class WebFeedListScreen extends ConsumerWidget {
|
||||
@@ -20,7 +21,10 @@ class WebFeedListScreen extends ConsumerWidget {
|
||||
floatingActionButton: FloatingActionButton(
|
||||
child: const Icon(Symbols.add),
|
||||
onPressed: () {
|
||||
context.pushNamed('creatorFeedNew', pathParameters: {'name': pubName});
|
||||
context.pushNamed(
|
||||
'creatorFeedNew',
|
||||
pathParameters: {'name': pubName},
|
||||
);
|
||||
},
|
||||
),
|
||||
body: feedsAsync.when(
|
||||
@@ -32,7 +36,7 @@ class WebFeedListScreen extends ConsumerWidget {
|
||||
description: 'Add a new web feed to get started',
|
||||
);
|
||||
}
|
||||
return RefreshIndicator(
|
||||
return ExtendedRefreshIndicator(
|
||||
onRefresh: () => ref.refresh(webFeedListProvider(pubName).future),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.only(top: 8),
|
||||
@@ -62,7 +66,10 @@ class WebFeedListScreen extends ConsumerWidget {
|
||||
),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
onTap: () {
|
||||
context.pushNamed('creatorFeedEdit', pathParameters: {'name': pubName, 'feedId': feed.id});
|
||||
context.pushNamed(
|
||||
'creatorFeedEdit',
|
||||
pathParameters: {'name': pubName, 'feedId': feed.id},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
|
||||
156
lib/screens/developers/app_detail.dart
Normal file
156
lib/screens/developers/app_detail.dart
Normal file
@@ -0,0 +1,156 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/custom_app.dart';
|
||||
import 'package:island/screens/developers/app_secrets.dart';
|
||||
import 'package:island/screens/developers/apps.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
class AppDetailScreen extends HookConsumerWidget {
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
final String appId;
|
||||
|
||||
const AppDetailScreen({
|
||||
super.key,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
required this.appId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final tabController = useTabController(initialLength: 2);
|
||||
final appData = ref.watch(
|
||||
customAppProvider(publisherName, projectId, appId),
|
||||
);
|
||||
|
||||
return AppScaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(appData.value?.name ?? 'appDetails'.tr()),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.edit),
|
||||
onPressed:
|
||||
appData.value == null
|
||||
? null
|
||||
: () {
|
||||
context.pushNamed(
|
||||
'developerAppEdit',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
'id': appId,
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
bottom: TabBar(
|
||||
controller: tabController,
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Text(
|
||||
'overview'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Text(
|
||||
'secrets'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: appData.when(
|
||||
data: (app) {
|
||||
return TabBarView(
|
||||
controller: tabController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
_AppOverview(app: app),
|
||||
AppSecretsScreen(
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
appId: appId,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(err, stack) => ResponseErrorWidget(
|
||||
error: err,
|
||||
onRetry:
|
||||
() => ref.invalidate(
|
||||
customAppProvider(publisherName, projectId, appId),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _AppOverview extends StatelessWidget {
|
||||
final CustomApp app;
|
||||
const _AppOverview({required this.app});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: 16 / 7,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Container(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
child:
|
||||
app.background != null
|
||||
? CloudFileWidget(
|
||||
item: app.background!,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
Positioned(
|
||||
left: 20,
|
||||
bottom: -32,
|
||||
child: ProfilePictureWidget(
|
||||
fileId: app.picture?.id,
|
||||
radius: 40,
|
||||
fallbackIcon: Symbols.apps,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
).padding(bottom: 32),
|
||||
ListTile(title: Text('name'.tr()), subtitle: Text(app.name)),
|
||||
ListTile(title: Text('slug'.tr()), subtitle: Text(app.slug)),
|
||||
if (app.description?.isNotEmpty ?? false)
|
||||
ListTile(
|
||||
title: Text('description'.tr()),
|
||||
subtitle: Text(app.description!),
|
||||
),
|
||||
],
|
||||
).padding(bottom: 24),
|
||||
);
|
||||
}
|
||||
}
|
||||
252
lib/screens/developers/app_secrets.dart
Normal file
252
lib/screens/developers/app_secrets.dart
Normal file
@@ -0,0 +1,252 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/custom_app_secret.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/services/time.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'app_secrets.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<CustomAppSecret>> customAppSecrets(
|
||||
Ref ref,
|
||||
String publisherName,
|
||||
String projectId,
|
||||
String appId,
|
||||
) async {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.get(
|
||||
'/develop/developers/$publisherName/projects/$projectId/apps/$appId/secrets',
|
||||
);
|
||||
return (resp.data as List)
|
||||
.map((e) => CustomAppSecret.fromJson(e))
|
||||
.cast<CustomAppSecret>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
class AppSecretsScreen extends HookConsumerWidget {
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
final String appId;
|
||||
|
||||
const AppSecretsScreen({
|
||||
super.key,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
required this.appId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final secrets = ref.watch(
|
||||
customAppSecretsProvider(publisherName, projectId, appId),
|
||||
);
|
||||
|
||||
void showNewSecretSheet(String newSecret) {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder:
|
||||
(context) => SheetScaffold(
|
||||
titleText: 'newSecretGenerated'.tr(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('copySecretHint'.tr()),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: SelectableText(newSecret),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
FilledButton.icon(
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: newSecret));
|
||||
},
|
||||
icon: const Icon(Symbols.copy_all),
|
||||
label: Text('copy'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
).whenComplete(() {
|
||||
ref.invalidate(
|
||||
customAppSecretsProvider(publisherName, projectId, appId),
|
||||
);
|
||||
});
|
||||
}
|
||||
|
||||
void createSecret() {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (context) {
|
||||
return HookBuilder(
|
||||
builder: (context) {
|
||||
final descriptionController = useTextEditingController();
|
||||
final expiresInController = useTextEditingController();
|
||||
final isOidc = useState(false);
|
||||
|
||||
return SheetScaffold(
|
||||
titleText: 'generateSecret'.tr(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: descriptionController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'description'.tr(),
|
||||
),
|
||||
autofocus: true,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
TextFormField(
|
||||
controller: expiresInController,
|
||||
decoration: InputDecoration(
|
||||
labelText: 'expiresIn'.tr(),
|
||||
),
|
||||
keyboardType: TextInputType.number,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
SwitchListTile(
|
||||
title: Text('isOidc'.tr()),
|
||||
value: isOidc.value,
|
||||
onChanged: (value) => isOidc.value = value,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
FilledButton.icon(
|
||||
onPressed: () async {
|
||||
final description = descriptionController.text;
|
||||
final expiresIn = int.tryParse(
|
||||
expiresInController.text,
|
||||
);
|
||||
Navigator.pop(context); // Close the sheet
|
||||
try {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final resp = await client.post(
|
||||
'/develop/developers/$publisherName/projects/$projectId/apps/$appId/secrets',
|
||||
data: {
|
||||
'description': description,
|
||||
'expires_in': expiresIn,
|
||||
'is_oidc': isOidc.value,
|
||||
},
|
||||
);
|
||||
final newSecret = CustomAppSecret.fromJson(
|
||||
resp.data,
|
||||
);
|
||||
if (newSecret.secret != null) {
|
||||
showNewSecretSheet(newSecret.secret!);
|
||||
}
|
||||
} catch (e) {
|
||||
showErrorAlert(e.toString());
|
||||
}
|
||||
},
|
||||
icon: const Icon(Symbols.add),
|
||||
label: Text('create'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
return secrets.when(
|
||||
data: (data) {
|
||||
return RefreshIndicator(
|
||||
onRefresh:
|
||||
() => ref.refresh(
|
||||
customAppSecretsProvider(
|
||||
publisherName,
|
||||
projectId,
|
||||
appId,
|
||||
).future,
|
||||
),
|
||||
child: Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Symbols.add),
|
||||
title: Text('generateSecret'.tr()),
|
||||
onTap: createSecret,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: data.length,
|
||||
itemBuilder: (context, index) {
|
||||
final secret = data[index];
|
||||
return ListTile(
|
||||
title: Text(secret.description ?? secret.id),
|
||||
subtitle: Text(
|
||||
'createdAt'.tr(args: [secret.createdAt.formatSystem()]),
|
||||
),
|
||||
trailing: Row(
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.delete, color: Colors.red),
|
||||
onPressed: () {
|
||||
showConfirmAlert(
|
||||
'deleteSecretHint'.tr(),
|
||||
'deleteSecret'.tr(),
|
||||
).then((confirm) {
|
||||
if (confirm) {
|
||||
final client = ref.read(apiClientProvider);
|
||||
client.delete(
|
||||
'/develop/developers/$publisherName/projects/$projectId/apps/$appId/secrets/${secret.id}',
|
||||
);
|
||||
ref.invalidate(
|
||||
customAppSecretsProvider(
|
||||
publisherName,
|
||||
projectId,
|
||||
appId,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(err, stack) => ResponseErrorWidget(
|
||||
error: err,
|
||||
onRetry:
|
||||
() => ref.invalidate(
|
||||
customAppSecretsProvider(publisherName, projectId, appId),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
188
lib/screens/developers/app_secrets.g.dart
Normal file
188
lib/screens/developers/app_secrets.g.dart
Normal file
@@ -0,0 +1,188 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'app_secrets.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$customAppSecretsHash() => r'1bc62ad812487883ce739793b22a76168d656752';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
/// See also [customAppSecrets].
|
||||
@ProviderFor(customAppSecrets)
|
||||
const customAppSecretsProvider = CustomAppSecretsFamily();
|
||||
|
||||
/// See also [customAppSecrets].
|
||||
class CustomAppSecretsFamily extends Family<AsyncValue<List<CustomAppSecret>>> {
|
||||
/// See also [customAppSecrets].
|
||||
const CustomAppSecretsFamily();
|
||||
|
||||
/// See also [customAppSecrets].
|
||||
CustomAppSecretsProvider call(
|
||||
String publisherName,
|
||||
String projectId,
|
||||
String appId,
|
||||
) {
|
||||
return CustomAppSecretsProvider(publisherName, projectId, appId);
|
||||
}
|
||||
|
||||
@override
|
||||
CustomAppSecretsProvider getProviderOverride(
|
||||
covariant CustomAppSecretsProvider provider,
|
||||
) {
|
||||
return call(provider.publisherName, provider.projectId, provider.appId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'customAppSecretsProvider';
|
||||
}
|
||||
|
||||
/// See also [customAppSecrets].
|
||||
class CustomAppSecretsProvider
|
||||
extends AutoDisposeFutureProvider<List<CustomAppSecret>> {
|
||||
/// See also [customAppSecrets].
|
||||
CustomAppSecretsProvider(String publisherName, String projectId, String appId)
|
||||
: this._internal(
|
||||
(ref) => customAppSecrets(
|
||||
ref as CustomAppSecretsRef,
|
||||
publisherName,
|
||||
projectId,
|
||||
appId,
|
||||
),
|
||||
from: customAppSecretsProvider,
|
||||
name: r'customAppSecretsProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$customAppSecretsHash,
|
||||
dependencies: CustomAppSecretsFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
CustomAppSecretsFamily._allTransitiveDependencies,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
appId: appId,
|
||||
);
|
||||
|
||||
CustomAppSecretsProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
required this.appId,
|
||||
}) : super.internal();
|
||||
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
final String appId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<List<CustomAppSecret>> Function(CustomAppSecretsRef provider)
|
||||
create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: CustomAppSecretsProvider._internal(
|
||||
(ref) => create(ref as CustomAppSecretsRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
appId: appId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<List<CustomAppSecret>> createElement() {
|
||||
return _CustomAppSecretsProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is CustomAppSecretsProvider &&
|
||||
other.publisherName == publisherName &&
|
||||
other.projectId == projectId &&
|
||||
other.appId == appId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, publisherName.hashCode);
|
||||
hash = _SystemHash.combine(hash, projectId.hashCode);
|
||||
hash = _SystemHash.combine(hash, appId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin CustomAppSecretsRef
|
||||
on AutoDisposeFutureProviderRef<List<CustomAppSecret>> {
|
||||
/// The parameter `publisherName` of this provider.
|
||||
String get publisherName;
|
||||
|
||||
/// The parameter `projectId` of this provider.
|
||||
String get projectId;
|
||||
|
||||
/// The parameter `appId` of this provider.
|
||||
String get appId;
|
||||
}
|
||||
|
||||
class _CustomAppSecretsProviderElement
|
||||
extends AutoDisposeFutureProviderElement<List<CustomAppSecret>>
|
||||
with CustomAppSecretsRef {
|
||||
_CustomAppSecretsProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get publisherName =>
|
||||
(origin as CustomAppSecretsProvider).publisherName;
|
||||
@override
|
||||
String get projectId => (origin as CustomAppSecretsProvider).projectId;
|
||||
@override
|
||||
String get appId => (origin as CustomAppSecretsProvider).appId;
|
||||
}
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
@@ -6,7 +6,6 @@ import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/custom_app.dart';
|
||||
import 'package:island/pods/network.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/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
@@ -16,50 +15,98 @@ import 'package:styled_widget/styled_widget.dart';
|
||||
part 'apps.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<CustomApp>> customApps(Ref ref, String publisherName) async {
|
||||
Future<CustomApp> customApp(
|
||||
Ref ref,
|
||||
String publisherName,
|
||||
String projectId,
|
||||
String appId,
|
||||
) async {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.get('/develop/developers/$publisherName/apps');
|
||||
return resp.data.map((e) => CustomApp.fromJson(e)).cast<CustomApp>().toList();
|
||||
final resp = await client.get(
|
||||
'/develop/developers/$publisherName/projects/$projectId/apps/$appId',
|
||||
);
|
||||
return CustomApp.fromJson(resp.data);
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Future<List<CustomApp>> customApps(
|
||||
Ref ref,
|
||||
String publisherName,
|
||||
String projectId,
|
||||
) async {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.get(
|
||||
'/develop/developers/$publisherName/projects/$projectId/apps',
|
||||
);
|
||||
return (resp.data as List)
|
||||
.map((e) => CustomApp.fromJson(e))
|
||||
.cast<CustomApp>()
|
||||
.toList();
|
||||
}
|
||||
|
||||
class CustomAppsScreen extends HookConsumerWidget {
|
||||
final String publisherName;
|
||||
const CustomAppsScreen({super.key, required this.publisherName});
|
||||
final String projectId;
|
||||
const CustomAppsScreen({
|
||||
super.key,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final apps = ref.watch(customAppsProvider(publisherName));
|
||||
final apps = ref.watch(customAppsProvider(publisherName, projectId));
|
||||
|
||||
return AppScaffold(
|
||||
appBar: AppBar(
|
||||
title: Text('customApps').tr(),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.add),
|
||||
onPressed: () {
|
||||
context.pushNamed(
|
||||
'developerAppNew',
|
||||
pathParameters: {'name': publisherName},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
body: apps.when(
|
||||
data: (data) {
|
||||
if (data.isEmpty) {
|
||||
return Center(child: Text('noCustomApps').tr());
|
||||
}
|
||||
return RefreshIndicator(
|
||||
onRefresh:
|
||||
() => ref.refresh(customAppsProvider(publisherName).future),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.only(top: 4),
|
||||
itemCount: data.length,
|
||||
itemBuilder: (context, index) {
|
||||
final app = data[index];
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(8.0),
|
||||
return apps.when(
|
||||
data: (data) {
|
||||
if (data.isEmpty) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('noCustomApps').tr(),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
context.pushNamed(
|
||||
'developerAppNew',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: const Icon(Symbols.add),
|
||||
label: Text('createCustomApp').tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return RefreshIndicator(
|
||||
onRefresh:
|
||||
() => ref.refresh(
|
||||
customAppsProvider(publisherName, projectId).future,
|
||||
),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.only(top: 4),
|
||||
itemCount: data.length,
|
||||
itemBuilder: (context, index) {
|
||||
final app = data[index];
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(8.0),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: InkWell(
|
||||
onTap: () {
|
||||
context.pushNamed(
|
||||
'developerAppDetail',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
'appId': app.id,
|
||||
},
|
||||
);
|
||||
},
|
||||
child: Column(
|
||||
children: [
|
||||
SizedBox(
|
||||
@@ -128,6 +175,7 @@ class CustomAppsScreen extends HookConsumerWidget {
|
||||
'developerAppEdit',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
'id': app.id,
|
||||
},
|
||||
);
|
||||
@@ -139,10 +187,13 @@ class CustomAppsScreen extends HookConsumerWidget {
|
||||
if (confirm) {
|
||||
final client = ref.read(apiClientProvider);
|
||||
client.delete(
|
||||
'/develop/developers/$publisherName/apps/${app.id}',
|
||||
'/develop/developers/$publisherName/projects/$projectId/apps/${app.id}',
|
||||
);
|
||||
ref.invalidate(
|
||||
customAppsProvider(publisherName),
|
||||
customAppsProvider(
|
||||
publisherName,
|
||||
projectId,
|
||||
),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -152,18 +203,21 @@ class CustomAppsScreen extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(err, stack) => ResponseErrorWidget(
|
||||
error: err,
|
||||
onRetry: () => ref.invalidate(customAppsProvider(publisherName)),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(err, stack) => ResponseErrorWidget(
|
||||
error: err,
|
||||
onRetry:
|
||||
() => ref.invalidate(
|
||||
customAppsProvider(publisherName, projectId),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,7 +6,7 @@ part of 'apps.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$customAppsHash() => r'c6ac78060eb51a2b208a749a81ecbe0a9c608ce1';
|
||||
String _$customAppHash() => r'be05431ba8bf06fd20ee988a61c3663a68e15fc9';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
@@ -29,6 +29,148 @@ class _SystemHash {
|
||||
}
|
||||
}
|
||||
|
||||
/// See also [customApp].
|
||||
@ProviderFor(customApp)
|
||||
const customAppProvider = CustomAppFamily();
|
||||
|
||||
/// See also [customApp].
|
||||
class CustomAppFamily extends Family<AsyncValue<CustomApp>> {
|
||||
/// See also [customApp].
|
||||
const CustomAppFamily();
|
||||
|
||||
/// See also [customApp].
|
||||
CustomAppProvider call(String publisherName, String projectId, String appId) {
|
||||
return CustomAppProvider(publisherName, projectId, appId);
|
||||
}
|
||||
|
||||
@override
|
||||
CustomAppProvider getProviderOverride(covariant CustomAppProvider provider) {
|
||||
return call(provider.publisherName, provider.projectId, provider.appId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'customAppProvider';
|
||||
}
|
||||
|
||||
/// See also [customApp].
|
||||
class CustomAppProvider extends AutoDisposeFutureProvider<CustomApp> {
|
||||
/// See also [customApp].
|
||||
CustomAppProvider(String publisherName, String projectId, String appId)
|
||||
: this._internal(
|
||||
(ref) =>
|
||||
customApp(ref as CustomAppRef, publisherName, projectId, appId),
|
||||
from: customAppProvider,
|
||||
name: r'customAppProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$customAppHash,
|
||||
dependencies: CustomAppFamily._dependencies,
|
||||
allTransitiveDependencies: CustomAppFamily._allTransitiveDependencies,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
appId: appId,
|
||||
);
|
||||
|
||||
CustomAppProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
required this.appId,
|
||||
}) : super.internal();
|
||||
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
final String appId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<CustomApp> Function(CustomAppRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: CustomAppProvider._internal(
|
||||
(ref) => create(ref as CustomAppRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
appId: appId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<CustomApp> createElement() {
|
||||
return _CustomAppProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is CustomAppProvider &&
|
||||
other.publisherName == publisherName &&
|
||||
other.projectId == projectId &&
|
||||
other.appId == appId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, publisherName.hashCode);
|
||||
hash = _SystemHash.combine(hash, projectId.hashCode);
|
||||
hash = _SystemHash.combine(hash, appId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin CustomAppRef on AutoDisposeFutureProviderRef<CustomApp> {
|
||||
/// The parameter `publisherName` of this provider.
|
||||
String get publisherName;
|
||||
|
||||
/// The parameter `projectId` of this provider.
|
||||
String get projectId;
|
||||
|
||||
/// The parameter `appId` of this provider.
|
||||
String get appId;
|
||||
}
|
||||
|
||||
class _CustomAppProviderElement
|
||||
extends AutoDisposeFutureProviderElement<CustomApp>
|
||||
with CustomAppRef {
|
||||
_CustomAppProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get publisherName => (origin as CustomAppProvider).publisherName;
|
||||
@override
|
||||
String get projectId => (origin as CustomAppProvider).projectId;
|
||||
@override
|
||||
String get appId => (origin as CustomAppProvider).appId;
|
||||
}
|
||||
|
||||
String _$customAppsHash() => r'450bedaf4220b8963cb44afeb14d4c0e80f01b11';
|
||||
|
||||
/// See also [customApps].
|
||||
@ProviderFor(customApps)
|
||||
const customAppsProvider = CustomAppsFamily();
|
||||
@@ -39,15 +181,15 @@ class CustomAppsFamily extends Family<AsyncValue<List<CustomApp>>> {
|
||||
const CustomAppsFamily();
|
||||
|
||||
/// See also [customApps].
|
||||
CustomAppsProvider call(String publisherName) {
|
||||
return CustomAppsProvider(publisherName);
|
||||
CustomAppsProvider call(String publisherName, String projectId) {
|
||||
return CustomAppsProvider(publisherName, projectId);
|
||||
}
|
||||
|
||||
@override
|
||||
CustomAppsProvider getProviderOverride(
|
||||
covariant CustomAppsProvider provider,
|
||||
) {
|
||||
return call(provider.publisherName);
|
||||
return call(provider.publisherName, provider.projectId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
@@ -68,9 +210,9 @@ class CustomAppsFamily extends Family<AsyncValue<List<CustomApp>>> {
|
||||
/// See also [customApps].
|
||||
class CustomAppsProvider extends AutoDisposeFutureProvider<List<CustomApp>> {
|
||||
/// See also [customApps].
|
||||
CustomAppsProvider(String publisherName)
|
||||
CustomAppsProvider(String publisherName, String projectId)
|
||||
: this._internal(
|
||||
(ref) => customApps(ref as CustomAppsRef, publisherName),
|
||||
(ref) => customApps(ref as CustomAppsRef, publisherName, projectId),
|
||||
from: customAppsProvider,
|
||||
name: r'customAppsProvider',
|
||||
debugGetCreateSourceHash:
|
||||
@@ -80,6 +222,7 @@ class CustomAppsProvider extends AutoDisposeFutureProvider<List<CustomApp>> {
|
||||
dependencies: CustomAppsFamily._dependencies,
|
||||
allTransitiveDependencies: CustomAppsFamily._allTransitiveDependencies,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
);
|
||||
|
||||
CustomAppsProvider._internal(
|
||||
@@ -90,9 +233,11 @@ class CustomAppsProvider extends AutoDisposeFutureProvider<List<CustomApp>> {
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
}) : super.internal();
|
||||
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
@@ -108,6 +253,7 @@ class CustomAppsProvider extends AutoDisposeFutureProvider<List<CustomApp>> {
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
),
|
||||
);
|
||||
}
|
||||
@@ -119,13 +265,16 @@ class CustomAppsProvider extends AutoDisposeFutureProvider<List<CustomApp>> {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is CustomAppsProvider && other.publisherName == publisherName;
|
||||
return other is CustomAppsProvider &&
|
||||
other.publisherName == publisherName &&
|
||||
other.projectId == projectId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, publisherName.hashCode);
|
||||
hash = _SystemHash.combine(hash, projectId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
@@ -136,6 +285,9 @@ class CustomAppsProvider extends AutoDisposeFutureProvider<List<CustomApp>> {
|
||||
mixin CustomAppsRef on AutoDisposeFutureProviderRef<List<CustomApp>> {
|
||||
/// The parameter `publisherName` of this provider.
|
||||
String get publisherName;
|
||||
|
||||
/// The parameter `projectId` of this provider.
|
||||
String get projectId;
|
||||
}
|
||||
|
||||
class _CustomAppsProviderElement
|
||||
@@ -145,6 +297,8 @@ class _CustomAppsProviderElement
|
||||
|
||||
@override
|
||||
String get publisherName => (origin as CustomAppsProvider).publisherName;
|
||||
@override
|
||||
String get projectId => (origin as CustomAppsProvider).projectId;
|
||||
}
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
|
||||
161
lib/screens/developers/bot_detail.dart
Normal file
161
lib/screens/developers/bot_detail.dart
Normal file
@@ -0,0 +1,161 @@
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/bot.dart';
|
||||
import 'package:island/screens/developers/bot_keys.dart';
|
||||
import 'package:island/screens/developers/edit_bot.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
class BotDetailScreen extends HookConsumerWidget {
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
final String botId;
|
||||
|
||||
const BotDetailScreen({
|
||||
super.key,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
required this.botId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final tabController = useTabController(initialLength: 2);
|
||||
final botData = ref.watch(botProvider(publisherName, projectId, botId));
|
||||
|
||||
return AppScaffold(
|
||||
appBar: AppBar(
|
||||
title: Text(botData.value?.account.nick ?? 'botDetails'.tr()),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.edit),
|
||||
onPressed:
|
||||
botData.value == null
|
||||
? null
|
||||
: () {
|
||||
context.pushNamed(
|
||||
'developerBotEdit',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
'id': botId,
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
],
|
||||
bottom: TabBar(
|
||||
controller: tabController,
|
||||
tabs: [
|
||||
Tab(
|
||||
child: Text(
|
||||
'overview'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
Tab(
|
||||
child: Text(
|
||||
'keys'.tr(),
|
||||
textAlign: TextAlign.center,
|
||||
style: TextStyle(
|
||||
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
body: botData.when(
|
||||
data: (bot) {
|
||||
if (bot == null) {
|
||||
return Center(child: Text('botNotFound'.tr()));
|
||||
}
|
||||
return TabBarView(
|
||||
controller: tabController,
|
||||
physics: const NeverScrollableScrollPhysics(),
|
||||
children: [
|
||||
_BotOverview(bot: bot),
|
||||
BotKeysScreen(
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
botId: botId,
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(err, stack) => ResponseErrorWidget(
|
||||
error: err,
|
||||
onRetry:
|
||||
() => ref.invalidate(
|
||||
botProvider(publisherName, projectId, botId),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
class _BotOverview extends StatelessWidget {
|
||||
final Bot bot;
|
||||
const _BotOverview({required this.bot});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
return SingleChildScrollView(
|
||||
child: Column(
|
||||
children: [
|
||||
AspectRatio(
|
||||
aspectRatio: 16 / 7,
|
||||
child: Stack(
|
||||
clipBehavior: Clip.none,
|
||||
fit: StackFit.expand,
|
||||
children: [
|
||||
Container(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
child:
|
||||
bot.account.profile.background != null
|
||||
? CloudFileWidget(
|
||||
item: bot.account.profile.background!,
|
||||
fit: BoxFit.cover,
|
||||
)
|
||||
: const SizedBox.shrink(),
|
||||
),
|
||||
Positioned(
|
||||
left: 20,
|
||||
bottom: -32,
|
||||
child: ProfilePictureWidget(
|
||||
fileId: bot.account.profile.picture?.id,
|
||||
radius: 40,
|
||||
fallbackIcon: Symbols.smart_toy,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
).padding(bottom: 32),
|
||||
ListTile(title: Text('name'.tr()), subtitle: Text(bot.account.name)),
|
||||
ListTile(
|
||||
title: Text('nickname'.tr()),
|
||||
subtitle: Text(bot.account.nick),
|
||||
),
|
||||
ListTile(title: Text('slug'.tr()), subtitle: Text(bot.slug)),
|
||||
if (bot.account.profile.bio.isNotEmpty)
|
||||
ListTile(
|
||||
title: Text('bio'.tr()),
|
||||
subtitle: Text(bot.account.profile.bio),
|
||||
),
|
||||
],
|
||||
).padding(bottom: 24),
|
||||
);
|
||||
}
|
||||
}
|
||||
278
lib/screens/developers/bot_keys.dart
Normal file
278
lib/screens/developers/bot_keys.dart
Normal file
@@ -0,0 +1,278 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/bot_key.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/services/time.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'bot_keys.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<SnAccountApiKey>> botKeys(
|
||||
Ref ref,
|
||||
String publisherName,
|
||||
String projectId,
|
||||
String botId,
|
||||
) async {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.get(
|
||||
'/develop/developers/$publisherName/projects/$projectId/bots/$botId/keys',
|
||||
);
|
||||
return (resp.data as List).map((e) => SnAccountApiKey.fromJson(e)).toList();
|
||||
}
|
||||
|
||||
class BotKeysScreen extends HookConsumerWidget {
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
final String botId;
|
||||
|
||||
const BotKeysScreen({
|
||||
super.key,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
required this.botId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final keys = ref.watch(botKeysProvider(publisherName, projectId, botId));
|
||||
final keyNameController = useTextEditingController();
|
||||
|
||||
void showNewKeySheet(SnAccountApiKey newApiKey) {
|
||||
final token = newApiKey.key;
|
||||
if (token == null) return;
|
||||
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder:
|
||||
(context) => SheetScaffold(
|
||||
titleText: 'newKeyGenerated'.tr(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
Text('copyKeyHint'.tr()),
|
||||
const SizedBox(height: 16),
|
||||
Container(
|
||||
padding: const EdgeInsets.all(12),
|
||||
decoration: BoxDecoration(
|
||||
color: Theme.of(context).colorScheme.surfaceContainer,
|
||||
borderRadius: BorderRadius.circular(8),
|
||||
),
|
||||
child: SelectableText(token),
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
FilledButton.icon(
|
||||
onPressed: () {
|
||||
Clipboard.setData(ClipboardData(text: token));
|
||||
},
|
||||
icon: const Icon(Symbols.copy_all),
|
||||
label: Text('copy'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
).whenComplete(() {
|
||||
ref.invalidate(botKeysProvider(publisherName, projectId, botId));
|
||||
});
|
||||
}
|
||||
|
||||
void createKey() {
|
||||
keyNameController.clear();
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder:
|
||||
(context) => SheetScaffold(
|
||||
titleText: 'newBotKey'.tr(),
|
||||
child: Padding(
|
||||
padding: const EdgeInsets.all(20.0),
|
||||
child: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||
mainAxisSize: MainAxisSize.min,
|
||||
children: [
|
||||
TextFormField(
|
||||
controller: keyNameController,
|
||||
decoration: InputDecoration(labelText: 'keyName'.tr()),
|
||||
autofocus: true,
|
||||
),
|
||||
const SizedBox(height: 20),
|
||||
FilledButton.icon(
|
||||
onPressed: () async {
|
||||
if (keyNameController.text.isEmpty) return;
|
||||
final keyName = keyNameController.text;
|
||||
Navigator.pop(context); // Close the sheet
|
||||
try {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final resp = await client.post(
|
||||
'/develop/developers/$publisherName/projects/$projectId/bots/$botId/keys',
|
||||
data: {'label': keyName},
|
||||
);
|
||||
final newApiKey = SnAccountApiKey.fromJson(resp.data);
|
||||
showNewKeySheet(newApiKey);
|
||||
} catch (e) {
|
||||
showErrorAlert(e.toString());
|
||||
}
|
||||
},
|
||||
icon: const Icon(Symbols.add),
|
||||
label: Text('create'.tr()),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
void rotateKey(String keyId) {
|
||||
showConfirmAlert('rotateBotKeyHint'.tr(), 'rotateBotKey'.tr()).then((
|
||||
confirm,
|
||||
) async {
|
||||
if (confirm) {
|
||||
try {
|
||||
if (context.mounted) showLoadingModal(context);
|
||||
final client = ref.read(apiClientProvider);
|
||||
final resp = await client.post(
|
||||
'/develop/developers/$publisherName/projects/$projectId/bots/$botId/keys/$keyId/rotate',
|
||||
);
|
||||
final rotatedApiKey = SnAccountApiKey.fromJson(resp.data);
|
||||
showNewKeySheet(rotatedApiKey);
|
||||
} catch (err) {
|
||||
showErrorAlert(err.toString());
|
||||
} finally {
|
||||
if (context.mounted) hideLoadingModal(context);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void revokeKey(String keyId) {
|
||||
showConfirmAlert('revokeBotKeyHint'.tr(), 'revokeBotKey'.tr()).then((
|
||||
confirm,
|
||||
) {
|
||||
if (confirm) {
|
||||
final client = ref.read(apiClientProvider);
|
||||
client
|
||||
.delete(
|
||||
'/develop/developers/$publisherName/projects/$projectId/bots/$botId/keys/$keyId',
|
||||
)
|
||||
.then((_) {
|
||||
ref.invalidate(
|
||||
botKeysProvider(publisherName, projectId, botId),
|
||||
);
|
||||
})
|
||||
.catchError((err) {
|
||||
showErrorAlert(err.toString());
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return keys.when(
|
||||
data: (data) {
|
||||
return Column(
|
||||
children: [
|
||||
ListTile(
|
||||
leading: const Icon(Symbols.add),
|
||||
title: Text('newBotKey'.tr()),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
onTap: createKey,
|
||||
),
|
||||
const Divider(height: 1),
|
||||
Expanded(
|
||||
child:
|
||||
data.isEmpty
|
||||
? Center(child: Text('noBotKeys'.tr()))
|
||||
: RefreshIndicator(
|
||||
onRefresh:
|
||||
() => ref.refresh(
|
||||
botKeysProvider(
|
||||
publisherName,
|
||||
projectId,
|
||||
botId,
|
||||
).future,
|
||||
),
|
||||
child: ListView.builder(
|
||||
padding: EdgeInsets.zero,
|
||||
itemCount: data.length,
|
||||
itemBuilder: (context, index) {
|
||||
final apiKey = data[index];
|
||||
return ListTile(
|
||||
title: Text(apiKey.label),
|
||||
subtitle: Text(apiKey.createdAt.formatSystem()),
|
||||
contentPadding: EdgeInsets.only(
|
||||
left: 16,
|
||||
right: 12,
|
||||
),
|
||||
trailing: PopupMenuButton(
|
||||
itemBuilder:
|
||||
(context) => [
|
||||
PopupMenuItem(
|
||||
value: 'rotate',
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Symbols.refresh),
|
||||
const Gap(12),
|
||||
Text('rotateKey'.tr()),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'revoke',
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(
|
||||
Symbols.delete,
|
||||
color: Colors.red,
|
||||
),
|
||||
const Gap(12),
|
||||
Text(
|
||||
'revoke'.tr(),
|
||||
style: TextStyle(
|
||||
color: Colors.red,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
onSelected: (value) {
|
||||
if (value == 'rotate') {
|
||||
rotateKey(apiKey.id);
|
||||
} else if (value == 'revoke') {
|
||||
revokeKey(apiKey.id);
|
||||
}
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(err, stack) => ResponseErrorWidget(
|
||||
error: err,
|
||||
onRetry:
|
||||
() => ref.invalidate(
|
||||
botKeysProvider(publisherName, projectId, botId),
|
||||
),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
||||
172
lib/screens/developers/bot_keys.g.dart
Normal file
172
lib/screens/developers/bot_keys.g.dart
Normal file
@@ -0,0 +1,172 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'bot_keys.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$botKeysHash() => r'f7d1121833dc3da0cbd84b6171c2b2539edeb785';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
_SystemHash._();
|
||||
|
||||
static int combine(int hash, int value) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + value);
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x0007ffff & hash) << 10));
|
||||
return hash ^ (hash >> 6);
|
||||
}
|
||||
|
||||
static int finish(int hash) {
|
||||
// ignore: parameter_assignments
|
||||
hash = 0x1fffffff & (hash + ((0x03ffffff & hash) << 3));
|
||||
// ignore: parameter_assignments
|
||||
hash = hash ^ (hash >> 11);
|
||||
return 0x1fffffff & (hash + ((0x00003fff & hash) << 15));
|
||||
}
|
||||
}
|
||||
|
||||
/// See also [botKeys].
|
||||
@ProviderFor(botKeys)
|
||||
const botKeysProvider = BotKeysFamily();
|
||||
|
||||
/// See also [botKeys].
|
||||
class BotKeysFamily extends Family<AsyncValue<List<SnAccountApiKey>>> {
|
||||
/// See also [botKeys].
|
||||
const BotKeysFamily();
|
||||
|
||||
/// See also [botKeys].
|
||||
BotKeysProvider call(String publisherName, String projectId, String botId) {
|
||||
return BotKeysProvider(publisherName, projectId, botId);
|
||||
}
|
||||
|
||||
@override
|
||||
BotKeysProvider getProviderOverride(covariant BotKeysProvider provider) {
|
||||
return call(provider.publisherName, provider.projectId, provider.botId);
|
||||
}
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _dependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get dependencies => _dependencies;
|
||||
|
||||
static const Iterable<ProviderOrFamily>? _allTransitiveDependencies = null;
|
||||
|
||||
@override
|
||||
Iterable<ProviderOrFamily>? get allTransitiveDependencies =>
|
||||
_allTransitiveDependencies;
|
||||
|
||||
@override
|
||||
String? get name => r'botKeysProvider';
|
||||
}
|
||||
|
||||
/// See also [botKeys].
|
||||
class BotKeysProvider extends AutoDisposeFutureProvider<List<SnAccountApiKey>> {
|
||||
/// See also [botKeys].
|
||||
BotKeysProvider(String publisherName, String projectId, String botId)
|
||||
: this._internal(
|
||||
(ref) => botKeys(ref as BotKeysRef, publisherName, projectId, botId),
|
||||
from: botKeysProvider,
|
||||
name: r'botKeysProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$botKeysHash,
|
||||
dependencies: BotKeysFamily._dependencies,
|
||||
allTransitiveDependencies: BotKeysFamily._allTransitiveDependencies,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
botId: botId,
|
||||
);
|
||||
|
||||
BotKeysProvider._internal(
|
||||
super._createNotifier, {
|
||||
required super.name,
|
||||
required super.dependencies,
|
||||
required super.allTransitiveDependencies,
|
||||
required super.debugGetCreateSourceHash,
|
||||
required super.from,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
required this.botId,
|
||||
}) : super.internal();
|
||||
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
final String botId;
|
||||
|
||||
@override
|
||||
Override overrideWith(
|
||||
FutureOr<List<SnAccountApiKey>> Function(BotKeysRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: BotKeysProvider._internal(
|
||||
(ref) => create(ref as BotKeysRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
publisherName: publisherName,
|
||||
projectId: projectId,
|
||||
botId: botId,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<List<SnAccountApiKey>> createElement() {
|
||||
return _BotKeysProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is BotKeysProvider &&
|
||||
other.publisherName == publisherName &&
|
||||
other.projectId == projectId &&
|
||||
other.botId == botId;
|
||||
}
|
||||
|
||||
@override
|
||||
int get hashCode {
|
||||
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||
hash = _SystemHash.combine(hash, publisherName.hashCode);
|
||||
hash = _SystemHash.combine(hash, projectId.hashCode);
|
||||
hash = _SystemHash.combine(hash, botId.hashCode);
|
||||
|
||||
return _SystemHash.finish(hash);
|
||||
}
|
||||
}
|
||||
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin BotKeysRef on AutoDisposeFutureProviderRef<List<SnAccountApiKey>> {
|
||||
/// The parameter `publisherName` of this provider.
|
||||
String get publisherName;
|
||||
|
||||
/// The parameter `projectId` of this provider.
|
||||
String get projectId;
|
||||
|
||||
/// The parameter `botId` of this provider.
|
||||
String get botId;
|
||||
}
|
||||
|
||||
class _BotKeysProviderElement
|
||||
extends AutoDisposeFutureProviderElement<List<SnAccountApiKey>>
|
||||
with BotKeysRef {
|
||||
_BotKeysProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get publisherName => (origin as BotKeysProvider).publisherName;
|
||||
@override
|
||||
String get projectId => (origin as BotKeysProvider).projectId;
|
||||
@override
|
||||
String get botId => (origin as BotKeysProvider).botId;
|
||||
}
|
||||
|
||||
// ignore_for_file: type=lint
|
||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user