Compare commits
123 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
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 | ||
|
10e0d2fe5f | ||
|
99e10cb612 | ||
|
1db6941431 | ||
|
8370da4fe3 | ||
|
2bdf7029e9 | ||
|
86682a3a9a | ||
|
c3925e81b5 | ||
|
6f1f488490 | ||
|
31b2de2e46 | ||
|
412dcfa62a | ||
|
ffdc7e81ae | ||
|
1d3357803d | ||
|
6c48aa2356 | ||
|
466e354679 | ||
|
5d4b896f70 | ||
|
a04dffdfe8 | ||
|
ff871943cf | ||
|
1a892ab227 | ||
|
af1b303211 | ||
|
6fd702eba8 | ||
|
d220d43cd2 | ||
|
6892afb974 | ||
|
007b46b080 | ||
|
67d130dc34 | ||
|
7e923c77fe | ||
|
a593b52812 | ||
|
520dc80303 | ||
|
001897bbcd | ||
|
bab29c23e3 | ||
|
76b39f2df3 | ||
|
509b3e145b | ||
|
2b80ebc2d0 | ||
|
0ab908dd2a | ||
|
6007467e7a | ||
|
3745157c42 | ||
|
94481ec7bd | ||
|
fbfe8cbdee | ||
|
fbbab0a981 | ||
|
ae2fb3b303 | ||
|
3d7a4666ed | ||
|
5d3e0fb800 | ||
|
85ff52a661 | ||
|
da7fd64a43 | ||
|
3902633217 | ||
|
f478ea8b84 | ||
|
0f481aff5b | ||
|
7a31663310 | ||
|
0239c53c04 | ||
|
16987c758e | ||
|
3a36915140 | ||
|
4bde708878 | ||
|
2f0cf560f8 | ||
|
cf355a95fd | ||
|
2f43073172 | ||
|
8236d31ecc | ||
|
459a7dade0 | ||
|
e6000a660a | ||
|
75abaac205 | ||
|
603d5c3f73 |
9
.github/workflows/build.yml
vendored
9
.github/workflows/build.yml
vendored
@@ -41,6 +41,15 @@ jobs:
|
||||
with:
|
||||
name: build-output-windows
|
||||
path: build/windows/x64/runner/Release
|
||||
- name: Compile Installer
|
||||
uses: Minionguyjpro/Inno-Setup-Action@v1.2.2
|
||||
with:
|
||||
path: setup.iss
|
||||
- name: Archive installer artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-output-windows-installer
|
||||
path: Installer/windows-x86_64-setup.exe
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
3
.gitignore
vendored
3
.gitignore
vendored
@@ -12,6 +12,9 @@
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
# Inno Setup
|
||||
Installer/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
|
@@ -5,6 +5,7 @@ plugins {
|
||||
id("com.android.application")
|
||||
// START: FlutterFire Configuration
|
||||
id("com.google.gms.google-services")
|
||||
id("com.google.firebase.crashlytics")
|
||||
// END: FlutterFire Configuration
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
|
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>
|
@@ -21,6 +21,7 @@ plugins {
|
||||
id("com.android.application") version "8.12.0" apply false
|
||||
// START: FlutterFire Configuration
|
||||
id("com.google.gms.google-services") version("4.3.15") apply false
|
||||
id("com.google.firebase.crashlytics") version("2.8.1") apply false
|
||||
// END: FlutterFire Configuration
|
||||
id("org.jetbrains.kotlin.android") version("2.2.0") apply false
|
||||
}
|
||||
|
@@ -334,6 +334,7 @@
|
||||
"walletCreate": "Create a Wallet",
|
||||
"settingsServerUrl": "Server URL",
|
||||
"settingsApplied": "The settings has been applied.",
|
||||
"settingsCustomFontsHelper": "Use comma to seprate.",
|
||||
"notifications": "Notifications",
|
||||
"posts": "Posts",
|
||||
"settingsBackgroundImage": "Background Image",
|
||||
@@ -385,6 +386,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",
|
||||
@@ -573,6 +575,7 @@
|
||||
"keyboardShortcuts": "Keyboard Shortcuts",
|
||||
"share": "Share",
|
||||
"sharePost": "Share Post",
|
||||
"sharePostPhoto": "Share Post as Photo",
|
||||
"quickActions": "Quick Actions",
|
||||
"post": "Post",
|
||||
"copy": "Copy",
|
||||
@@ -641,6 +644,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",
|
||||
@@ -760,6 +775,7 @@
|
||||
"pollsRecent": "Recent Polls",
|
||||
"pollCreateNew": "Create New",
|
||||
"pollCreateNewHint": "Create a new poll for your post. Pick a publisher and continue.",
|
||||
"pollQuestions": "Questions",
|
||||
"publisher": "Publisher",
|
||||
"publisherHint": "Enter the publisher name",
|
||||
"publisherCannotBeEmpty": "Publisher cannot be empty",
|
||||
@@ -792,5 +808,157 @@
|
||||
"joinedAt": "Joined at {}",
|
||||
"searchAccounts": "Search accounts...",
|
||||
"webFeeds": "Web Feeds",
|
||||
"polls": "Polls"
|
||||
}
|
||||
"polls": "Polls",
|
||||
"sharePostSlogan": "Explore more on the Solar Network",
|
||||
"filesListAdditional": {
|
||||
"one": "+{} file remaining",
|
||||
"other": "+{} files remaining"
|
||||
},
|
||||
"pollAnswerSubmitted": "Poll answer has been submitted.",
|
||||
"modifyAnswers": "Modify Answers",
|
||||
"back": "Back",
|
||||
"submit": "Submit",
|
||||
"pollOptionDefaultLabel": "Option 1",
|
||||
"pollUpdated": "Poll updated.",
|
||||
"pollCreated": "Poll created.",
|
||||
"pollCreate": "Create Poll",
|
||||
"pollEdit": "Edit Poll",
|
||||
"pollPreviewJsonDebug": "Debug Preview",
|
||||
"pollTitleRequired": "Title is required",
|
||||
"pollEndDateOptional": "End date & time (optional)",
|
||||
"notSet": "Not set",
|
||||
"pick": "Pick",
|
||||
"clear": "Clear",
|
||||
"questions": "Questions",
|
||||
"pollAddQuestion": "Add question",
|
||||
"pollQuestionTypeSingleChoice": "Single choice",
|
||||
"pollQuestionTypeMultipleChoice": "Multiple choice",
|
||||
"pollQuestionTypeFreeText": "Free text",
|
||||
"pollQuestionTypeYesNo": "Yes / No",
|
||||
"pollQuestionTypeRating": "Rating",
|
||||
"pollNoQuestionsYet": "No questions yet",
|
||||
"pollNoQuestionsHint": "Use \"Add question\" to start building your poll.",
|
||||
"pollDebugPreview": "Debug Preview",
|
||||
"pollUntitledQuestion": "Untitled question",
|
||||
"moveUp": "Move up",
|
||||
"moveDown": "Move down",
|
||||
"required": "Required",
|
||||
"pollQuestionTitle": "Question title",
|
||||
"pollQuestionTitleRequired": "Question title is required",
|
||||
"pollQuestionDescriptionOptional": "Question description (optional)",
|
||||
"options": "Options",
|
||||
"pollAddOption": "Add option",
|
||||
"pollOptionLabel": "Option label",
|
||||
"pollLongTextAnswerPreview": "Long text answer (preview)",
|
||||
"pollShortTextAnswerPreview": "Short text answer (preview)",
|
||||
"messageJumpNotLoaded": "The referenced message was not loaded, unable to jump to it.",
|
||||
"postUnlinkRealm": "No linked realm",
|
||||
"postSlug": "Slug",
|
||||
"postSlugHint": "The slug can be used to access your post via URL in the webpage, it should be publisher-wide unique.",
|
||||
"attachmentOnDevice": "On-device",
|
||||
"attachmentOnCloud": "On-cloud",
|
||||
"attachments": "Attachments",
|
||||
"publisherCollabInvitation": "Collabration invitations",
|
||||
"publisherCollabInvitationCount": {
|
||||
"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)",
|
||||
"chatBreakEnterMinutes": "Enter 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"
|
||||
}
|
@@ -46,7 +46,6 @@
|
||||
"delete": "删除",
|
||||
"deletePublisher": "删除发布者",
|
||||
"deletePublisherHint": "确定要删除此发布者吗?这也会删除此发布者下的所有帖子和收藏。",
|
||||
"somethingWentWrong": "发生了一些错误……",
|
||||
"deletePost": "删除帖子",
|
||||
"deletePostHint": "确定要删除这篇帖子吗?",
|
||||
"copyLink": "复制链接",
|
||||
@@ -301,6 +300,7 @@
|
||||
"walletCreate": "创建钱包",
|
||||
"settingsServerUrl": "服务器 URL",
|
||||
"settingsApplied": "设置已应用。",
|
||||
"settingsCustomFontsHelper": "用逗号分隔。",
|
||||
"notifications": "通知",
|
||||
"posts": "帖子",
|
||||
"settingsBackgroundImage": "背景图片",
|
||||
@@ -345,11 +345,10 @@
|
||||
"accountSettingsHelpContent": "此页面允许您管理您的帐户安全性、隐私和其他设置。如果您需要帮助,请联系管理员。",
|
||||
"unauthorized": "未授权",
|
||||
"unauthorizedHint": "您未登录或会话已过期,请重新登录。",
|
||||
"publisherBelongsTo": "属于",
|
||||
"publisherBelongsTo": "属于 {}",
|
||||
"postContent": "内容",
|
||||
"postSettings": "设置",
|
||||
"postPublisherUnselected": "未指定发布者",
|
||||
"postVisibility": "可见性",
|
||||
"postVisibilityPublic": "公开",
|
||||
"postVisibilityFriends": "仅好友可见",
|
||||
"postVisibilityUnlisted": "不公开",
|
||||
@@ -501,9 +500,6 @@
|
||||
"membershipTierNova": "新星",
|
||||
"membershipTierSupernova": "超新星",
|
||||
"membershipTierUnknown": "未知",
|
||||
"membershipPriceStellar": "每月 10 金点",
|
||||
"membershipPriceNova": "每月 20 金点",
|
||||
"membershipPriceSupernova": "每月 30 金点",
|
||||
"membershipFeatureBasic": "基础功能",
|
||||
"membershipFeaturePrioritySupport": "优先支持",
|
||||
"membershipFeatureAdFree": "无广告",
|
||||
@@ -573,37 +569,36 @@
|
||||
"share": "分享",
|
||||
"sharePost": "分享帖子",
|
||||
"quickActions": "快捷操作",
|
||||
"post": "帖子",
|
||||
"post": "发帖",
|
||||
"copy": "复制",
|
||||
"sendToChat": "发送到聊天",
|
||||
"failedToShareToPost": "分享到帖子失败:{}",
|
||||
"shareToChatComingSoon": "分享到聊天的功能即将到来",
|
||||
"shareToChatComingSoon": "分享到聊天功能即将推出",
|
||||
"failedToShareToChat": "分享到聊天失败:{}",
|
||||
"shareToSpecificChatComingSoon": "分享到 {} 的功能即将到来",
|
||||
"shareToSpecificChatComingSoon": "分享到 {} 功能即将推出",
|
||||
"directChat": "私信",
|
||||
"systemShareComingSoon": "系统分享功能即将到来",
|
||||
"systemShareComingSoon": "系统分享功能即将推出",
|
||||
"failedToShareToSystem": "分享到系统失败:{}",
|
||||
"failedToCopy": "复制失败:{}",
|
||||
"noChatRoomsAvailable": "没有聊天室可用",
|
||||
"failedToLoadChats": "加载聊天室失败",
|
||||
"contentToShare": "要分享的内容:",
|
||||
"unknownChat": "未知聊天室",
|
||||
"addAdditionalMessage": "添加额外消息……",
|
||||
"noChatRoomsAvailable": "无可用聊天室",
|
||||
"failedToLoadChats": "加载聊天失败",
|
||||
"contentToShare": "分享内容:",
|
||||
"unknownChat": "未知聊天",
|
||||
"addAdditionalMessage": "添加附加消息……",
|
||||
"uploadingFiles": "上传文件中……",
|
||||
"sharedSuccessfully": "分享成功!",
|
||||
"shareSuccess": "分享成功!",
|
||||
"shareToSpecificChatSuccess": "分享到 {} 成功!",
|
||||
"wouldYouLikeToGoToChat": "你想要前往聊天页面吗?",
|
||||
"no": "是",
|
||||
"yes": "否",
|
||||
"navigateToChat": "前往聊天室",
|
||||
"wouldYouLikeToNavigateToChat": "你想要前往聊天页面吗?",
|
||||
"shareToSpecificChatSuccess": "成功分享至 {}!",
|
||||
"wouldYouLikeToGoToChat": "是否前往该聊天?",
|
||||
"no": "否",
|
||||
"yes": "是",
|
||||
"navigateToChat": "前往聊天",
|
||||
"abuseReport": "举报",
|
||||
"abuseReportTitle": "举报内容",
|
||||
"abuseReportDescription": "通过举报不合适的内容和行为来帮助我们维护社区的健康稳定发展。",
|
||||
"abuseReportDescription": "举报不当内容或行为,协助维护社区安全。",
|
||||
"abuseReportType": "举报类型",
|
||||
"abuseReportReason": "额外细节",
|
||||
"abuseReportReasonHint": "请提供更多关于此的细节……",
|
||||
"abuseReportReason": "补充详情",
|
||||
"abuseReportReasonHint": "请提供更多详情……",
|
||||
"abuseReportSubmit": "提交举报",
|
||||
"abuseReportSuccess": "举报提交成功,感谢你为社区维护作出贡献。",
|
||||
"abuseReportError": "无法提交举报,请稍后再试。",
|
||||
@@ -629,8 +624,6 @@
|
||||
"chatJoin": "加入聊天",
|
||||
"realmJoin": "加入领域",
|
||||
"realmJoinSuccess": "成功加入领域。",
|
||||
"discoverRealms": "发现领域",
|
||||
"discoverPublishers": "发现发布者",
|
||||
"search": "搜索",
|
||||
"publisherMembers": "合作者",
|
||||
"developerHub": "开发者中心",
|
||||
@@ -679,10 +672,32 @@
|
||||
"discoverWebArticles": "来自站外的文章",
|
||||
"webArticlesStand": "文章亭",
|
||||
"about": "关于",
|
||||
"membershipCancel": "取消会员资格",
|
||||
"membershipCancelConfirm": "你确定要取消会员资格吗?",
|
||||
"membershipCancelHint": "你确定要取消会员资格吗?你将不会再次被扣费。你的会员资格将在当前计费周期结束前保持有效。并且你将无法重新订阅,直到当前订阅结束。",
|
||||
"membershipCancelSuccess": "你的会员资格已成功取消。",
|
||||
"somethingWentWrong": "发生了一些错误",
|
||||
"editedAt": "编辑于 {}",
|
||||
"addAudio": "添加音频",
|
||||
"recordAudio": "录制音频",
|
||||
"linkAttachment": "链接附件",
|
||||
"fileIdCannotBeEmpty": "文件 ID 不能为空",
|
||||
"fileIdLinkHint": "还没有上传到 Solar Network?点击此处打开 Solar Network Drive,自定义您的上传内容。",
|
||||
"failedToFetchFile": "获取文件失败:{}",
|
||||
"callLeave": "离开",
|
||||
"callEnd": "挂断通话",
|
||||
"postType": "帖子类型",
|
||||
"articleAttachmentHint": "附件必须上传并插入到文章主体中才能显示出来。",
|
||||
"postVisibility": "可见性",
|
||||
"currentMembershipMember": "恒星计划成员 · {}",
|
||||
"membershipPriceStellar": "需要用户等级 3+,每月价格 1200 NSP",
|
||||
"membershipPriceNova": "需要用户等级 6+,每月价格 2400 NSP",
|
||||
"membershipPriceSupernova": "需要用户等级 9+,每月价格 3600 NSP",
|
||||
"sharePostPhoto": "通过图片分享帖子",
|
||||
"wouldYouLikeToNavigateToChat": "你想要前往聊天页面吗?",
|
||||
"abuseReports": "举报",
|
||||
"discoverRealms": "发现领域",
|
||||
"discoverPublishers": "发现发布者",
|
||||
"membershipCancel": "取消会员订阅",
|
||||
"membershipCancelConfirm": "你确定要取消会员订阅吗?",
|
||||
"membershipCancelHint": "你确定要取消会员订阅吗?你将不会再次被扣费。你的会员资格将在当前计费周期结束前保持有效。并且你将无法重新订阅,直到当前订阅结束。",
|
||||
"membershipCancelSuccess": "你的会员订阅已成功取消。",
|
||||
"aboutScreenTitle": "关于",
|
||||
"aboutScreenVersionInfo": "版本 {} ({})",
|
||||
"aboutScreenAppInfoSectionTitle": "应用信息",
|
||||
@@ -696,7 +711,7 @@
|
||||
"aboutScreenDeveloperSectionTitle": "开发者",
|
||||
"aboutScreenContactUsTitle": "联系我们",
|
||||
"aboutScreenLicenseTitle": "许可",
|
||||
"aboutScreenLicenseContent": "GNU Affero General Public License v3.0",
|
||||
"aboutScreenLicenseContent": "无法翻译",
|
||||
"aboutScreenCopyright": "版权所有 © Solsynth {}",
|
||||
"aboutScreenMadeWith": "由 Solar Network 团队用 ❤︎️ 制作",
|
||||
"aboutScreenFailedToLoadPackageInfo": "无法加载包信息:{error}",
|
||||
@@ -710,13 +725,13 @@
|
||||
"aboutDeviceName": "设备名称",
|
||||
"aboutDeviceIdentifier": "设备标识符",
|
||||
"donate": "捐赠",
|
||||
"donateDescription": "支持我们继续开发 Solar Network,并保持服务器运行。",
|
||||
"fileId": "文件ID",
|
||||
"fileIdHint": "文件ID是你通过 Solar Network Drive 上传文件后获得的ID。",
|
||||
"donateDescription": "支持我们继续开发 Solar Network,并维持服务器运行。",
|
||||
"fileId": "文件 ID",
|
||||
"fileIdHint": "文件 ID 是你通过 Solar Network Drive 上传文件后获得的 ID。",
|
||||
"translate": "翻译",
|
||||
"translating": "正在翻译",
|
||||
"translated": "已翻译",
|
||||
"reactionThumbUp": "点赞",
|
||||
"reactionThumbUp": "赞",
|
||||
"reactionThumbDown": "踩",
|
||||
"reactionJustOkay": "还行",
|
||||
"reactionCry": "哭",
|
||||
@@ -726,7 +741,7 @@
|
||||
"reactionAngry": "生气",
|
||||
"reactionParty": "派对",
|
||||
"reactionPray": "祈祷",
|
||||
"reactionHeart": "心",
|
||||
"reactionHeart": "爱心",
|
||||
"selectMicrophone": "选择麦克风",
|
||||
"selectCamera": "选择摄像头",
|
||||
"switchedTo": "已切换到 {}",
|
||||
@@ -741,19 +756,21 @@
|
||||
"rename": "重命名",
|
||||
"markAsSensitive": "标记为敏感",
|
||||
"fileName": "文件名",
|
||||
"sensitiveCategories.language": "语言",
|
||||
"sensitiveCategories.sexualContent": "色情内容",
|
||||
"sensitiveCategories.violence": "暴力",
|
||||
"sensitiveCategories.profanity": "亵渎",
|
||||
"sensitiveCategories.hateSpeech": "仇恨言论",
|
||||
"sensitiveCategories.racism": "种族主义",
|
||||
"sensitiveCategories.adultContent": "成人内容",
|
||||
"sensitiveCategories.drugAbuse": "药物滥用",
|
||||
"sensitiveCategories.alcoholAbuse": "酗酒",
|
||||
"sensitiveCategories.gambling": "赌博",
|
||||
"sensitiveCategories.selfHarm": "自残",
|
||||
"sensitiveCategories.childAbuse": "虐待儿童",
|
||||
"sensitiveCategories.other": "其他",
|
||||
"sensitiveCategories": {
|
||||
"language": "语言",
|
||||
"sexualContent": "色情内容",
|
||||
"violence": "暴力",
|
||||
"profanity": "亵渎",
|
||||
"hateSpeech": "仇恨言论",
|
||||
"racism": "种族主义",
|
||||
"adultContent": "成人内容",
|
||||
"drugAbuse": "药物滥用",
|
||||
"alcoholAbuse": "酗酒",
|
||||
"gambling": "赌博",
|
||||
"selfHarm": "自残",
|
||||
"childAbuse": "虐待儿童",
|
||||
"other": "其他"
|
||||
},
|
||||
"poll": "投票",
|
||||
"pollsRecent": "最近投票",
|
||||
"pollCreateNew": "创建新投票",
|
||||
@@ -785,10 +802,60 @@
|
||||
"links": "链接",
|
||||
"addLink": "添加链接",
|
||||
"linkKey": "链接名称",
|
||||
"linkValue": "URL",
|
||||
"linkValue": "链接",
|
||||
"debugOptions": "调试选项",
|
||||
"joinedAt": "加入于 {}",
|
||||
"searchAccounts": "搜索帐号……",
|
||||
"webFeeds": "订阅源",
|
||||
"polls": "投票"
|
||||
"polls": "投票",
|
||||
"sharePostSlogan": "加入 Solar Network 以便探索更多",
|
||||
"filesListAdditional": {
|
||||
"one": "+{} 个文件被折叠",
|
||||
"other": "+{} 个文件被折叠"
|
||||
},
|
||||
"messageJumpNotLoaded": "引用的消息没有被加载,无法跳转。",
|
||||
"postUnlinkRealm": "不关联领域",
|
||||
"postSlug": "别名",
|
||||
"postSlugHint": "这个别名可以用于在网页通过 URL 浏览到你的帖子,它应该在同一发布者中是唯一。",
|
||||
"attachmentOnDevice": "离线",
|
||||
"attachmentOnCloud": "在线",
|
||||
"publisherCollabInvitation": "协作邀请",
|
||||
"publisherCollabInvitationCount": {
|
||||
"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": "机器人"
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
BIN
assets/icons/icon.ico
Normal file
BIN
assets/icons/icon.ico
Normal file
Binary file not shown.
After Width: | Height: | Size: 108 KiB |
BIN
assets/images/media-offline.png
Normal file
BIN
assets/images/media-offline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 307 KiB |
115
ios/Podfile.lock
115
ios/Podfile.lock
@@ -40,24 +40,66 @@ PODS:
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- file_saver (0.0.1):
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- Firebase/Crashlytics (12.0.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseCrashlytics (~> 12.0.0)
|
||||
- Firebase/Messaging (12.0.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 12.0.0)
|
||||
- firebase_analytics (12.0.0):
|
||||
- firebase_core
|
||||
- FirebaseAnalytics (= 12.0.0)
|
||||
- Flutter
|
||||
- firebase_core (4.0.0):
|
||||
- Firebase/CoreOnly (= 12.0.0)
|
||||
- Flutter
|
||||
- firebase_crashlytics (5.0.0):
|
||||
- Firebase/Crashlytics (= 12.0.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- firebase_messaging (16.0.0):
|
||||
- Firebase/Messaging (= 12.0.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseAnalytics (12.0.0):
|
||||
- FirebaseAnalytics/Default (= 12.0.0)
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseInstallations (~> 12.0.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)
|
||||
- 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)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreExtension (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseCoreInternal (12.0.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)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseInstallations (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
@@ -72,6 +114,16 @@ PODS:
|
||||
- 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)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesSwift (~> 2.1)
|
||||
- Flutter (1.0.0)
|
||||
- flutter_app_update (0.0.1):
|
||||
- Flutter
|
||||
@@ -101,6 +153,32 @@ PODS:
|
||||
- gal (1.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- GoogleAdsOnDeviceConversion (2.1.0):
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Core (12.0.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)
|
||||
- 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)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleDataTransport (10.1.0):
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
@@ -114,6 +192,9 @@ PODS:
|
||||
- GoogleUtilities/Logger (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/MethodSwizzler (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Network (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
@@ -162,9 +243,11 @@ PODS:
|
||||
- pointer_interceptor_ios (0.0.1):
|
||||
- Flutter
|
||||
- PromisesObjC (2.4.0)
|
||||
- PromisesSwift (2.4.0):
|
||||
- PromisesObjC (= 2.4.0)
|
||||
- receive_sharing_intent (1.8.1):
|
||||
- Flutter
|
||||
- record_ios (1.0.0):
|
||||
- record_ios (1.1.0):
|
||||
- Flutter
|
||||
- SAMKeychain (1.5.3)
|
||||
- SDWebImage (5.21.1):
|
||||
@@ -222,7 +305,10 @@ 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`)
|
||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
||||
@@ -265,16 +351,24 @@ SPEC REPOS:
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- Firebase
|
||||
- FirebaseAnalytics
|
||||
- FirebaseCore
|
||||
- FirebaseCoreExtension
|
||||
- FirebaseCoreInternal
|
||||
- FirebaseCrashlytics
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- FirebaseRemoteConfigInterop
|
||||
- FirebaseSessions
|
||||
- GoogleAdsOnDeviceConversion
|
||||
- GoogleAppMeasurement
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- Kingfisher
|
||||
- nanopb
|
||||
- OrderedSet
|
||||
- PromisesObjC
|
||||
- PromisesSwift
|
||||
- SAMKeychain
|
||||
- SDWebImage
|
||||
- sqlite3
|
||||
@@ -290,8 +384,14 @@ 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:
|
||||
:path: ".symlinks/plugins/firebase_core/ios"
|
||||
firebase_crashlytics:
|
||||
:path: ".symlinks/plugins/firebase_crashlytics/ios"
|
||||
firebase_messaging:
|
||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||
Flutter:
|
||||
@@ -369,13 +469,21 @@ SPEC CHECKSUMS:
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
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
|
||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
@@ -387,6 +495,8 @@ SPEC CHECKSUMS:
|
||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||
flutter_webrtc: 6f7da106613d52ade777d5b4875a43f48c28b457
|
||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||
GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64
|
||||
GoogleAppMeasurement: 8f6ab04ad6ae493b53fcf56bd26323fb2f1384f3
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||
@@ -404,8 +514,9 @@ SPEC CHECKSUMS:
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
pointer_interceptor_ios: ec847ef8b0915778bed2b2cef636f4d177fa8eed
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||
record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b
|
||||
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
|
@@ -439,6 +439,7 @@
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
8C0351B03869BBF493808288 /* [CP] Embed Pods Frameworks */,
|
||||
5E7D6EF29B671AC7EDBA5649 /* [CP] Copy Pods Resources */,
|
||||
E86CDE9D6464F4F52B910856 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -682,6 +683,24 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
E86CDE9D6464F4F52B910856 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\"";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\n#!/bin/bash\nPATH=\"${PATH}:$FLUTTER_ROOT/bin:${PUB_CACHE}/bin:$HOME/.pub-cache/bin\"\n\nif [ -z \"$PODS_ROOT\" ] || [ ! -d \"$PODS_ROOT/FirebaseCrashlytics\" ]; then\n # Cannot use \"BUILD_DIR%/Build/*\" as per Firebase documentation, it points to \"flutter-project/build/ios/*\" path which doesn't have run script\n DERIVED_DATA_PATH=$(echo \"$BUILD_ROOT\" | sed -E 's|(.*DerivedData/[^/]+).*|\\1|')\n PATH_TO_CRASHLYTICS_UPLOAD_SCRIPT=\"${DERIVED_DATA_PATH}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run\"\nelse\n PATH_TO_CRASHLYTICS_UPLOAD_SCRIPT=\"$PODS_ROOT/FirebaseCrashlytics/run\"\nfi\n\n# Command to upload symbols script used to upload symbols to Firebase server\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=\"$PATH_TO_CRASHLYTICS_UPLOAD_SCRIPT\" --platform=ios --apple-project-path=\"${SRCROOT}\" --env-platform-name=\"${PLATFORM_NAME}\" --env-configuration=\"${CONFIGURATION}\" --env-project-dir=\"${PROJECT_DIR}\" --env-built-products-dir=\"${BUILT_PRODUCTS_DIR}\" --env-dwarf-dsym-folder-path=\"${DWARF_DSYM_FOLDER_PATH}\" --env-dwarf-dsym-file-name=\"${DWARF_DSYM_FILE_NAME}\" --env-infoplist-path=\"${INFOPLIST_PATH}\" --default-config=default\n";
|
||||
};
|
||||
E947029FCA058878F9B63890 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
@@ -68,6 +68,34 @@ 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(
|
||||
|
@@ -1,484 +0,0 @@
|
||||
import 'package:dio/dio.dart';
|
||||
import 'package:island/database/drift_db.dart';
|
||||
import 'package:island/database/message.dart';
|
||||
import 'package:island/models/chat.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/services/file.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:uuid/uuid.dart';
|
||||
|
||||
class MessageRepository {
|
||||
final SnChatRoom room;
|
||||
final SnChatMember identity;
|
||||
final Dio _apiClient;
|
||||
final AppDatabase _database;
|
||||
|
||||
final Map<String, LocalChatMessage> pendingMessages = {};
|
||||
final Map<String, Map<int, double>> fileUploadProgress = {};
|
||||
int? _totalCount;
|
||||
|
||||
MessageRepository(this.room, this.identity, this._apiClient, this._database);
|
||||
|
||||
Future<LocalChatMessage?> getLastMessages() async {
|
||||
final dbMessages = await _database.getMessagesForRoom(
|
||||
room.id,
|
||||
offset: 0,
|
||||
limit: 1,
|
||||
);
|
||||
|
||||
if (dbMessages.isEmpty) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return _database.companionToMessage(dbMessages.first);
|
||||
}
|
||||
|
||||
Future<bool> syncMessages() async {
|
||||
final lastMessage = await getLastMessages();
|
||||
if (lastMessage == null) return false;
|
||||
try {
|
||||
final resp = await _apiClient.post(
|
||||
'/sphere/chat/${room.id}/sync',
|
||||
data: {
|
||||
'last_sync_timestamp':
|
||||
lastMessage.toRemoteMessage().updatedAt.millisecondsSinceEpoch,
|
||||
},
|
||||
);
|
||||
|
||||
final response = MessageSyncResponse.fromJson(resp.data);
|
||||
for (final change in response.changes) {
|
||||
switch (change.action) {
|
||||
case MessageChangeAction.create:
|
||||
await receiveMessage(change.message!);
|
||||
break;
|
||||
case MessageChangeAction.update:
|
||||
await receiveMessageUpdate(change.message!);
|
||||
break;
|
||||
case MessageChangeAction.delete:
|
||||
await receiveMessageDeletion(change.messageId.toString());
|
||||
break;
|
||||
}
|
||||
}
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> listMessages({
|
||||
int offset = 0,
|
||||
int take = 20,
|
||||
bool synced = false,
|
||||
}) async {
|
||||
try {
|
||||
// For initial load, fetch latest messages in the background to sync.
|
||||
if (offset == 0 && !synced) {
|
||||
// Not awaiting this is intentional, for a quicker UI response.
|
||||
// The UI should rely on a stream from the database to get updates.
|
||||
_fetchAndCacheMessages(room.id, offset: 0, take: take).catchError((_) {
|
||||
// Best effort, errors will be handled by later fetches.
|
||||
return <LocalChatMessage>[];
|
||||
});
|
||||
}
|
||||
|
||||
final localMessages = await _getCachedMessages(
|
||||
room.id,
|
||||
offset: offset,
|
||||
take: take,
|
||||
);
|
||||
|
||||
// If local cache has messages, return them. This is the common case for scrolling up.
|
||||
if (localMessages.isNotEmpty) {
|
||||
return localMessages;
|
||||
}
|
||||
|
||||
// If local cache is empty, we've probably reached the end of cached history.
|
||||
// Fetch from remote. This will also be hit on first load if cache is empty.
|
||||
return await _fetchAndCacheMessages(room.id, offset: offset, take: take);
|
||||
} catch (e) {
|
||||
// Final fallback to cache in case of network errors during fetch.
|
||||
final localMessages = await _getCachedMessages(
|
||||
room.id,
|
||||
offset: offset,
|
||||
take: take,
|
||||
);
|
||||
|
||||
if (localMessages.isNotEmpty) {
|
||||
return localMessages;
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> _getCachedMessages(
|
||||
String roomId, {
|
||||
int offset = 0,
|
||||
int take = 20,
|
||||
}) async {
|
||||
// Get messages from local database
|
||||
final dbMessages = await _database.getMessagesForRoom(
|
||||
roomId,
|
||||
offset: offset,
|
||||
limit: take,
|
||||
);
|
||||
final dbLocalMessages =
|
||||
dbMessages.map(_database.companionToMessage).toList();
|
||||
|
||||
// Combine with pending messages for the first page
|
||||
if (offset == 0) {
|
||||
final pendingForRoom =
|
||||
pendingMessages.values.where((msg) => msg.roomId == roomId).toList();
|
||||
|
||||
final allMessages = [...pendingForRoom, ...dbLocalMessages];
|
||||
allMessages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
||||
|
||||
// Remove duplicates by ID, preserving the order
|
||||
final uniqueMessages = <LocalChatMessage>[];
|
||||
final seenIds = <String>{};
|
||||
for (final message in allMessages) {
|
||||
if (seenIds.add(message.id)) {
|
||||
uniqueMessages.add(message);
|
||||
}
|
||||
}
|
||||
return uniqueMessages;
|
||||
}
|
||||
|
||||
return dbLocalMessages;
|
||||
}
|
||||
|
||||
Future<List<LocalChatMessage>> _fetchAndCacheMessages(
|
||||
String roomId, {
|
||||
int offset = 0,
|
||||
int take = 20,
|
||||
}) async {
|
||||
// Use cached total count if available, otherwise fetch it
|
||||
if (_totalCount == null) {
|
||||
final response = await _apiClient.get(
|
||||
'/sphere/chat/$roomId/messages',
|
||||
queryParameters: {'offset': 0, 'take': 1},
|
||||
);
|
||||
_totalCount = int.parse(response.headers['x-total']?.firstOrNull ?? '0');
|
||||
}
|
||||
|
||||
if (offset >= _totalCount!) {
|
||||
return [];
|
||||
}
|
||||
|
||||
final response = await _apiClient.get(
|
||||
'/sphere/chat/$roomId/messages',
|
||||
queryParameters: {'offset': offset, 'take': take},
|
||||
);
|
||||
|
||||
final List<dynamic> data = response.data;
|
||||
// Update total count from response headers
|
||||
_totalCount = int.parse(response.headers['x-total']?.firstOrNull ?? '0');
|
||||
|
||||
final messages =
|
||||
data.map((json) {
|
||||
final remoteMessage = SnChatMessage.fromJson(json);
|
||||
return LocalChatMessage.fromRemoteMessage(
|
||||
remoteMessage,
|
||||
MessageStatus.sent,
|
||||
);
|
||||
}).toList();
|
||||
|
||||
for (final message in messages) {
|
||||
await _database.saveMessage(_database.messageToCompanion(message));
|
||||
if (message.nonce != null) {
|
||||
pendingMessages.removeWhere(
|
||||
(_, pendingMsg) => pendingMsg.nonce == message.nonce,
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
Future<LocalChatMessage> sendMessage(
|
||||
String token,
|
||||
String baseUrl,
|
||||
String roomId,
|
||||
String content,
|
||||
String nonce, {
|
||||
required List<UniversalFile> attachments,
|
||||
Map<String, dynamic>? meta,
|
||||
SnChatMessage? replyingTo,
|
||||
SnChatMessage? forwardingTo,
|
||||
SnChatMessage? editingTo,
|
||||
Function(LocalChatMessage)? onPending,
|
||||
Function(String, Map<int, double>)? onProgress,
|
||||
}) async {
|
||||
// Generate a unique nonce for this message
|
||||
final nonce = const Uuid().v4();
|
||||
|
||||
// Create a local message with pending status
|
||||
final mockMessage = SnChatMessage(
|
||||
id: 'pending_$nonce',
|
||||
chatRoomId: roomId,
|
||||
senderId: identity.id,
|
||||
content: content,
|
||||
createdAt: DateTime.now(),
|
||||
updatedAt: DateTime.now(),
|
||||
nonce: nonce,
|
||||
sender: identity,
|
||||
);
|
||||
|
||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
||||
mockMessage,
|
||||
MessageStatus.pending,
|
||||
);
|
||||
|
||||
// Store in memory and database
|
||||
pendingMessages[localMessage.id] = localMessage;
|
||||
fileUploadProgress[localMessage.id] = {};
|
||||
await _database.saveMessage(_database.messageToCompanion(localMessage));
|
||||
onPending?.call(localMessage);
|
||||
|
||||
try {
|
||||
var cloudAttachments = List.empty(growable: true);
|
||||
// Upload files
|
||||
for (var idx = 0; idx < attachments.length; idx++) {
|
||||
final cloudFile =
|
||||
await putMediaToCloud(
|
||||
fileData: attachments[idx],
|
||||
atk: token,
|
||||
baseUrl: baseUrl,
|
||||
filename: attachments[idx].data.name ?? 'Post media',
|
||||
mimetype:
|
||||
attachments[idx].data.mimeType ??
|
||||
switch (attachments[idx].type) {
|
||||
UniversalFileType.image => 'image/unknown',
|
||||
UniversalFileType.video => 'video/unknown',
|
||||
UniversalFileType.audio => 'audio/unknown',
|
||||
UniversalFileType.file => 'application/octet-stream',
|
||||
},
|
||||
onProgress: (progress, _) {
|
||||
fileUploadProgress[localMessage.id]?[idx] = progress;
|
||||
onProgress?.call(
|
||||
localMessage.id,
|
||||
fileUploadProgress[localMessage.id] ?? {},
|
||||
);
|
||||
},
|
||||
).future;
|
||||
if (cloudFile == null) {
|
||||
throw ArgumentError('Failed to upload the file...');
|
||||
}
|
||||
cloudAttachments.add(cloudFile);
|
||||
}
|
||||
|
||||
// Send to server
|
||||
final response = await _apiClient.request(
|
||||
editingTo == null
|
||||
? '/sphere/chat/$roomId/messages'
|
||||
: '/sphere/chat/$roomId/messages/${editingTo.id}',
|
||||
data: {
|
||||
'content': content,
|
||||
'attachments_id': cloudAttachments.map((e) => e.id).toList(),
|
||||
'replied_message_id': replyingTo?.id,
|
||||
'forwarded_message_id': forwardingTo?.id,
|
||||
'meta': meta,
|
||||
'nonce': nonce,
|
||||
},
|
||||
options: Options(method: editingTo == null ? 'POST' : 'PATCH'),
|
||||
);
|
||||
|
||||
// Update with server response
|
||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
||||
remoteMessage,
|
||||
MessageStatus.sent,
|
||||
);
|
||||
|
||||
// Remove from pending and update in database
|
||||
pendingMessages.remove(localMessage.id);
|
||||
await _database.deleteMessage(localMessage.id);
|
||||
await _database.saveMessage(_database.messageToCompanion(updatedMessage));
|
||||
|
||||
return updatedMessage;
|
||||
} catch (e) {
|
||||
// Update status to failed
|
||||
localMessage.status = MessageStatus.failed;
|
||||
pendingMessages[localMessage.id] = localMessage;
|
||||
await _database.updateMessageStatus(
|
||||
localMessage.id,
|
||||
MessageStatus.failed,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<LocalChatMessage> retryMessage(String pendingMessageId) async {
|
||||
final message = await getMessageById(pendingMessageId);
|
||||
if (message == null) {
|
||||
throw Exception('Message not found');
|
||||
}
|
||||
|
||||
// Update status back to pending
|
||||
message.status = MessageStatus.pending;
|
||||
pendingMessages[pendingMessageId] = message;
|
||||
await _database.updateMessageStatus(
|
||||
pendingMessageId,
|
||||
MessageStatus.pending,
|
||||
);
|
||||
|
||||
try {
|
||||
// Send to server
|
||||
var remoteMessage = message.toRemoteMessage();
|
||||
final response = await _apiClient.post(
|
||||
'/sphere/chat/${message.roomId}/messages',
|
||||
data: {
|
||||
'content': remoteMessage.content,
|
||||
'attachments_id': remoteMessage.attachments,
|
||||
'meta': remoteMessage.meta,
|
||||
'nonce': message.nonce,
|
||||
},
|
||||
);
|
||||
|
||||
// Update with server response
|
||||
remoteMessage = SnChatMessage.fromJson(response.data);
|
||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
||||
remoteMessage,
|
||||
MessageStatus.sent,
|
||||
);
|
||||
|
||||
// Remove from pending and update in database
|
||||
pendingMessages.remove(pendingMessageId);
|
||||
await _database.deleteMessage(pendingMessageId);
|
||||
await _database.saveMessage(_database.messageToCompanion(updatedMessage));
|
||||
|
||||
return updatedMessage;
|
||||
} catch (e) {
|
||||
// Update status to failed
|
||||
message.status = MessageStatus.failed;
|
||||
pendingMessages[pendingMessageId] = message;
|
||||
await _database.updateMessageStatus(
|
||||
pendingMessageId,
|
||||
MessageStatus.failed,
|
||||
);
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<LocalChatMessage> receiveMessage(SnChatMessage remoteMessage) async {
|
||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
||||
remoteMessage,
|
||||
MessageStatus.sent,
|
||||
);
|
||||
|
||||
if (remoteMessage.nonce != null) {
|
||||
pendingMessages.removeWhere(
|
||||
(_, pendingMsg) => pendingMsg.nonce == remoteMessage.nonce,
|
||||
);
|
||||
}
|
||||
|
||||
await _database.saveMessage(_database.messageToCompanion(localMessage));
|
||||
return localMessage;
|
||||
}
|
||||
|
||||
Future<LocalChatMessage> receiveMessageUpdate(
|
||||
SnChatMessage remoteMessage,
|
||||
) async {
|
||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
||||
remoteMessage,
|
||||
MessageStatus.sent,
|
||||
);
|
||||
|
||||
await _database.updateMessage(_database.messageToCompanion(localMessage));
|
||||
return localMessage;
|
||||
}
|
||||
|
||||
Future<void> receiveMessageDeletion(String messageId) async {
|
||||
// Remove from pending messages if exists
|
||||
pendingMessages.remove(messageId);
|
||||
|
||||
// Delete from local database
|
||||
await _database.deleteMessage(messageId);
|
||||
}
|
||||
|
||||
Future<LocalChatMessage> updateMessage(
|
||||
String messageId,
|
||||
String content, {
|
||||
List<SnCloudFile>? attachments,
|
||||
Map<String, dynamic>? meta,
|
||||
}) async {
|
||||
final message = pendingMessages[messageId];
|
||||
if (message != null) {
|
||||
// Update pending message
|
||||
final rmMessage = message.toRemoteMessage();
|
||||
final updatedRemoteMessage = rmMessage.copyWith(
|
||||
content: content,
|
||||
meta: meta ?? rmMessage.meta,
|
||||
);
|
||||
final updatedLocalMessage = LocalChatMessage.fromRemoteMessage(
|
||||
updatedRemoteMessage,
|
||||
MessageStatus.pending,
|
||||
);
|
||||
pendingMessages[messageId] = updatedLocalMessage;
|
||||
await _database.updateMessage(
|
||||
_database.messageToCompanion(updatedLocalMessage),
|
||||
);
|
||||
return message;
|
||||
}
|
||||
|
||||
try {
|
||||
// Update on server
|
||||
final response = await _apiClient.put(
|
||||
'/sphere/chat/${room.id}/messages/$messageId',
|
||||
data: {'content': content, 'attachments': attachments, 'meta': meta},
|
||||
);
|
||||
|
||||
// Update local copy
|
||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
||||
remoteMessage,
|
||||
MessageStatus.sent,
|
||||
);
|
||||
await _database.updateMessage(
|
||||
_database.messageToCompanion(updatedMessage),
|
||||
);
|
||||
return updatedMessage;
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<void> deleteMessage(String messageId) async {
|
||||
try {
|
||||
await _apiClient.delete('/sphere/chat/${room.id}/messages/$messageId');
|
||||
pendingMessages.remove(messageId);
|
||||
await _database.deleteMessage(messageId);
|
||||
} catch (e) {
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
Future<LocalChatMessage?> getMessageById(String messageId) async {
|
||||
try {
|
||||
// Attempt to get the message from the local database
|
||||
final localMessage =
|
||||
await (_database.select(_database.chatMessages)
|
||||
..where((tbl) => tbl.id.equals(messageId))).getSingleOrNull();
|
||||
if (localMessage != null) {
|
||||
return _database.companionToMessage(localMessage);
|
||||
}
|
||||
|
||||
// If not found locally, fetch from the server
|
||||
final response = await _apiClient.get(
|
||||
'/sphere/chat/${room.id}/messages/$messageId',
|
||||
);
|
||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
||||
final message = LocalChatMessage.fromRemoteMessage(
|
||||
remoteMessage,
|
||||
MessageStatus.sent,
|
||||
);
|
||||
|
||||
// Save the fetched message to the local database
|
||||
await _database.saveMessage(_database.messageToCompanion(message));
|
||||
return message;
|
||||
} catch (e) {
|
||||
if (e is DioException) return null;
|
||||
// Handle errors
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
}
|
@@ -61,10 +61,8 @@ class DefaultFirebaseOptions {
|
||||
messagingSenderId: '961776991058',
|
||||
projectId: 'solian-0x001',
|
||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||
androidClientId:
|
||||
'961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com',
|
||||
iosClientId:
|
||||
'961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com',
|
||||
androidClientId: '961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com',
|
||||
iosClientId: '961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com',
|
||||
iosBundleId: 'dev.solsynth.solian',
|
||||
);
|
||||
|
||||
@@ -74,10 +72,8 @@ class DefaultFirebaseOptions {
|
||||
messagingSenderId: '961776991058',
|
||||
projectId: 'solian-0x001',
|
||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||
androidClientId:
|
||||
'961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com',
|
||||
iosClientId:
|
||||
'961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com',
|
||||
androidClientId: '961776991058-r4iv9qoio57ul7utbfpgfrda2etvtch8.apps.googleusercontent.com',
|
||||
iosClientId: '961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com',
|
||||
iosBundleId: 'dev.solsynth.solian',
|
||||
);
|
||||
|
||||
@@ -90,4 +86,5 @@ class DefaultFirebaseOptions {
|
||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||
measurementId: 'G-JD1YEG9D6F',
|
||||
);
|
||||
}
|
||||
|
||||
}
|
@@ -4,10 +4,11 @@ import 'dart:io';
|
||||
import 'package:croppy/croppy.dart';
|
||||
import 'package:easy_localization/easy_localization.dart' hide TextDirection;
|
||||
import 'package:firebase_core/firebase_core.dart';
|
||||
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';
|
||||
@@ -28,7 +29,6 @@ import 'package:relative_time/relative_time.dart';
|
||||
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:island/widgets/keyboard_navigation.dart';
|
||||
import 'package:url_launcher/url_launcher_string.dart';
|
||||
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
||||
|
||||
@@ -62,6 +62,17 @@ void main() async {
|
||||
FirebaseMessaging.onBackgroundMessage(
|
||||
_firebaseMessagingBackgroundHandler,
|
||||
);
|
||||
// Although previous if case checked this. Still check is web or not
|
||||
// Otherwise the web platform will broke due to there is no Platform api on the web
|
||||
// Skip crashlytics setup on debug mode to prevent unexpected report to firebase
|
||||
if ((kIsWeb || !Platform.isWindows) && !kDebugMode) {
|
||||
FlutterError.onError =
|
||||
FirebaseCrashlytics.instance.recordFlutterFatalError;
|
||||
PlatformDispatcher.instance.onError = (error, stack) {
|
||||
FirebaseCrashlytics.instance.recordError(error, stack, fatal: true);
|
||||
return true;
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
log("[SplashScreen] Firebase is ready!");
|
||||
@@ -158,12 +169,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);
|
||||
@@ -175,27 +186,6 @@ class IslandApp extends HookConsumerWidget {
|
||||
if (!kIsWeb && Platform.isLinux) {
|
||||
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) {
|
||||
@@ -245,32 +235,30 @@ class IslandApp extends HookConsumerWidget {
|
||||
|
||||
final router = ref.watch(routerProvider);
|
||||
|
||||
return KeyboardNavigation(
|
||||
child: MaterialApp.router(
|
||||
theme: theme?.light,
|
||||
darkTheme: theme?.dark,
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: router,
|
||||
supportedLocales: context.supportedLocales,
|
||||
localizationsDelegates: [
|
||||
...context.localizationDelegates,
|
||||
CroppyLocalizations.delegate,
|
||||
RelativeTimeLocalizations.delegate,
|
||||
],
|
||||
locale: context.locale,
|
||||
builder: (context, child) {
|
||||
return Overlay(
|
||||
key: globalOverlay,
|
||||
initialEntries: [
|
||||
OverlayEntry(
|
||||
builder:
|
||||
(_) =>
|
||||
WindowScaffold(child: child ?? const SizedBox.shrink()),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
),
|
||||
return MaterialApp.router(
|
||||
theme: theme?.light,
|
||||
darkTheme: theme?.dark,
|
||||
themeMode: ThemeMode.system,
|
||||
routerConfig: router,
|
||||
supportedLocales: context.supportedLocales,
|
||||
localizationsDelegates: [
|
||||
...context.localizationDelegates,
|
||||
CroppyLocalizations.delegate,
|
||||
RelativeTimeLocalizations.delegate,
|
||||
],
|
||||
locale: context.locale,
|
||||
builder: (context, child) {
|
||||
return Overlay(
|
||||
key: globalOverlay,
|
||||
initialEntries: [
|
||||
OverlayEntry(
|
||||
builder:
|
||||
(_) =>
|
||||
WindowScaffold(child: child ?? const SizedBox.shrink()),
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -1,9 +1,10 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/auth.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/models/wallet.dart';
|
||||
|
||||
part 'user.freezed.dart';
|
||||
part 'user.g.dart';
|
||||
part 'account.freezed.dart';
|
||||
part 'account.g.dart';
|
||||
|
||||
@freezed
|
||||
sealed class SnAccount with _$SnAccount {
|
||||
@@ -13,6 +14,7 @@ sealed class SnAccount with _$SnAccount {
|
||||
required String nick,
|
||||
required String language,
|
||||
required bool isSuperuser,
|
||||
required String? automatedId,
|
||||
required SnAccountProfile profile,
|
||||
required SnWalletSubscriptionRef? perkSubscription,
|
||||
@Default([]) List<SnAccountBadge> badges,
|
||||
@@ -69,6 +71,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,
|
||||
@@ -174,3 +178,70 @@ sealed class SnVerificationMark with _$SnVerificationMark {
|
||||
factory SnVerificationMark.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnVerificationMarkFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnAuthDevice with _$SnAuthDevice {
|
||||
const factory SnAuthDevice({
|
||||
required String id,
|
||||
required String deviceId,
|
||||
required String deviceName,
|
||||
required String? deviceLabel,
|
||||
required String accountId,
|
||||
required int platform,
|
||||
@Default(false) bool isCurrent,
|
||||
}) = _SnAuthDevice;
|
||||
|
||||
factory SnAuthDevice.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnAuthDeviceFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnAuthDeviceWithChallenge with _$SnAuthDeviceWithChallenge {
|
||||
const factory SnAuthDeviceWithChallenge({
|
||||
required String id,
|
||||
required String deviceId,
|
||||
required String deviceName,
|
||||
required String? deviceLabel,
|
||||
required String accountId,
|
||||
required int platform,
|
||||
required List<SnAuthChallenge> challenges,
|
||||
@Default(false) bool isCurrent,
|
||||
}) = _SnAuthDeviceWithChallengee;
|
||||
|
||||
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
@@ -1,6 +1,6 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'user.dart';
|
||||
part of 'account.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// JsonSerializableGenerator
|
||||
@@ -12,6 +12,7 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
||||
nick: json['nick'] as String,
|
||||
language: json['language'] 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
|
||||
@@ -39,6 +40,7 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
||||
'nick': instance.nick,
|
||||
'language': instance.language,
|
||||
'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(),
|
||||
@@ -84,6 +86,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 +130,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(),
|
||||
@@ -297,3 +303,113 @@ Map<String, dynamic> _$SnVerificationMarkToJson(_SnVerificationMark instance) =>
|
||||
'description': instance.description,
|
||||
'verified_by': instance.verifiedBy,
|
||||
};
|
||||
|
||||
_SnAuthDevice _$SnAuthDeviceFromJson(Map<String, dynamic> json) =>
|
||||
_SnAuthDevice(
|
||||
id: json['id'] as String,
|
||||
deviceId: json['device_id'] as String,
|
||||
deviceName: json['device_name'] as String,
|
||||
deviceLabel: json['device_label'] as String?,
|
||||
accountId: json['account_id'] as String,
|
||||
platform: (json['platform'] as num).toInt(),
|
||||
isCurrent: json['is_current'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnAuthDeviceToJson(_SnAuthDevice instance) =>
|
||||
<String, dynamic>{
|
||||
'id': instance.id,
|
||||
'device_id': instance.deviceId,
|
||||
'device_name': instance.deviceName,
|
||||
'device_label': instance.deviceLabel,
|
||||
'account_id': instance.accountId,
|
||||
'platform': instance.platform,
|
||||
'is_current': instance.isCurrent,
|
||||
};
|
||||
|
||||
_SnAuthDeviceWithChallengee _$SnAuthDeviceWithChallengeeFromJson(
|
||||
Map<String, dynamic> json,
|
||||
) => _SnAuthDeviceWithChallengee(
|
||||
id: json['id'] as String,
|
||||
deviceId: json['device_id'] as String,
|
||||
deviceName: json['device_name'] as String,
|
||||
deviceLabel: json['device_label'] as String?,
|
||||
accountId: json['account_id'] as String,
|
||||
platform: (json['platform'] as num).toInt(),
|
||||
challenges:
|
||||
(json['challenges'] as List<dynamic>)
|
||||
.map((e) => SnAuthChallenge.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
isCurrent: json['is_current'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnAuthDeviceWithChallengeeToJson(
|
||||
_SnAuthDeviceWithChallengee instance,
|
||||
) => <String, dynamic>{
|
||||
'id': instance.id,
|
||||
'device_id': instance.deviceId,
|
||||
'device_name': instance.deviceName,
|
||||
'device_label': instance.deviceLabel,
|
||||
'account_id': instance.accountId,
|
||||
'platform': instance.platform,
|
||||
'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(),
|
||||
};
|
@@ -1,5 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
|
||||
part 'activity.freezed.dart';
|
||||
part 'activity.g.dart';
|
||||
@@ -54,7 +54,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) =>
|
||||
|
@@ -861,7 +861,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 +894,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 +916,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 +1010,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnEventCalendarEntry() when $default != null:
|
||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||
@@ -1031,7 +1031,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnEventCalendarEntry():
|
||||
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
||||
@@ -1048,7 +1048,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);}
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnEventCalendarEntry() when $default != null:
|
||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||
@@ -1063,13 +1063,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 +1109,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 +1131,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>,
|
||||
));
|
||||
}
|
||||
|
||||
|
@@ -87,7 +87,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 +98,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(),
|
||||
};
|
||||
|
@@ -19,14 +19,12 @@ sealed class SnAuthChallenge with _$SnAuthChallenge {
|
||||
required int stepRemain,
|
||||
required int stepTotal,
|
||||
required int failedAttempts,
|
||||
required int platform,
|
||||
required int type,
|
||||
required List<String> blacklistFactors,
|
||||
required List<dynamic> audiences,
|
||||
required List<dynamic> scopes,
|
||||
required String ipAddress,
|
||||
required String userAgent,
|
||||
required String deviceId,
|
||||
required String? nonce,
|
||||
required String? location,
|
||||
required String accountId,
|
||||
@@ -76,22 +74,6 @@ sealed class SnAuthFactor with _$SnAuthFactor {
|
||||
_$SnAuthFactorFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnAuthDevice with _$SnAuthDevice {
|
||||
const factory SnAuthDevice({
|
||||
required dynamic label,
|
||||
required String userAgent,
|
||||
required String deviceId,
|
||||
required int platform,
|
||||
required List<SnAuthSession> sessions,
|
||||
// Not from backend, used for UI
|
||||
@Default(false) bool isCurrent,
|
||||
}) = _SnAuthDevice;
|
||||
|
||||
factory SnAuthDevice.fromJson(Map<String, dynamic> json) =>
|
||||
_$SnAuthDeviceFromJson(json);
|
||||
}
|
||||
|
||||
@freezed
|
||||
sealed class SnAccountConnection with _$SnAccountConnection {
|
||||
const factory SnAccountConnection({
|
||||
|
@@ -272,7 +272,7 @@ as String,
|
||||
/// @nodoc
|
||||
mixin _$SnAuthChallenge {
|
||||
|
||||
String get id; DateTime get expiredAt; int get stepRemain; int get stepTotal; int get failedAttempts; int get platform; int get type; List<String> get blacklistFactors; List<dynamic> get audiences; List<dynamic> get scopes; String get ipAddress; String get userAgent; String get deviceId; 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; String? 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)
|
||||
@@ -285,16 +285,16 @@ $SnAuthChallengeCopyWith<SnAuthChallenge> get copyWith => _$SnAuthChallengeCopyW
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthChallenge&&(identical(other.id, id) || other.id == id)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.stepRemain, stepRemain) || other.stepRemain == stepRemain)&&(identical(other.stepTotal, stepTotal) || other.stepTotal == stepTotal)&&(identical(other.failedAttempts, failedAttempts) || other.failedAttempts == failedAttempts)&&(identical(other.platform, platform) || other.platform == platform)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.blacklistFactors, blacklistFactors)&&const DeepCollectionEquality().equals(other.audiences, audiences)&&const DeepCollectionEquality().equals(other.scopes, scopes)&&(identical(other.ipAddress, ipAddress) || other.ipAddress == ipAddress)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&(identical(other.location, location) || other.location == location)&&(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));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthChallenge&&(identical(other.id, id) || other.id == id)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.stepRemain, stepRemain) || other.stepRemain == stepRemain)&&(identical(other.stepTotal, stepTotal) || other.stepTotal == stepTotal)&&(identical(other.failedAttempts, failedAttempts) || other.failedAttempts == failedAttempts)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.blacklistFactors, blacklistFactors)&&const DeepCollectionEquality().equals(other.audiences, audiences)&&const DeepCollectionEquality().equals(other.scopes, scopes)&&(identical(other.ipAddress, ipAddress) || other.ipAddress == ipAddress)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&(identical(other.location, location) || other.location == location)&&(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.hashAll([runtimeType,id,expiredAt,stepRemain,stepTotal,failedAttempts,platform,type,const DeepCollectionEquality().hash(blacklistFactors),const DeepCollectionEquality().hash(audiences),const DeepCollectionEquality().hash(scopes),ipAddress,userAgent,deviceId,nonce,location,accountId,createdAt,updatedAt,deletedAt]);
|
||||
int get hashCode => Object.hash(runtimeType,id,expiredAt,stepRemain,stepTotal,failedAttempts,type,const DeepCollectionEquality().hash(blacklistFactors),const DeepCollectionEquality().hash(audiences),const DeepCollectionEquality().hash(scopes),ipAddress,userAgent,nonce,location,accountId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, failedAttempts: $failedAttempts, platform: $platform, type: $type, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, deviceId: $deviceId, nonce: $nonce, location: $location, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, failedAttempts: $failedAttempts, type: $type, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, nonce: $nonce, location: $location, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -305,7 +305,7 @@ 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 platform, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String deviceId, 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, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@@ -322,21 +322,19 @@ 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? platform = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? deviceId = 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 = 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,}) {
|
||||
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 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,platform: null == platform ? _self.platform : platform // ignore: cast_nullable_to_non_nullable
|
||||
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as int,blacklistFactors: null == blacklistFactors ? _self.blacklistFactors : blacklistFactors // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,audiences: null == audiences ? _self.audiences : audiences // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,scopes: null == scopes ? _self.scopes : scopes // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // ignore: cast_nullable_to_non_nullable
|
||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||
as String,deviceId: null == deviceId ? _self.deviceId : deviceId // 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
|
||||
@@ -425,10 +423,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int platform, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String deviceId, 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, String? 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.platform,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.deviceId,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
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 _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -446,10 +444,10 @@ 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 platform, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String deviceId, 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, String? 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.platform,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.deviceId,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
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);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -463,10 +461,10 @@ 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 platform, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String deviceId, 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, String? 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.platform,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.deviceId,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
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 _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -478,7 +476,7 @@ return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAuthChallenge implements SnAuthChallenge {
|
||||
const _SnAuthChallenge({required this.id, required this.expiredAt, required this.stepRemain, required this.stepTotal, required this.failedAttempts, required this.platform, required this.type, required final List<String> blacklistFactors, required final List<dynamic> audiences, required final List<dynamic> scopes, required this.ipAddress, required this.userAgent, required this.deviceId, required this.nonce, required this.location, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _blacklistFactors = blacklistFactors,_audiences = audiences,_scopes = scopes;
|
||||
const _SnAuthChallenge({required this.id, required this.expiredAt, required this.stepRemain, required this.stepTotal, required this.failedAttempts, required this.type, required final List<String> blacklistFactors, required final List<dynamic> audiences, required final List<dynamic> scopes, required this.ipAddress, required this.userAgent, required this.nonce, required this.location, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt}): _blacklistFactors = blacklistFactors,_audiences = audiences,_scopes = scopes;
|
||||
factory _SnAuthChallenge.fromJson(Map<String, dynamic> json) => _$SnAuthChallengeFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -486,7 +484,6 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
||||
@override final int stepRemain;
|
||||
@override final int stepTotal;
|
||||
@override final int failedAttempts;
|
||||
@override final int platform;
|
||||
@override final int type;
|
||||
final List<String> _blacklistFactors;
|
||||
@override List<String> get blacklistFactors {
|
||||
@@ -511,7 +508,6 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
||||
|
||||
@override final String ipAddress;
|
||||
@override final String userAgent;
|
||||
@override final String deviceId;
|
||||
@override final String? nonce;
|
||||
@override final String? location;
|
||||
@override final String accountId;
|
||||
@@ -532,16 +528,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAuthChallenge&&(identical(other.id, id) || other.id == id)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.stepRemain, stepRemain) || other.stepRemain == stepRemain)&&(identical(other.stepTotal, stepTotal) || other.stepTotal == stepTotal)&&(identical(other.failedAttempts, failedAttempts) || other.failedAttempts == failedAttempts)&&(identical(other.platform, platform) || other.platform == platform)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._blacklistFactors, _blacklistFactors)&&const DeepCollectionEquality().equals(other._audiences, _audiences)&&const DeepCollectionEquality().equals(other._scopes, _scopes)&&(identical(other.ipAddress, ipAddress) || other.ipAddress == ipAddress)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&(identical(other.location, location) || other.location == location)&&(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));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAuthChallenge&&(identical(other.id, id) || other.id == id)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.stepRemain, stepRemain) || other.stepRemain == stepRemain)&&(identical(other.stepTotal, stepTotal) || other.stepTotal == stepTotal)&&(identical(other.failedAttempts, failedAttempts) || other.failedAttempts == failedAttempts)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._blacklistFactors, _blacklistFactors)&&const DeepCollectionEquality().equals(other._audiences, _audiences)&&const DeepCollectionEquality().equals(other._scopes, _scopes)&&(identical(other.ipAddress, ipAddress) || other.ipAddress == ipAddress)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&(identical(other.location, location) || other.location == location)&&(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.hashAll([runtimeType,id,expiredAt,stepRemain,stepTotal,failedAttempts,platform,type,const DeepCollectionEquality().hash(_blacklistFactors),const DeepCollectionEquality().hash(_audiences),const DeepCollectionEquality().hash(_scopes),ipAddress,userAgent,deviceId,nonce,location,accountId,createdAt,updatedAt,deletedAt]);
|
||||
int get hashCode => Object.hash(runtimeType,id,expiredAt,stepRemain,stepTotal,failedAttempts,type,const DeepCollectionEquality().hash(_blacklistFactors),const DeepCollectionEquality().hash(_audiences),const DeepCollectionEquality().hash(_scopes),ipAddress,userAgent,nonce,location,accountId,createdAt,updatedAt,deletedAt);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, failedAttempts: $failedAttempts, platform: $platform, type: $type, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, deviceId: $deviceId, nonce: $nonce, location: $location, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, failedAttempts: $failedAttempts, type: $type, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, nonce: $nonce, location: $location, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
}
|
||||
|
||||
|
||||
@@ -552,7 +548,7 @@ 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 platform, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String deviceId, 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, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
});
|
||||
|
||||
|
||||
@@ -569,21 +565,19 @@ 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? platform = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? deviceId = 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 = 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,}) {
|
||||
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 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,platform: null == platform ? _self.platform : platform // ignore: cast_nullable_to_non_nullable
|
||||
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as int,blacklistFactors: null == blacklistFactors ? _self._blacklistFactors : blacklistFactors // ignore: cast_nullable_to_non_nullable
|
||||
as List<String>,audiences: null == audiences ? _self._audiences : audiences // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,scopes: null == scopes ? _self._scopes : scopes // ignore: cast_nullable_to_non_nullable
|
||||
as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // ignore: cast_nullable_to_non_nullable
|
||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||
as String,deviceId: null == deviceId ? _self.deviceId : deviceId // 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
|
||||
@@ -1189,286 +1183,6 @@ as Map<String, dynamic>?,
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnAuthDevice {
|
||||
|
||||
dynamic get label; String get userAgent; String get deviceId; int get platform; List<SnAuthSession> get sessions;// Not from backend, used for UI
|
||||
bool get isCurrent;
|
||||
/// Create a copy of SnAuthDevice
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAuthDeviceCopyWith<SnAuthDevice> get copyWith => _$SnAuthDeviceCopyWithImpl<SnAuthDevice>(this as SnAuthDevice, _$identity);
|
||||
|
||||
/// Serializes this SnAuthDevice to a JSON map.
|
||||
Map<String, dynamic> toJson();
|
||||
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthDevice&&const DeepCollectionEquality().equals(other.label, label)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.platform, platform) || other.platform == platform)&&const DeepCollectionEquality().equals(other.sessions, sessions)&&(identical(other.isCurrent, isCurrent) || other.isCurrent == isCurrent));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(label),userAgent,deviceId,platform,const DeepCollectionEquality().hash(sessions),isCurrent);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAuthDevice(label: $label, userAgent: $userAgent, deviceId: $deviceId, platform: $platform, sessions: $sessions, isCurrent: $isCurrent)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class $SnAuthDeviceCopyWith<$Res> {
|
||||
factory $SnAuthDeviceCopyWith(SnAuthDevice value, $Res Function(SnAuthDevice) _then) = _$SnAuthDeviceCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
dynamic label, String userAgent, String deviceId, int platform, List<SnAuthSession> sessions, bool isCurrent
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class _$SnAuthDeviceCopyWithImpl<$Res>
|
||||
implements $SnAuthDeviceCopyWith<$Res> {
|
||||
_$SnAuthDeviceCopyWithImpl(this._self, this._then);
|
||||
|
||||
final SnAuthDevice _self;
|
||||
final $Res Function(SnAuthDevice) _then;
|
||||
|
||||
/// Create a copy of SnAuthDevice
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? label = freezed,Object? userAgent = null,Object? deviceId = null,Object? platform = null,Object? sessions = null,Object? isCurrent = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||
as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable
|
||||
as String,platform: null == platform ? _self.platform : platform // ignore: cast_nullable_to_non_nullable
|
||||
as int,sessions: null == sessions ? _self.sessions : sessions // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnAuthSession>,isCurrent: null == isCurrent ? _self.isCurrent : isCurrent // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// Adds pattern-matching-related methods to [SnAuthDevice].
|
||||
extension SnAuthDevicePatterns on SnAuthDevice {
|
||||
/// 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( _SnAuthDevice value)? $default,{required TResult orElse(),}){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthDevice() 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( _SnAuthDevice value) $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthDevice():
|
||||
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( _SnAuthDevice value)? $default,){
|
||||
final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthDevice() 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( dynamic label, String userAgent, String deviceId, int platform, List<SnAuthSession> sessions, bool isCurrent)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthDevice() when $default != null:
|
||||
return $default(_that.label,_that.userAgent,_that.deviceId,_that.platform,_that.sessions,_that.isCurrent);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( dynamic label, String userAgent, String deviceId, int platform, List<SnAuthSession> sessions, bool isCurrent) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthDevice():
|
||||
return $default(_that.label,_that.userAgent,_that.deviceId,_that.platform,_that.sessions,_that.isCurrent);}
|
||||
}
|
||||
/// 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( dynamic label, String userAgent, String deviceId, int platform, List<SnAuthSession> sessions, bool isCurrent)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnAuthDevice() when $default != null:
|
||||
return $default(_that.label,_that.userAgent,_that.deviceId,_that.platform,_that.sessions,_that.isCurrent);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnAuthDevice implements SnAuthDevice {
|
||||
const _SnAuthDevice({required this.label, required this.userAgent, required this.deviceId, required this.platform, required final List<SnAuthSession> sessions, this.isCurrent = false}): _sessions = sessions;
|
||||
factory _SnAuthDevice.fromJson(Map<String, dynamic> json) => _$SnAuthDeviceFromJson(json);
|
||||
|
||||
@override final dynamic label;
|
||||
@override final String userAgent;
|
||||
@override final String deviceId;
|
||||
@override final int platform;
|
||||
final List<SnAuthSession> _sessions;
|
||||
@override List<SnAuthSession> get sessions {
|
||||
if (_sessions is EqualUnmodifiableListView) return _sessions;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableListView(_sessions);
|
||||
}
|
||||
|
||||
// Not from backend, used for UI
|
||||
@override@JsonKey() final bool isCurrent;
|
||||
|
||||
/// Create a copy of SnAuthDevice
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@pragma('vm:prefer-inline')
|
||||
_$SnAuthDeviceCopyWith<_SnAuthDevice> get copyWith => __$SnAuthDeviceCopyWithImpl<_SnAuthDevice>(this, _$identity);
|
||||
|
||||
@override
|
||||
Map<String, dynamic> toJson() {
|
||||
return _$SnAuthDeviceToJson(this, );
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAuthDevice&&const DeepCollectionEquality().equals(other.label, label)&&(identical(other.userAgent, userAgent) || other.userAgent == userAgent)&&(identical(other.deviceId, deviceId) || other.deviceId == deviceId)&&(identical(other.platform, platform) || other.platform == platform)&&const DeepCollectionEquality().equals(other._sessions, _sessions)&&(identical(other.isCurrent, isCurrent) || other.isCurrent == isCurrent));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(label),userAgent,deviceId,platform,const DeepCollectionEquality().hash(_sessions),isCurrent);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnAuthDevice(label: $label, userAgent: $userAgent, deviceId: $deviceId, platform: $platform, sessions: $sessions, isCurrent: $isCurrent)';
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/// @nodoc
|
||||
abstract mixin class _$SnAuthDeviceCopyWith<$Res> implements $SnAuthDeviceCopyWith<$Res> {
|
||||
factory _$SnAuthDeviceCopyWith(_SnAuthDevice value, $Res Function(_SnAuthDevice) _then) = __$SnAuthDeviceCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
dynamic label, String userAgent, String deviceId, int platform, List<SnAuthSession> sessions, bool isCurrent
|
||||
});
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
class __$SnAuthDeviceCopyWithImpl<$Res>
|
||||
implements _$SnAuthDeviceCopyWith<$Res> {
|
||||
__$SnAuthDeviceCopyWithImpl(this._self, this._then);
|
||||
|
||||
final _SnAuthDevice _self;
|
||||
final $Res Function(_SnAuthDevice) _then;
|
||||
|
||||
/// Create a copy of SnAuthDevice
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? label = freezed,Object? userAgent = null,Object? deviceId = null,Object? platform = null,Object? sessions = null,Object? isCurrent = null,}) {
|
||||
return _then(_SnAuthDevice(
|
||||
label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||
as dynamic,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||
as String,deviceId: null == deviceId ? _self.deviceId : deviceId // ignore: cast_nullable_to_non_nullable
|
||||
as String,platform: null == platform ? _self.platform : platform // ignore: cast_nullable_to_non_nullable
|
||||
as int,sessions: null == sessions ? _self._sessions : sessions // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnAuthSession>,isCurrent: null == isCurrent ? _self.isCurrent : isCurrent // ignore: cast_nullable_to_non_nullable
|
||||
as bool,
|
||||
));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/// @nodoc
|
||||
mixin _$SnAccountConnection {
|
||||
|
||||
|
@@ -20,7 +20,6 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||
stepRemain: (json['step_remain'] as num).toInt(),
|
||||
stepTotal: (json['step_total'] as num).toInt(),
|
||||
failedAttempts: (json['failed_attempts'] as num).toInt(),
|
||||
platform: (json['platform'] as num).toInt(),
|
||||
type: (json['type'] as num).toInt(),
|
||||
blacklistFactors:
|
||||
(json['blacklist_factors'] as List<dynamic>)
|
||||
@@ -30,7 +29,6 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||
scopes: json['scopes'] as List<dynamic>,
|
||||
ipAddress: json['ip_address'] as String,
|
||||
userAgent: json['user_agent'] as String,
|
||||
deviceId: json['device_id'] as String,
|
||||
nonce: json['nonce'] as String?,
|
||||
location: json['location'] as String?,
|
||||
accountId: json['account_id'] as String,
|
||||
@@ -49,14 +47,12 @@ Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
||||
'step_remain': instance.stepRemain,
|
||||
'step_total': instance.stepTotal,
|
||||
'failed_attempts': instance.failedAttempts,
|
||||
'platform': instance.platform,
|
||||
'type': instance.type,
|
||||
'blacklist_factors': instance.blacklistFactors,
|
||||
'audiences': instance.audiences,
|
||||
'scopes': instance.scopes,
|
||||
'ip_address': instance.ipAddress,
|
||||
'user_agent': instance.userAgent,
|
||||
'device_id': instance.deviceId,
|
||||
'nonce': instance.nonce,
|
||||
'location': instance.location,
|
||||
'account_id': instance.accountId,
|
||||
@@ -133,29 +129,6 @@ Map<String, dynamic> _$SnAuthFactorToJson(_SnAuthFactor instance) =>
|
||||
'created_response': instance.createdResponse,
|
||||
};
|
||||
|
||||
_SnAuthDevice _$SnAuthDeviceFromJson(Map<String, dynamic> json) =>
|
||||
_SnAuthDevice(
|
||||
label: json['label'],
|
||||
userAgent: json['user_agent'] as String,
|
||||
deviceId: json['device_id'] as String,
|
||||
platform: (json['platform'] as num).toInt(),
|
||||
sessions:
|
||||
(json['sessions'] as List<dynamic>)
|
||||
.map((e) => SnAuthSession.fromJson(e as Map<String, dynamic>))
|
||||
.toList(),
|
||||
isCurrent: json['is_current'] as bool? ?? false,
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnAuthDeviceToJson(_SnAuthDevice instance) =>
|
||||
<String, dynamic>{
|
||||
'label': instance.label,
|
||||
'user_agent': instance.userAgent,
|
||||
'device_id': instance.deviceId,
|
||||
'platform': instance.platform,
|
||||
'sessions': instance.sessions.map((e) => e.toJson()).toList(),
|
||||
'is_current': instance.isCurrent,
|
||||
};
|
||||
|
||||
_SnAccountConnection _$SnAccountConnectionFromJson(Map<String, dynamic> json) =>
|
||||
_SnAccountConnection(
|
||||
id: json['id'] as String,
|
||||
|
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,
|
||||
};
|
@@ -1,7 +1,7 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/models/realm.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
|
||||
part 'chat.freezed.dart';
|
||||
part 'chat.g.dart';
|
||||
@@ -91,6 +91,7 @@ sealed class SnChatMember with _$SnChatMember {
|
||||
required DateTime? breakUntil,
|
||||
required DateTime? timeoutUntil,
|
||||
required bool isBot,
|
||||
required SnAccountStatus? status,
|
||||
// Frontend data
|
||||
DateTime? lastTyped,
|
||||
}) = _SnChatMember;
|
||||
@@ -103,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) =>
|
||||
|
@@ -1037,7 +1037,7 @@ $SnChatMemberCopyWith<$Res> get sender {
|
||||
/// @nodoc
|
||||
mixin _$SnChatMember {
|
||||
|
||||
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String get chatRoomId; SnChatRoom? get chatRoom; String get accountId; SnAccount get account; String? get nick; int get role; int get notify; DateTime? get joinedAt; DateTime? get breakUntil; DateTime? get timeoutUntil; bool get isBot;// Frontend data
|
||||
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String get chatRoomId; SnChatRoom? get chatRoom; String get accountId; SnAccount get account; String? get nick; int get role; int get notify; DateTime? get joinedAt; DateTime? get breakUntil; DateTime? get timeoutUntil; bool get isBot; SnAccountStatus? get status;// Frontend data
|
||||
DateTime? get lastTyped;
|
||||
/// Create a copy of SnChatMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -1051,16 +1051,16 @@ $SnChatMemberCopyWith<SnChatMember> get copyWith => _$SnChatMemberCopyWithImpl<S
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.status, status) || other.status == status)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,lastTyped);
|
||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,status,lastTyped);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, lastTyped: $lastTyped)';
|
||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, status: $status, lastTyped: $lastTyped)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1071,11 +1071,11 @@ abstract mixin class $SnChatMemberCopyWith<$Res> {
|
||||
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped
|
||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped
|
||||
});
|
||||
|
||||
|
||||
$SnChatRoomCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;
|
||||
$SnChatRoomCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;$SnAccountStatusCopyWith<$Res>? get status;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1088,7 +1088,7 @@ class _$SnChatMemberCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnChatMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? lastTyped = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? status = freezed,Object? lastTyped = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
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
|
||||
@@ -1105,7 +1105,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
||||
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,timeoutUntil: freezed == timeoutUntil ? _self.timeoutUntil : timeoutUntil // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
||||
as bool,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||
as bool,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountStatus?,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
@@ -1130,6 +1131,18 @@ $SnAccountCopyWith<$Res> get account {
|
||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}/// Create a copy of SnChatMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountStatusCopyWith<$Res>? get status {
|
||||
if (_self.status == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||
return _then(_self.copyWith(status: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1209,10 +1222,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnChatMember() when $default != null:
|
||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);case _:
|
||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -1230,10 +1243,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnChatMember():
|
||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);}
|
||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -1247,10 +1260,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnChatMember() when $default != null:
|
||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);case _:
|
||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -1262,7 +1275,7 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnChatMember implements SnChatMember {
|
||||
const _SnChatMember({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.id, required this.chatRoomId, required this.chatRoom, required this.accountId, required this.account, required this.nick, required this.role, required this.notify, required this.joinedAt, required this.breakUntil, required this.timeoutUntil, required this.isBot, this.lastTyped});
|
||||
const _SnChatMember({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.id, required this.chatRoomId, required this.chatRoom, required this.accountId, required this.account, required this.nick, required this.role, required this.notify, required this.joinedAt, required this.breakUntil, required this.timeoutUntil, required this.isBot, required this.status, this.lastTyped});
|
||||
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
||||
|
||||
@override final DateTime createdAt;
|
||||
@@ -1280,6 +1293,7 @@ class _SnChatMember implements SnChatMember {
|
||||
@override final DateTime? breakUntil;
|
||||
@override final DateTime? timeoutUntil;
|
||||
@override final bool isBot;
|
||||
@override final SnAccountStatus? status;
|
||||
// Frontend data
|
||||
@override final DateTime? lastTyped;
|
||||
|
||||
@@ -1296,16 +1310,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.status, status) || other.status == status)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,lastTyped);
|
||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,status,lastTyped);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, lastTyped: $lastTyped)';
|
||||
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, status: $status, lastTyped: $lastTyped)';
|
||||
}
|
||||
|
||||
|
||||
@@ -1316,11 +1330,11 @@ abstract mixin class _$SnChatMemberCopyWith<$Res> implements $SnChatMemberCopyWi
|
||||
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped
|
||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped
|
||||
});
|
||||
|
||||
|
||||
@override $SnChatRoomCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;
|
||||
@override $SnChatRoomCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;@override $SnAccountStatusCopyWith<$Res>? get status;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -1333,7 +1347,7 @@ class __$SnChatMemberCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnChatMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? lastTyped = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? status = freezed,Object? lastTyped = freezed,}) {
|
||||
return _then(_SnChatMember(
|
||||
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
|
||||
@@ -1350,7 +1364,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
||||
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,timeoutUntil: freezed == timeoutUntil ? _self.timeoutUntil : timeoutUntil // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
||||
as bool,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||
as bool,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountStatus?,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
));
|
||||
}
|
||||
@@ -1376,6 +1391,18 @@ $SnAccountCopyWith<$Res> get account {
|
||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}/// Create a copy of SnChatMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountStatusCopyWith<$Res>? get status {
|
||||
if (_self.status == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||
return _then(_self.copyWith(status: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1383,7 +1410,7 @@ $SnAccountCopyWith<$Res> get account {
|
||||
/// @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)
|
||||
@@ -1416,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
|
||||
@@ -1433,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 {
|
||||
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage, (value) {
|
||||
$SnChatMessageCopyWith<$Res>? get lastMessage {
|
||||
if (_self.lastMessage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage!, (value) {
|
||||
return _then(_self.copyWith(lastMessage: value));
|
||||
});
|
||||
}
|
||||
@@ -1528,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 _:
|
||||
@@ -1549,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);}
|
||||
@@ -1566,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 _:
|
||||
@@ -1585,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.
|
||||
@@ -1620,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
|
||||
@@ -1637,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?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -1649,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 {
|
||||
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage, (value) {
|
||||
$SnChatMessageCopyWith<$Res>? get lastMessage {
|
||||
if (_self.lastMessage == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage!, (value) {
|
||||
return _then(_self.copyWith(lastMessage: value));
|
||||
});
|
||||
}
|
||||
|
@@ -177,6 +177,12 @@ _SnChatMember _$SnChatMemberFromJson(Map<String, dynamic> json) =>
|
||||
? null
|
||||
: DateTime.parse(json['timeout_until'] as String),
|
||||
isBot: json['is_bot'] as bool,
|
||||
status:
|
||||
json['status'] == null
|
||||
? null
|
||||
: SnAccountStatus.fromJson(
|
||||
json['status'] as Map<String, dynamic>,
|
||||
),
|
||||
lastTyped:
|
||||
json['last_typed'] == null
|
||||
? null
|
||||
@@ -200,21 +206,25 @@ Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
||||
'break_until': instance.breakUntil?.toIso8601String(),
|
||||
'timeout_until': instance.timeoutUntil?.toIso8601String(),
|
||||
'is_bot': instance.isBot,
|
||||
'status': instance.status?.toJson(),
|
||||
'last_typed': instance.lastTyped?.toIso8601String(),
|
||||
};
|
||||
|
||||
_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) =>
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
|
||||
part 'custom_app.freezed.dart';
|
||||
part 'custom_app.g.dart';
|
||||
|
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'],
|
||||
);
|
||||
}
|
||||
}
|
@@ -11,8 +11,8 @@ sealed class SnScrappedLink with _$SnScrappedLink {
|
||||
required String title,
|
||||
required String? description,
|
||||
required String? imageUrl,
|
||||
required String faviconUrl,
|
||||
required String siteName,
|
||||
required String? faviconUrl,
|
||||
required String? siteName,
|
||||
required String? contentType,
|
||||
required String? author,
|
||||
required DateTime? publishedDate,
|
||||
|
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
||||
/// @nodoc
|
||||
mixin _$SnScrappedLink {
|
||||
|
||||
String get type; String get url; String get title; String? get description; String? get imageUrl; String get faviconUrl; String get siteName; String? get contentType; String? get author; DateTime? get publishedDate;
|
||||
String get type; String get url; String get title; String? get description; String? get imageUrl; String? get faviconUrl; String? get siteName; String? get contentType; String? get author; DateTime? get publishedDate;
|
||||
/// Create a copy of SnScrappedLink
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -48,7 +48,7 @@ abstract mixin class $SnScrappedLinkCopyWith<$Res> {
|
||||
factory $SnScrappedLinkCopyWith(SnScrappedLink value, $Res Function(SnScrappedLink) _then) = _$SnScrappedLinkCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate
|
||||
String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate
|
||||
});
|
||||
|
||||
|
||||
@@ -65,16 +65,16 @@ class _$SnScrappedLinkCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnScrappedLink
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = null,Object? siteName = null,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = freezed,Object? siteName = freezed,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
||||
as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String?,faviconUrl: null == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String,siteName: null == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
||||
as String,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,faviconUrl: freezed == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String?,siteName: freezed == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable
|
||||
as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
@@ -159,7 +159,7 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnScrappedLink() when $default != null:
|
||||
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _:
|
||||
@@ -180,7 +180,7 @@ return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUr
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnScrappedLink():
|
||||
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);}
|
||||
@@ -197,7 +197,7 @@ return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUr
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnScrappedLink() when $default != null:
|
||||
return $default(_that.type,_that.url,_that.title,_that.description,_that.imageUrl,_that.faviconUrl,_that.siteName,_that.contentType,_that.author,_that.publishedDate);case _:
|
||||
@@ -220,8 +220,8 @@ class _SnScrappedLink implements SnScrappedLink {
|
||||
@override final String title;
|
||||
@override final String? description;
|
||||
@override final String? imageUrl;
|
||||
@override final String faviconUrl;
|
||||
@override final String siteName;
|
||||
@override final String? faviconUrl;
|
||||
@override final String? siteName;
|
||||
@override final String? contentType;
|
||||
@override final String? author;
|
||||
@override final DateTime? publishedDate;
|
||||
@@ -259,7 +259,7 @@ abstract mixin class _$SnScrappedLinkCopyWith<$Res> implements $SnScrappedLinkCo
|
||||
factory _$SnScrappedLinkCopyWith(_SnScrappedLink value, $Res Function(_SnScrappedLink) _then) = __$SnScrappedLinkCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String type, String url, String title, String? description, String? imageUrl, String faviconUrl, String siteName, String? contentType, String? author, DateTime? publishedDate
|
||||
String type, String url, String title, String? description, String? imageUrl, String? faviconUrl, String? siteName, String? contentType, String? author, DateTime? publishedDate
|
||||
});
|
||||
|
||||
|
||||
@@ -276,16 +276,16 @@ class __$SnScrappedLinkCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnScrappedLink
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = null,Object? siteName = null,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? url = null,Object? title = null,Object? description = freezed,Object? imageUrl = freezed,Object? faviconUrl = freezed,Object? siteName = freezed,Object? contentType = freezed,Object? author = freezed,Object? publishedDate = freezed,}) {
|
||||
return _then(_SnScrappedLink(
|
||||
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||
as String,url: null == url ? _self.url : url // ignore: cast_nullable_to_non_nullable
|
||||
as String,title: null == title ? _self.title : title // ignore: cast_nullable_to_non_nullable
|
||||
as String,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||
as String?,imageUrl: freezed == imageUrl ? _self.imageUrl : imageUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String?,faviconUrl: null == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String,siteName: null == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
||||
as String,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,faviconUrl: freezed == faviconUrl ? _self.faviconUrl : faviconUrl // ignore: cast_nullable_to_non_nullable
|
||||
as String?,siteName: freezed == siteName ? _self.siteName : siteName // ignore: cast_nullable_to_non_nullable
|
||||
as String?,contentType: freezed == contentType ? _self.contentType : contentType // ignore: cast_nullable_to_non_nullable
|
||||
as String?,author: freezed == author ? _self.author : author // ignore: cast_nullable_to_non_nullable
|
||||
as String?,publishedDate: freezed == publishedDate ? _self.publishedDate : publishedDate // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,
|
||||
|
@@ -13,8 +13,8 @@ _SnScrappedLink _$SnScrappedLinkFromJson(Map<String, dynamic> json) =>
|
||||
title: json['title'] as String,
|
||||
description: json['description'] as String?,
|
||||
imageUrl: json['image_url'] as String?,
|
||||
faviconUrl: json['favicon_url'] as String,
|
||||
siteName: json['site_name'] as String,
|
||||
faviconUrl: json['favicon_url'] as String?,
|
||||
siteName: json['site_name'] as String?,
|
||||
contentType: json['content_type'] as String?,
|
||||
author: json['author'] as String?,
|
||||
publishedDate:
|
||||
|
@@ -8,7 +8,7 @@ part 'poll.g.dart';
|
||||
sealed class SnPollWithStats with _$SnPollWithStats {
|
||||
const factory SnPollWithStats({
|
||||
required Map<String, dynamic>? userAnswer,
|
||||
required Map<String, dynamic> stats,
|
||||
@Default({}) Map<String, dynamic> stats,
|
||||
required String id,
|
||||
required List<SnPollQuestion> questions,
|
||||
String? title,
|
||||
|
@@ -213,7 +213,7 @@ return $default(_that.userAnswer,_that.stats,_that.id,_that.questions,_that.titl
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnPollWithStats implements SnPollWithStats {
|
||||
const _SnPollWithStats({required final Map<String, dynamic>? userAnswer, required final Map<String, dynamic> stats, required this.id, required final List<SnPollQuestion> questions, this.title, this.description, this.endedAt, required this.publisherId, required this.createdAt, required this.updatedAt, this.deletedAt}): _userAnswer = userAnswer,_stats = stats,_questions = questions;
|
||||
const _SnPollWithStats({required final Map<String, dynamic>? userAnswer, final Map<String, dynamic> stats = const {}, required this.id, required final List<SnPollQuestion> questions, this.title, this.description, this.endedAt, required this.publisherId, required this.createdAt, required this.updatedAt, this.deletedAt}): _userAnswer = userAnswer,_stats = stats,_questions = questions;
|
||||
factory _SnPollWithStats.fromJson(Map<String, dynamic> json) => _$SnPollWithStatsFromJson(json);
|
||||
|
||||
final Map<String, dynamic>? _userAnswer;
|
||||
@@ -226,7 +226,7 @@ class _SnPollWithStats implements SnPollWithStats {
|
||||
}
|
||||
|
||||
final Map<String, dynamic> _stats;
|
||||
@override Map<String, dynamic> get stats {
|
||||
@override@JsonKey() Map<String, dynamic> get stats {
|
||||
if (_stats is EqualUnmodifiableMapView) return _stats;
|
||||
// ignore: implicit_dynamic_type
|
||||
return EqualUnmodifiableMapView(_stats);
|
||||
|
@@ -9,7 +9,7 @@ part of 'poll.dart';
|
||||
_SnPollWithStats _$SnPollWithStatsFromJson(Map<String, dynamic> json) =>
|
||||
_SnPollWithStats(
|
||||
userAnswer: json['user_answer'] as Map<String, dynamic>?,
|
||||
stats: json['stats'] as Map<String, dynamic>,
|
||||
stats: json['stats'] as Map<String, dynamic>? ?? const {},
|
||||
id: json['id'] as String,
|
||||
questions:
|
||||
(json['questions'] as List<dynamic>)
|
||||
|
@@ -3,6 +3,7 @@ import 'package:island/models/file.dart';
|
||||
import 'package:island/models/post_category.dart';
|
||||
import 'package:island/models/post_tag.dart';
|
||||
import 'package:island/models/publisher.dart';
|
||||
import 'package:island/models/realm.dart';
|
||||
|
||||
part 'post.freezed.dart';
|
||||
part 'post.g.dart';
|
||||
@@ -18,6 +19,7 @@ sealed class SnPost with _$SnPost {
|
||||
@Default(null) DateTime? publishedAt,
|
||||
@Default(0) int visibility,
|
||||
String? content,
|
||||
String? slug,
|
||||
@Default(0) int type,
|
||||
Map<String, dynamic>? meta,
|
||||
@Default(0) int viewsUnique,
|
||||
@@ -25,12 +27,15 @@ sealed class SnPost with _$SnPost {
|
||||
@Default(0) int upvotes,
|
||||
@Default(0) int downvotes,
|
||||
@Default(0) int repliesCount,
|
||||
int? pinMode,
|
||||
String? threadedPostId,
|
||||
SnPost? threadedPost,
|
||||
String? repliedPostId,
|
||||
SnPost? repliedPost,
|
||||
String? forwardedPostId,
|
||||
SnPost? forwardedPost,
|
||||
String? realmId,
|
||||
SnRealm? realm,
|
||||
@Default([]) List<SnCloudFile> attachments,
|
||||
required SnPublisher publisher,
|
||||
@Default({}) Map<String, int> reactionsCount,
|
||||
|
@@ -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; int get type; Map<String, dynamic>? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
|
||||
String get id; String? get title; String? get description; String? get language; DateTime? get editedAt; DateTime? get publishedAt; int get visibility; String? get content; String? get slug; int get type; Map<String, dynamic>? get meta; int get viewsUnique; int get viewsTotal; int get upvotes; int get downvotes; int get repliesCount; int? get pinMode; String? get threadedPostId; SnPost? get threadedPost; String? get repliedPostId; SnPost? get repliedPost; String? get forwardedPostId; SnPost? get forwardedPost; String? get realmId; SnRealm? get realm; List<SnCloudFile> get attachments; SnPublisher get publisher; Map<String, int> get reactionsCount; Map<String, bool> get reactionsMade; List<dynamic> get reactions; List<SnPostTag> get tags; List<SnPostCategory> get categories; List<dynamic> get collections; DateTime? get createdAt; DateTime? get updatedAt; DateTime? get deletedAt; bool get isTruncated;
|
||||
/// Create a copy of SnPost
|
||||
/// 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.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other.meta, meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other.reactionsCount, reactionsCount)&&const DeepCollectionEquality().equals(other.reactionsMade, reactionsMade)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&const DeepCollectionEquality().equals(other.tags, tags)&&const DeepCollectionEquality().equals(other.categories, categories)&&const DeepCollectionEquality().equals(other.collections, collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(attachments),publisher,const DeepCollectionEquality().hash(reactionsCount),const DeepCollectionEquality().hash(reactionsMade),const DeepCollectionEquality().hash(reactions),const DeepCollectionEquality().hash(tags),const DeepCollectionEquality().hash(categories),const DeepCollectionEquality().hash(collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
}
|
||||
|
||||
|
||||
@@ -48,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, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
});
|
||||
|
||||
|
||||
$SnPostCopyWith<$Res>? get threadedPost;$SnPostCopyWith<$Res>? get repliedPost;$SnPostCopyWith<$Res>? get forwardedPost;$SnPublisherCopyWith<$Res> get publisher;
|
||||
$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? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
return _then(_self.copyWith(
|
||||
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
|
||||
@@ -75,6 +75,7 @@ as String?,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore:
|
||||
as DateTime?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||
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
|
||||
@@ -82,13 +83,16 @@ as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore:
|
||||
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
||||
as int,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,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
|
||||
as SnPost?,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId : forwardedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
||||
as SnPost?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||
as SnPost?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||
as SnRealm?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||
as SnPublisher,reactionsCount: null == reactionsCount ? _self.reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, int>,reactionsMade: null == reactionsMade ? _self.reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
||||
@@ -143,6 +147,18 @@ $SnPostCopyWith<$Res>? get forwardedPost {
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnRealmCopyWith<$Res>? get realm {
|
||||
if (_self.realm == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnRealmCopyWith<$Res>(_self.realm!, (value) {
|
||||
return _then(_self.copyWith(realm: value));
|
||||
});
|
||||
}/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPublisherCopyWith<$Res> get publisher {
|
||||
|
||||
return $SnPublisherCopyWith<$Res>(_self.publisher, (value) {
|
||||
@@ -227,10 +243,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPost() when $default != null:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -248,10 +264,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPost():
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -265,10 +281,10 @@ return $default(_that.id,_that.title,_that.description,_that.language,_that.edit
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnPost() when $default != null:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return $default(_that.id,_that.title,_that.description,_that.language,_that.editedAt,_that.publishedAt,_that.visibility,_that.content,_that.slug,_that.type,_that.meta,_that.viewsUnique,_that.viewsTotal,_that.upvotes,_that.downvotes,_that.repliesCount,_that.pinMode,_that.threadedPostId,_that.threadedPost,_that.repliedPostId,_that.repliedPost,_that.forwardedPostId,_that.forwardedPost,_that.realmId,_that.realm,_that.attachments,_that.publisher,_that.reactionsCount,_that.reactionsMade,_that.reactions,_that.tags,_that.categories,_that.collections,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.isTruncated);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -280,7 +296,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.type = 0, final Map<String, dynamic>? meta, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
||||
const _SnPost({required this.id, this.title, this.description, this.language, this.editedAt, this.publishedAt = null, this.visibility = 0, this.content, this.slug, this.type = 0, final Map<String, dynamic>? meta, this.viewsUnique = 0, this.viewsTotal = 0, this.upvotes = 0, this.downvotes = 0, this.repliesCount = 0, this.pinMode, this.threadedPostId, this.threadedPost, this.repliedPostId, this.repliedPost, this.forwardedPostId, this.forwardedPost, this.realmId, this.realm, final List<SnCloudFile> attachments = const [], required this.publisher, final Map<String, int> reactionsCount = const {}, final Map<String, bool> reactionsMade = const {}, final List<dynamic> reactions = const [], final List<SnPostTag> tags = const [], final List<SnPostCategory> categories = const [], final List<dynamic> collections = const [], this.createdAt = null, this.updatedAt = null, this.deletedAt, this.isTruncated = false}): _meta = meta,_attachments = attachments,_reactionsCount = reactionsCount,_reactionsMade = reactionsMade,_reactions = reactions,_tags = tags,_categories = categories,_collections = collections;
|
||||
factory _SnPost.fromJson(Map<String, dynamic> json) => _$SnPostFromJson(json);
|
||||
|
||||
@override final String id;
|
||||
@@ -291,6 +307,7 @@ class _SnPost implements SnPost {
|
||||
@override@JsonKey() final DateTime? publishedAt;
|
||||
@override@JsonKey() final int visibility;
|
||||
@override final String? content;
|
||||
@override final String? slug;
|
||||
@override@JsonKey() final int type;
|
||||
final Map<String, dynamic>? _meta;
|
||||
@override Map<String, dynamic>? get meta {
|
||||
@@ -306,12 +323,15 @@ class _SnPost implements SnPost {
|
||||
@override@JsonKey() final int upvotes;
|
||||
@override@JsonKey() final int downvotes;
|
||||
@override@JsonKey() final int repliesCount;
|
||||
@override final int? pinMode;
|
||||
@override final String? threadedPostId;
|
||||
@override final SnPost? threadedPost;
|
||||
@override final String? repliedPostId;
|
||||
@override final SnPost? repliedPost;
|
||||
@override final String? forwardedPostId;
|
||||
@override final SnPost? forwardedPost;
|
||||
@override final String? realmId;
|
||||
@override final SnRealm? realm;
|
||||
final List<SnCloudFile> _attachments;
|
||||
@override@JsonKey() List<SnCloudFile> get attachments {
|
||||
if (_attachments is EqualUnmodifiableListView) return _attachments;
|
||||
@@ -380,16 +400,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.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPost&&(identical(other.id, id) || other.id == id)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.language, language) || other.language == language)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&(identical(other.publishedAt, publishedAt) || other.publishedAt == publishedAt)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.content, content) || other.content == content)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.type, type) || other.type == type)&&const DeepCollectionEquality().equals(other._meta, _meta)&&(identical(other.viewsUnique, viewsUnique) || other.viewsUnique == viewsUnique)&&(identical(other.viewsTotal, viewsTotal) || other.viewsTotal == viewsTotal)&&(identical(other.upvotes, upvotes) || other.upvotes == upvotes)&&(identical(other.downvotes, downvotes) || other.downvotes == downvotes)&&(identical(other.repliesCount, repliesCount) || other.repliesCount == repliesCount)&&(identical(other.pinMode, pinMode) || other.pinMode == pinMode)&&(identical(other.threadedPostId, threadedPostId) || other.threadedPostId == threadedPostId)&&(identical(other.threadedPost, threadedPost) || other.threadedPost == threadedPost)&&(identical(other.repliedPostId, repliedPostId) || other.repliedPostId == repliedPostId)&&(identical(other.repliedPost, repliedPost) || other.repliedPost == repliedPost)&&(identical(other.forwardedPostId, forwardedPostId) || other.forwardedPostId == forwardedPostId)&&(identical(other.forwardedPost, forwardedPost) || other.forwardedPost == forwardedPost)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&(identical(other.publisher, publisher) || other.publisher == publisher)&&const DeepCollectionEquality().equals(other._reactionsCount, _reactionsCount)&&const DeepCollectionEquality().equals(other._reactionsMade, _reactionsMade)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&const DeepCollectionEquality().equals(other._tags, _tags)&&const DeepCollectionEquality().equals(other._categories, _categories)&&const DeepCollectionEquality().equals(other._collections, _collections)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.isTruncated, isTruncated) || other.isTruncated == isTruncated));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
int get hashCode => Object.hashAll([runtimeType,id,title,description,language,editedAt,publishedAt,visibility,content,slug,type,const DeepCollectionEquality().hash(_meta),viewsUnique,viewsTotal,upvotes,downvotes,repliesCount,pinMode,threadedPostId,threadedPost,repliedPostId,repliedPost,forwardedPostId,forwardedPost,realmId,realm,const DeepCollectionEquality().hash(_attachments),publisher,const DeepCollectionEquality().hash(_reactionsCount),const DeepCollectionEquality().hash(_reactionsMade),const DeepCollectionEquality().hash(_reactions),const DeepCollectionEquality().hash(_tags),const DeepCollectionEquality().hash(_categories),const DeepCollectionEquality().hash(_collections),createdAt,updatedAt,deletedAt,isTruncated]);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
return 'SnPost(id: $id, title: $title, description: $description, language: $language, editedAt: $editedAt, publishedAt: $publishedAt, visibility: $visibility, content: $content, slug: $slug, type: $type, meta: $meta, viewsUnique: $viewsUnique, viewsTotal: $viewsTotal, upvotes: $upvotes, downvotes: $downvotes, repliesCount: $repliesCount, pinMode: $pinMode, threadedPostId: $threadedPostId, threadedPost: $threadedPost, repliedPostId: $repliedPostId, repliedPost: $repliedPost, forwardedPostId: $forwardedPostId, forwardedPost: $forwardedPost, realmId: $realmId, realm: $realm, attachments: $attachments, publisher: $publisher, reactionsCount: $reactionsCount, reactionsMade: $reactionsMade, reactions: $reactions, tags: $tags, categories: $categories, collections: $collections, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, isTruncated: $isTruncated)';
|
||||
}
|
||||
|
||||
|
||||
@@ -400,11 +420,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, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
String id, String? title, String? description, String? language, DateTime? editedAt, DateTime? publishedAt, int visibility, String? content, String? slug, int type, Map<String, dynamic>? meta, int viewsUnique, int viewsTotal, int upvotes, int downvotes, int repliesCount, int? pinMode, String? threadedPostId, SnPost? threadedPost, String? repliedPostId, SnPost? repliedPost, String? forwardedPostId, SnPost? forwardedPost, String? realmId, SnRealm? realm, List<SnCloudFile> attachments, SnPublisher publisher, Map<String, int> reactionsCount, Map<String, bool> reactionsMade, List<dynamic> reactions, List<SnPostTag> tags, List<SnPostCategory> categories, List<dynamic> collections, DateTime? createdAt, DateTime? updatedAt, DateTime? deletedAt, bool isTruncated
|
||||
});
|
||||
|
||||
|
||||
@override $SnPostCopyWith<$Res>? get threadedPost;@override $SnPostCopyWith<$Res>? get repliedPost;@override $SnPostCopyWith<$Res>? get forwardedPost;@override $SnPublisherCopyWith<$Res> get publisher;
|
||||
@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
|
||||
@@ -417,7 +437,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? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? title = freezed,Object? description = freezed,Object? language = freezed,Object? editedAt = freezed,Object? publishedAt = freezed,Object? visibility = null,Object? content = freezed,Object? slug = freezed,Object? type = null,Object? meta = freezed,Object? viewsUnique = null,Object? viewsTotal = null,Object? upvotes = null,Object? downvotes = null,Object? repliesCount = null,Object? pinMode = freezed,Object? threadedPostId = freezed,Object? threadedPost = freezed,Object? repliedPostId = freezed,Object? repliedPost = freezed,Object? forwardedPostId = freezed,Object? forwardedPost = freezed,Object? realmId = freezed,Object? realm = freezed,Object? attachments = null,Object? publisher = null,Object? reactionsCount = null,Object? reactionsMade = null,Object? reactions = null,Object? tags = null,Object? categories = null,Object? collections = null,Object? createdAt = freezed,Object? updatedAt = freezed,Object? deletedAt = freezed,Object? isTruncated = null,}) {
|
||||
return _then(_SnPost(
|
||||
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
|
||||
@@ -427,6 +447,7 @@ as String?,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore:
|
||||
as DateTime?,publishedAt: freezed == publishedAt ? _self.publishedAt : publishedAt // ignore: cast_nullable_to_non_nullable
|
||||
as DateTime?,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
||||
as int,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||
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
|
||||
@@ -434,13 +455,16 @@ as int,viewsTotal: null == viewsTotal ? _self.viewsTotal : viewsTotal // ignore:
|
||||
as int,upvotes: null == upvotes ? _self.upvotes : upvotes // ignore: cast_nullable_to_non_nullable
|
||||
as int,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,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
|
||||
as SnPost?,forwardedPostId: freezed == forwardedPostId ? _self.forwardedPostId : forwardedPostId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,forwardedPost: freezed == forwardedPost ? _self.forwardedPost : forwardedPost // ignore: cast_nullable_to_non_nullable
|
||||
as SnPost?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||
as SnPost?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||
as String?,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||
as SnRealm?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||
as List<SnCloudFile>,publisher: null == publisher ? _self.publisher : publisher // ignore: cast_nullable_to_non_nullable
|
||||
as SnPublisher,reactionsCount: null == reactionsCount ? _self._reactionsCount : reactionsCount // ignore: cast_nullable_to_non_nullable
|
||||
as Map<String, int>,reactionsMade: null == reactionsMade ? _self._reactionsMade : reactionsMade // ignore: cast_nullable_to_non_nullable
|
||||
@@ -496,6 +520,18 @@ $SnPostCopyWith<$Res>? get forwardedPost {
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnRealmCopyWith<$Res>? get realm {
|
||||
if (_self.realm == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnRealmCopyWith<$Res>(_self.realm!, (value) {
|
||||
return _then(_self.copyWith(realm: value));
|
||||
});
|
||||
}/// Create a copy of SnPost
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnPublisherCopyWith<$Res> get publisher {
|
||||
|
||||
return $SnPublisherCopyWith<$Res>(_self.publisher, (value) {
|
||||
|
@@ -21,6 +21,7 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
: DateTime.parse(json['published_at'] as String),
|
||||
visibility: (json['visibility'] as num?)?.toInt() ?? 0,
|
||||
content: json['content'] as String?,
|
||||
slug: json['slug'] as String?,
|
||||
type: (json['type'] as num?)?.toInt() ?? 0,
|
||||
meta: json['meta'] as Map<String, dynamic>?,
|
||||
viewsUnique: (json['views_unique'] as num?)?.toInt() ?? 0,
|
||||
@@ -28,6 +29,7 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
upvotes: (json['upvotes'] as num?)?.toInt() ?? 0,
|
||||
downvotes: (json['downvotes'] as num?)?.toInt() ?? 0,
|
||||
repliesCount: (json['replies_count'] as num?)?.toInt() ?? 0,
|
||||
pinMode: (json['pin_mode'] as num?)?.toInt(),
|
||||
threadedPostId: json['threaded_post_id'] as String?,
|
||||
threadedPost:
|
||||
json['threaded_post'] == null
|
||||
@@ -43,6 +45,11 @@ _SnPost _$SnPostFromJson(Map<String, dynamic> json) => _SnPost(
|
||||
json['forwarded_post'] == null
|
||||
? null
|
||||
: SnPost.fromJson(json['forwarded_post'] as Map<String, dynamic>),
|
||||
realmId: json['realm_id'] as String?,
|
||||
realm:
|
||||
json['realm'] == null
|
||||
? null
|
||||
: SnRealm.fromJson(json['realm'] as Map<String, dynamic>),
|
||||
attachments:
|
||||
(json['attachments'] as List<dynamic>?)
|
||||
?.map((e) => SnCloudFile.fromJson(e as Map<String, dynamic>))
|
||||
@@ -95,6 +102,7 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
||||
'published_at': instance.publishedAt?.toIso8601String(),
|
||||
'visibility': instance.visibility,
|
||||
'content': instance.content,
|
||||
'slug': instance.slug,
|
||||
'type': instance.type,
|
||||
'meta': instance.meta,
|
||||
'views_unique': instance.viewsUnique,
|
||||
@@ -102,12 +110,15 @@ Map<String, dynamic> _$SnPostToJson(_SnPost instance) => <String, dynamic>{
|
||||
'upvotes': instance.upvotes,
|
||||
'downvotes': instance.downvotes,
|
||||
'replies_count': instance.repliesCount,
|
||||
'pin_mode': instance.pinMode,
|
||||
'threaded_post_id': instance.threadedPostId,
|
||||
'threaded_post': instance.threadedPost?.toJson(),
|
||||
'replied_post_id': instance.repliedPostId,
|
||||
'replied_post': instance.repliedPost?.toJson(),
|
||||
'forwarded_post_id': instance.forwardedPostId,
|
||||
'forwarded_post': instance.forwardedPost?.toJson(),
|
||||
'realm_id': instance.realmId,
|
||||
'realm': instance.realm?.toJson(),
|
||||
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
||||
'publisher': instance.publisher.toJson(),
|
||||
'reactions_count': instance.reactionsCount,
|
||||
|
@@ -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,
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
|
||||
part 'publisher.freezed.dart';
|
||||
part 'publisher.g.dart';
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
|
||||
part 'realm.freezed.dart';
|
||||
part 'realm.g.dart';
|
||||
@@ -40,6 +40,7 @@ sealed class SnRealmMember with _$SnRealmMember {
|
||||
required DateTime createdAt,
|
||||
required DateTime updatedAt,
|
||||
required DateTime? deletedAt,
|
||||
required SnAccountStatus? status,
|
||||
}) = _SnRealmMember;
|
||||
|
||||
factory SnRealmMember.fromJson(Map<String, dynamic> json) =>
|
||||
|
@@ -359,7 +359,7 @@ $SnCloudFileCopyWith<$Res>? get background {
|
||||
/// @nodoc
|
||||
mixin _$SnRealmMember {
|
||||
|
||||
String get realmId; SnRealm? get realm; String get accountId; SnAccount? get account; int get role; DateTime? get joinedAt; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||
String get realmId; SnRealm? get realm; String get accountId; SnAccount? get account; int get role; DateTime? get joinedAt; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; SnAccountStatus? get status;
|
||||
/// Create a copy of SnRealmMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@@ -372,16 +372,16 @@ $SnRealmMemberCopyWith<SnRealmMember> get copyWith => _$SnRealmMemberCopyWithImp
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(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 SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.status, status) || other.status == status));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt,status);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, status: $status)';
|
||||
}
|
||||
|
||||
|
||||
@@ -392,11 +392,11 @@ abstract mixin class $SnRealmMemberCopyWith<$Res> {
|
||||
factory $SnRealmMemberCopyWith(SnRealmMember value, $Res Function(SnRealmMember) _then) = _$SnRealmMemberCopyWithImpl;
|
||||
@useResult
|
||||
$Res call({
|
||||
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status
|
||||
});
|
||||
|
||||
|
||||
$SnRealmCopyWith<$Res>? get realm;$SnAccountCopyWith<$Res>? get account;
|
||||
$SnRealmCopyWith<$Res>? get realm;$SnAccountCopyWith<$Res>? get account;$SnAccountStatusCopyWith<$Res>? get status;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -409,7 +409,7 @@ class _$SnRealmMemberCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnRealmMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@pragma('vm:prefer-inline') @override $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? status = freezed,}) {
|
||||
return _then(_self.copyWith(
|
||||
realmId: null == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||
as String,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||
@@ -420,7 +420,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
||||
as DateTime?,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?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountStatus?,
|
||||
));
|
||||
}
|
||||
/// Create a copy of SnRealmMember
|
||||
@@ -447,6 +448,18 @@ $SnAccountCopyWith<$Res>? get account {
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}/// Create a copy of SnRealmMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountStatusCopyWith<$Res>? get status {
|
||||
if (_self.status == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||
return _then(_self.copyWith(status: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -526,10 +539,10 @@ return $default(_that);case _:
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status)? $default,{required TResult orElse(),}) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnRealmMember() when $default != null:
|
||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.status);case _:
|
||||
return orElse();
|
||||
|
||||
}
|
||||
@@ -547,10 +560,10 @@ return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.ro
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status) $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnRealmMember():
|
||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.status);}
|
||||
}
|
||||
/// A variant of `when` that fallback to returning `null`
|
||||
///
|
||||
@@ -564,10 +577,10 @@ return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.ro
|
||||
/// }
|
||||
/// ```
|
||||
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status)? $default,) {final _that = this;
|
||||
switch (_that) {
|
||||
case _SnRealmMember() when $default != null:
|
||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||
return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.role,_that.joinedAt,_that.createdAt,_that.updatedAt,_that.deletedAt,_that.status);case _:
|
||||
return null;
|
||||
|
||||
}
|
||||
@@ -579,7 +592,7 @@ return $default(_that.realmId,_that.realm,_that.accountId,_that.account,_that.ro
|
||||
@JsonSerializable()
|
||||
|
||||
class _SnRealmMember implements SnRealmMember {
|
||||
const _SnRealmMember({required this.realmId, required this.realm, required this.accountId, required this.account, required this.role, required this.joinedAt, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||
const _SnRealmMember({required this.realmId, required this.realm, required this.accountId, required this.account, required this.role, required this.joinedAt, required this.createdAt, required this.updatedAt, required this.deletedAt, required this.status});
|
||||
factory _SnRealmMember.fromJson(Map<String, dynamic> json) => _$SnRealmMemberFromJson(json);
|
||||
|
||||
@override final String realmId;
|
||||
@@ -591,6 +604,7 @@ class _SnRealmMember implements SnRealmMember {
|
||||
@override final DateTime createdAt;
|
||||
@override final DateTime updatedAt;
|
||||
@override final DateTime? deletedAt;
|
||||
@override final SnAccountStatus? status;
|
||||
|
||||
/// Create a copy of SnRealmMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@@ -605,16 +619,16 @@ Map<String, dynamic> toJson() {
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(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 _SnRealmMember&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.role, role) || other.role == role)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.status, status) || other.status == status));
|
||||
}
|
||||
|
||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||
@override
|
||||
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt);
|
||||
int get hashCode => Object.hash(runtimeType,realmId,realm,accountId,account,role,joinedAt,createdAt,updatedAt,deletedAt,status);
|
||||
|
||||
@override
|
||||
String toString() {
|
||||
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||
return 'SnRealmMember(realmId: $realmId, realm: $realm, accountId: $accountId, account: $account, role: $role, joinedAt: $joinedAt, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, status: $status)';
|
||||
}
|
||||
|
||||
|
||||
@@ -625,11 +639,11 @@ abstract mixin class _$SnRealmMemberCopyWith<$Res> implements $SnRealmMemberCopy
|
||||
factory _$SnRealmMemberCopyWith(_SnRealmMember value, $Res Function(_SnRealmMember) _then) = __$SnRealmMemberCopyWithImpl;
|
||||
@override @useResult
|
||||
$Res call({
|
||||
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||
String realmId, SnRealm? realm, String accountId, SnAccount? account, int role, DateTime? joinedAt, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, SnAccountStatus? status
|
||||
});
|
||||
|
||||
|
||||
@override $SnRealmCopyWith<$Res>? get realm;@override $SnAccountCopyWith<$Res>? get account;
|
||||
@override $SnRealmCopyWith<$Res>? get realm;@override $SnAccountCopyWith<$Res>? get account;@override $SnAccountStatusCopyWith<$Res>? get status;
|
||||
|
||||
}
|
||||
/// @nodoc
|
||||
@@ -642,7 +656,7 @@ class __$SnRealmMemberCopyWithImpl<$Res>
|
||||
|
||||
/// Create a copy of SnRealmMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||
@override @pragma('vm:prefer-inline') $Res call({Object? realmId = null,Object? realm = freezed,Object? accountId = null,Object? account = freezed,Object? role = null,Object? joinedAt = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? status = freezed,}) {
|
||||
return _then(_SnRealmMember(
|
||||
realmId: null == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||
as String,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||
@@ -653,7 +667,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
||||
as DateTime?,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?,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||
as SnAccountStatus?,
|
||||
));
|
||||
}
|
||||
|
||||
@@ -681,6 +696,18 @@ $SnAccountCopyWith<$Res>? get account {
|
||||
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||
return _then(_self.copyWith(account: value));
|
||||
});
|
||||
}/// Create a copy of SnRealmMember
|
||||
/// with the given fields replaced by the non-null parameter values.
|
||||
@override
|
||||
@pragma('vm:prefer-inline')
|
||||
$SnAccountStatusCopyWith<$Res>? get status {
|
||||
if (_self.status == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||
return _then(_self.copyWith(status: value));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
@@ -75,6 +75,12 @@ _SnRealmMember _$SnRealmMemberFromJson(Map<String, dynamic> json) =>
|
||||
json['deleted_at'] == null
|
||||
? null
|
||||
: DateTime.parse(json['deleted_at'] as String),
|
||||
status:
|
||||
json['status'] == null
|
||||
? null
|
||||
: SnAccountStatus.fromJson(
|
||||
json['status'] as Map<String, dynamic>,
|
||||
),
|
||||
);
|
||||
|
||||
Map<String, dynamic> _$SnRealmMemberToJson(_SnRealmMember instance) =>
|
||||
@@ -88,4 +94,5 @@ Map<String, dynamic> _$SnRealmMemberToJson(_SnRealmMember instance) =>
|
||||
'created_at': instance.createdAt.toIso8601String(),
|
||||
'updated_at': instance.updatedAt.toIso8601String(),
|
||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||
'status': instance.status?.toJson(),
|
||||
};
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
|
||||
part 'relationship.freezed.dart';
|
||||
part 'relationship.g.dart';
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
|
||||
part 'wallet.freezed.dart';
|
||||
part 'wallet.g.dart';
|
||||
|
@@ -23,6 +23,8 @@ const kAppSoundEffects = 'app_sound_effects';
|
||||
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
||||
const kAppWindowSize = 'app_window_size';
|
||||
const kAppEnterToSend = 'app_enter_to_send';
|
||||
const kFeaturedPostsCollapsedId =
|
||||
'featured_posts_collapsed_id'; // Key for storing the ID of the collapsed featured post
|
||||
|
||||
const Map<String, FilterQuality> kImageQualityLevel = {
|
||||
'settingsImageQualityLowest': FilterQuality.none,
|
||||
|
@@ -1,8 +1,15 @@
|
||||
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/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/pods/config.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
|
||||
@@ -12,12 +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);
|
||||
|
||||
if (kIsWeb || !Platform.isLinux) {
|
||||
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}\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',
|
||||
@@ -33,6 +87,9 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
||||
final prefs = _ref.read(sharedPreferencesProvider);
|
||||
await prefs.remove(kTokenPairStoreKey);
|
||||
_ref.invalidate(tokenProvider);
|
||||
if (kIsWeb || !Platform.isLinux) {
|
||||
FirebaseAnalytics.instance.setUserId(id: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
223
lib/route.dart
223
lib/route.dart
@@ -1,12 +1,25 @@
|
||||
import 'dart:io' show Platform;
|
||||
import 'package:animations/animations.dart';
|
||||
import 'package:firebase_analytics/firebase_analytics.dart';
|
||||
import 'package:flutter/material.dart';
|
||||
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';
|
||||
@@ -18,19 +31,22 @@ import 'package:island/screens/notification.dart';
|
||||
import 'package:island/screens/wallet.dart';
|
||||
import 'package:island/screens/account/relationship.dart';
|
||||
import 'package:island/screens/account/profile.dart';
|
||||
import 'package:island/screens/account/me/update.dart';
|
||||
import 'package:island/screens/account/me/profile_update.dart';
|
||||
import 'package:island/screens/account/leveling.dart';
|
||||
import 'package:island/screens/account/me/settings.dart';
|
||||
import 'package:island/screens/account/me/account_settings.dart';
|
||||
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';
|
||||
@@ -48,17 +64,43 @@ 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>();
|
||||
final _shellNavigatorKey = GlobalKey<NavigatorState>();
|
||||
final _tabsShellKey = GlobalKey<NavigatorState>();
|
||||
|
||||
Widget _tabPagesTransitionBuilder(
|
||||
BuildContext context,
|
||||
Animation<double> animation,
|
||||
Animation<double> secondaryAnimation,
|
||||
Widget child,
|
||||
) {
|
||||
return FadeThroughTransition(
|
||||
animation: animation,
|
||||
secondaryAnimation: secondaryAnimation,
|
||||
fillColor: Theme.of(context).colorScheme.surface,
|
||||
child: child,
|
||||
);
|
||||
}
|
||||
|
||||
bool get _supportsAnalytics =>
|
||||
kIsWeb ||
|
||||
Platform.isAndroid ||
|
||||
Platform.isIOS ||
|
||||
Platform.isMacOS ||
|
||||
Platform.isWindows;
|
||||
|
||||
// Provider for the router
|
||||
final routerProvider = Provider<GoRouter>((ref) {
|
||||
return GoRouter(
|
||||
navigatorKey: rootNavigatorKey,
|
||||
initialLocation: '/',
|
||||
observers: [
|
||||
if (_supportsAnalytics)
|
||||
FirebaseAnalyticsObserver(analytics: FirebaseAnalytics.instance),
|
||||
],
|
||||
routes: [
|
||||
ShellRoute(
|
||||
navigatorKey: _shellNavigatorKey,
|
||||
@@ -257,30 +299,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']!,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -334,7 +445,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
GoRoute(
|
||||
name: 'explore',
|
||||
path: '/',
|
||||
builder: (context, state) => const ExploreScreen(),
|
||||
pageBuilder:
|
||||
(context, state) => CustomTransitionPage(
|
||||
key: const ValueKey('explore'),
|
||||
child: const ExploreScreen(),
|
||||
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||
),
|
||||
),
|
||||
GoRoute(
|
||||
name: 'postSearch',
|
||||
@@ -342,12 +458,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',
|
||||
@@ -357,6 +475,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',
|
||||
@@ -368,6 +491,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',
|
||||
@@ -384,8 +515,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
|
||||
// Chat tab
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) => ChatShellScreen(child: child),
|
||||
pageBuilder:
|
||||
(context, state, child) => CustomTransitionPage(
|
||||
key: const ValueKey('chat'),
|
||||
child: ChatShellScreen(child: child),
|
||||
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'chatList',
|
||||
@@ -421,6 +556,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);
|
||||
},
|
||||
),
|
||||
],
|
||||
),
|
||||
|
||||
@@ -428,7 +571,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
GoRoute(
|
||||
name: 'realmList',
|
||||
path: '/realms',
|
||||
builder: (context, state) => const RealmListScreen(),
|
||||
pageBuilder:
|
||||
(context, state) => CustomTransitionPage(
|
||||
key: const ValueKey('realms'),
|
||||
child: const RealmListScreen(),
|
||||
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'realmNew',
|
||||
@@ -456,8 +604,12 @@ final routerProvider = Provider<GoRouter>((ref) {
|
||||
|
||||
// Account tab
|
||||
ShellRoute(
|
||||
builder:
|
||||
(context, state, child) => AccountShellScreen(child: child),
|
||||
pageBuilder:
|
||||
(context, state, child) => CustomTransitionPage(
|
||||
key: const ValueKey('account'),
|
||||
child: AccountShellScreen(child: child),
|
||||
transitionsBuilder: _tabPagesTransitionBuilder,
|
||||
),
|
||||
routes: [
|
||||
GoRoute(
|
||||
name: 'account',
|
||||
@@ -481,6 +633,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',
|
||||
@@ -491,6 +659,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',
|
||||
|
@@ -178,7 +178,8 @@ class _AboutScreenState extends ConsumerState<AboutScreen> {
|
||||
context,
|
||||
icon: Symbols.label,
|
||||
label: 'aboutDeviceName'.tr(),
|
||||
value: _deviceInfo?.data['name'],
|
||||
value:
|
||||
_deviceInfo?.data['name'] ?? 'unknown'.tr(),
|
||||
),
|
||||
_buildInfoItem(
|
||||
context,
|
||||
|
@@ -3,12 +3,14 @@ import 'package:flutter/material.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/screens/notification.dart';
|
||||
import 'package:island/services/responsive.dart';
|
||||
import 'package:island/widgets/account/account_name.dart';
|
||||
import 'package:island/widgets/account/status.dart';
|
||||
import 'package:island/widgets/account/leveling_progress.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/debug_sheet.dart';
|
||||
@@ -234,6 +236,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(),
|
||||
@@ -303,7 +325,12 @@ class AccountScreen extends HookConsumerWidget {
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||
title: Text('logout').tr(),
|
||||
onTap: () {
|
||||
onTap: () async {
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
showLoadingModal(context);
|
||||
await apiClient.delete('/id/accounts/me/sessions/current');
|
||||
if (!context.mounted) return;
|
||||
hideLoadingModal(context);
|
||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||
userNotifier.logOut();
|
||||
},
|
||||
@@ -382,6 +409,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),
|
||||
],
|
||||
),
|
||||
),
|
||||
),
|
||||
|
@@ -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
|
||||
|
@@ -6,7 +6,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter/services.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/auth.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
import 'package:island/screens/account/me/settings_auth_factors.dart';
|
||||
@@ -15,7 +15,7 @@ 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_session_sheet.dart';
|
||||
import 'package:island/widgets/account/account_devices.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
@@ -23,7 +23,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
||||
part 'settings.g.dart';
|
||||
part 'account_settings.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<SnAuthFactor>> authFactors(Ref ref) async {
|
@@ -1,6 +1,6 @@
|
||||
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||
|
||||
part of 'settings.dart';
|
||||
part of 'account_settings.dart';
|
||||
|
||||
// **************************************************************************
|
||||
// RiverpodGenerator
|
@@ -1,3 +1,4 @@
|
||||
import 'package:collection/collection.dart';
|
||||
import 'package:croppy/croppy.dart' hide cropImage;
|
||||
import 'package:dropdown_button2/dropdown_button2.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
@@ -7,7 +8,7 @@ import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:image_picker/image_picker.dart';
|
||||
import 'package:island/models/file.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/pods/config.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/pods/userinfo.dart';
|
||||
@@ -168,11 +169,18 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
'location': locationController.text,
|
||||
'time_zone': timeZoneController.text,
|
||||
'birthday': birthday.value?.toUtc().toIso8601String(),
|
||||
'links': links.value,
|
||||
'links':
|
||||
links.value
|
||||
.where((e) => e.name.isNotEmpty && e.url.isNotEmpty)
|
||||
.toList(),
|
||||
},
|
||||
);
|
||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||
userNotifier.fetchUser();
|
||||
links.value =
|
||||
links.value
|
||||
.where((e) => e.name.isNotEmpty && e.url.isNotEmpty)
|
||||
.toList();
|
||||
} catch (err) {
|
||||
showErrorAlert(err);
|
||||
} finally {
|
||||
@@ -568,6 +576,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
children: [
|
||||
for (var i = 0; i < links.value.length; i++)
|
||||
Row(
|
||||
key: ValueKey(links.value[i].hashCode),
|
||||
crossAxisAlignment: CrossAxisAlignment.end,
|
||||
children: [
|
||||
Expanded(
|
||||
@@ -610,8 +619,10 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
||||
IconButton(
|
||||
icon: const Icon(Symbols.delete),
|
||||
onPressed: () {
|
||||
links.value = List.from(links.value)
|
||||
..removeAt(i);
|
||||
links.value =
|
||||
links.value
|
||||
.whereIndexed((idx, _) => idx != i)
|
||||
.toList();
|
||||
},
|
||||
),
|
||||
],
|
@@ -6,7 +6,7 @@ import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/auth.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/screens/account/me/settings.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/services/time.dart';
|
||||
@@ -166,7 +166,7 @@ class AccountConnectionNewSheet extends HookConsumerWidget {
|
||||
webAuthenticationOptions: WebAuthenticationOptions(
|
||||
clientId: 'dev.solsynth.solarpass',
|
||||
redirectUri: Uri.parse(
|
||||
'https://nt.solian.app/auth/callback/apple',
|
||||
'https://id.solian.app/auth/callback/apple',
|
||||
),
|
||||
),
|
||||
);
|
||||
|
@@ -3,7 +3,7 @@ import 'package:flutter/material.dart';
|
||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
|
@@ -2,12 +2,14 @@ import 'package:dio/dio.dart';
|
||||
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:go_router/go_router.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/chat.dart';
|
||||
import 'package:island/models/developer.dart';
|
||||
import 'package:island/models/relationship.dart';
|
||||
import 'package:island/models/user.dart';
|
||||
import 'package:island/models/account.dart';
|
||||
import 'package:island/pods/config.dart';
|
||||
import 'package:island/pods/event_calendar.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
@@ -111,6 +113,24 @@ Future<SnRelationship?> accountRelationship(Ref ref, String uname) async {
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Future<SnDeveloper?> accountBotDeveloper(Ref ref, String uname) async {
|
||||
final account = await ref.watch(accountProvider(uname).future);
|
||||
if (account.automatedId == null) return null;
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
try {
|
||||
final resp = await apiClient.get(
|
||||
"/develop/bots/${account.automatedId}/developer",
|
||||
);
|
||||
return SnDeveloper.fromJson(resp.data);
|
||||
} catch (err) {
|
||||
if (err is DioException && err.response?.statusCode == 404) {
|
||||
return null;
|
||||
}
|
||||
rethrow;
|
||||
}
|
||||
}
|
||||
|
||||
class AccountProfileScreen extends HookConsumerWidget {
|
||||
final String name;
|
||||
const AccountProfileScreen({super.key, required this.name});
|
||||
@@ -127,6 +147,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
);
|
||||
final accountChat = ref.watch(accountDirectChatProvider(name));
|
||||
final accountRelationship = ref.watch(accountRelationshipProvider(name));
|
||||
final accountDeveloper = ref.watch(accountBotDeveloperProvider(name));
|
||||
|
||||
final appbarColor = ref.watch(accountAppbarForcegroundColorProvider(name));
|
||||
|
||||
@@ -258,10 +279,32 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
if (data.profile.lastName.isNotEmpty) Text(data.profile.lastName),
|
||||
],
|
||||
),
|
||||
Tooltip(
|
||||
message: 'creditsStatus'.tr(),
|
||||
child: Row(
|
||||
spacing: 6,
|
||||
children: [
|
||||
Icon(Symbols.star, size: 17, fill: 1).padding(right: 2),
|
||||
Text('${data.profile.socialCredits.toStringAsFixed(2)} pts'),
|
||||
Text('·').bold(),
|
||||
switch (data.profile.socialCreditsLevel) {
|
||||
-1 => Text('socialCreditsLevelPoor').tr(),
|
||||
0 => Text('socialCreditsLevelNormal').tr(),
|
||||
1 => Text('socialCreditsLevelGood').tr(),
|
||||
2 => Text('socialCreditsLevelExcellent').tr(),
|
||||
_ => Text('unknown').tr(),
|
||||
},
|
||||
],
|
||||
),
|
||||
),
|
||||
];
|
||||
}
|
||||
|
||||
final user = ref.watch(userInfoProvider);
|
||||
final isCurrentUser = useMemoized(
|
||||
() => user.value?.id == account.value?.id,
|
||||
[user, account],
|
||||
);
|
||||
|
||||
Widget accountBasicInfo(SnAccount data) => Padding(
|
||||
padding: const EdgeInsets.fromLTRB(24, 24, 24, 8),
|
||||
@@ -287,6 +330,19 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
),
|
||||
],
|
||||
),
|
||||
if (accountDeveloper.value != null)
|
||||
Row(
|
||||
spacing: 7,
|
||||
children: [
|
||||
const Icon(Symbols.smart_toy, size: 18),
|
||||
Text(
|
||||
'botAutomatedBy'.tr(
|
||||
args: [accountDeveloper.value!.publisher!.nick],
|
||||
),
|
||||
).fontSize(13),
|
||||
],
|
||||
).opacity(0.75),
|
||||
const Gap(4),
|
||||
AccountStatusWidget(uname: name, padding: EdgeInsets.zero),
|
||||
],
|
||||
),
|
||||
@@ -589,7 +645,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
child: CustomScrollView(
|
||||
slivers: [
|
||||
SliverGap(24),
|
||||
if (user.value != null)
|
||||
if (user.value != null && !isCurrentUser)
|
||||
SliverToBoxAdapter(child: accountAction(data)),
|
||||
SliverToBoxAdapter(
|
||||
child: Card(
|
||||
@@ -686,7 +742,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
||||
data,
|
||||
).padding(horizontal: 4),
|
||||
),
|
||||
if (user.value != null)
|
||||
if (user.value != null && !isCurrentUser)
|
||||
SliverToBoxAdapter(
|
||||
child: accountAction(data).padding(horizontal: 4),
|
||||
),
|
||||
|
@@ -639,5 +639,128 @@ 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;
|
||||
}
|
||||
|
||||
// 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,7 @@ import 'package:flutter_hooks/flutter_hooks.dart';
|
||||
import 'package:gap/gap.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/screens/account/me/update.dart';
|
||||
import 'package:island/screens/account/me/profile_update.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
|
@@ -42,6 +42,22 @@ 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});
|
||||
|
||||
@@ -198,28 +214,6 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
||||
wsNotifier.connect();
|
||||
if (context.mounted) Navigator.pop(context, true);
|
||||
});
|
||||
|
||||
// Update the sessions' device name is available
|
||||
if (!kIsWeb) {
|
||||
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;
|
||||
}
|
||||
if (name != null) {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
await client.patch(
|
||||
'/id/accounts/me/sessions/current/label',
|
||||
data: jsonEncode(name),
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
useEffect(() {
|
||||
@@ -578,6 +572,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
data: {
|
||||
'account': uname,
|
||||
'device_id': await getUdid(),
|
||||
'device_name': await getDeviceName(),
|
||||
'platform':
|
||||
kIsWeb
|
||||
? 1
|
||||
@@ -628,6 +623,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
||||
'identity_token': credential.identityToken!,
|
||||
'authorization_code': credential.authorizationCode,
|
||||
'device_id': await getUdid(),
|
||||
'device_name': await getDeviceName(),
|
||||
},
|
||||
);
|
||||
|
||||
|
@@ -23,7 +23,7 @@ import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:island/widgets/content/sheet.dart';
|
||||
import 'package:island/widgets/realms/selection_dropdown.dart';
|
||||
import 'package:island/widgets/realm/realm_selection_dropdown.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
import 'package:island/screens/tabs.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
@@ -79,31 +79,38 @@ class ChatRoomListTile extends HookConsumerWidget {
|
||||
color: Theme.of(context).colorScheme.primary,
|
||||
),
|
||||
),
|
||||
Row(
|
||||
children: [
|
||||
Text(
|
||||
'${data.lastMessage.sender.account.name}: ',
|
||||
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,
|
||||
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,
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
],
|
||||
);
|
||||
},
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -6,7 +6,7 @@ part of 'room.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$messagesNotifierHash() => r'afc4d43f4948ec571118cef0321838a6cefc89c0';
|
||||
String _$messagesNotifierHash() => r'fc3b66dfb8dd3fc55d142dae5c5e7bdc67eca5d4';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
|
@@ -9,7 +9,9 @@ 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';
|
||||
import 'package:island/widgets/app_scaffold.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
@@ -18,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});
|
||||
@@ -30,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',
|
||||
@@ -130,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: () {
|
||||
@@ -142,8 +152,8 @@ 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)));
|
||||
@@ -154,8 +164,8 @@ 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)));
|
||||
@@ -166,8 +176,8 @@ 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)));
|
||||
@@ -178,8 +188,8 @@ 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)));
|
||||
@@ -193,8 +203,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),
|
||||
@@ -237,7 +247,7 @@ 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: [
|
||||
@@ -357,6 +367,22 @@ 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(),
|
||||
@@ -544,7 +570,7 @@ class ChatMemberListNotifier extends _$ChatMemberListNotifier
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
final response = await apiClient.get(
|
||||
'/sphere/chat/$roomId/members',
|
||||
queryParameters: {'offset': offset, 'take': take},
|
||||
queryParameters: {'offset': offset, 'take': take, 'withStatus': true},
|
||||
);
|
||||
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
@@ -665,13 +691,18 @@ 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!),
|
||||
if (member.joinedAt == null)
|
||||
const Icon(Symbols.pending_actions, size: 20),
|
||||
],
|
||||
@@ -685,7 +716,7 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
||||
? 'permissionModerator'
|
||||
: 'permissionMember',
|
||||
).tr(),
|
||||
Text('·').bold().padding(horizontal: 6),
|
||||
Text('dotSeparator').bold().padding(horizontal: 6),
|
||||
Expanded(child: Text("@${member.account.name}")),
|
||||
],
|
||||
),
|
||||
@@ -845,7 +876,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'a15c03461f25c2d4d39c0926509bf626ae2550a6';
|
||||
|
||||
/// 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()]))),
|
||||
),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
@@ -212,30 +212,6 @@ class CreatorHubScreen extends HookConsumerWidget {
|
||||
leading: !isWide ? const PageBackButton() : null,
|
||||
title: Text('creatorHub').tr(),
|
||||
actions: [
|
||||
IconButton(
|
||||
icon: Badge(
|
||||
label: Text(
|
||||
publisherInvites.when(
|
||||
data: (invites) => invites.length.toString(),
|
||||
error: (_, _) => '0',
|
||||
loading: () => '0',
|
||||
),
|
||||
),
|
||||
isLabelVisible: publisherInvites.when(
|
||||
data: (invites) => invites.isNotEmpty,
|
||||
error: (_, _) => false,
|
||||
loading: () => false,
|
||||
),
|
||||
child: const Icon(Symbols.email),
|
||||
),
|
||||
onPressed: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (_) => const _PublisherInviteSheet(),
|
||||
);
|
||||
},
|
||||
),
|
||||
DropdownButtonHideUnderline(
|
||||
child: DropdownButton2<SnPublisher>(
|
||||
alignment: Alignment.centerRight,
|
||||
@@ -323,6 +299,23 @@ class CreatorHubScreen extends HookConsumerWidget {
|
||||
),
|
||||
) ??
|
||||
[]),
|
||||
ListTile(
|
||||
leading: const CircleAvatar(
|
||||
child: Icon(Symbols.mail),
|
||||
),
|
||||
title: Text('publisherCollabInvitation').tr(),
|
||||
subtitle: Text(
|
||||
'publisherCollabInvitationCount',
|
||||
).plural(publisherInvites.value?.length ?? 0),
|
||||
trailing: const Icon(Symbols.chevron_right),
|
||||
onTap: () {
|
||||
showModalBottomSheet(
|
||||
context: context,
|
||||
isScrollControlled: true,
|
||||
builder: (_) => const _PublisherInviteSheet(),
|
||||
);
|
||||
},
|
||||
),
|
||||
ListTile(
|
||||
leading: const CircleAvatar(
|
||||
child: Icon(Symbols.add),
|
||||
|
@@ -14,17 +14,19 @@ part 'poll_list.g.dart';
|
||||
|
||||
@riverpod
|
||||
class PollListNotifier extends _$PollListNotifier
|
||||
with CursorPagingNotifierMixin<SnPoll> {
|
||||
with CursorPagingNotifierMixin<SnPollWithStats> {
|
||||
static const int _pageSize = 20;
|
||||
|
||||
@override
|
||||
Future<CursorPagingData<SnPoll>> build(String? pubName) {
|
||||
Future<CursorPagingData<SnPollWithStats>> build(String? pubName) {
|
||||
// immediately load first page
|
||||
return fetch(cursor: null);
|
||||
}
|
||||
|
||||
@override
|
||||
Future<CursorPagingData<SnPoll>> fetch({required String? cursor}) async {
|
||||
Future<CursorPagingData<SnPollWithStats>> fetch({
|
||||
required String? cursor,
|
||||
}) async {
|
||||
final client = ref.read(apiClientProvider);
|
||||
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||
|
||||
@@ -42,7 +44,7 @@ class PollListNotifier extends _$PollListNotifier
|
||||
);
|
||||
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||
final List<dynamic> data = response.data;
|
||||
final items = data.map((json) => SnPoll.fromJson(json)).toList();
|
||||
final items = data.map((json) => SnPollWithStats.fromJson(json)).toList();
|
||||
|
||||
final hasMore = offset + items.length < total;
|
||||
final nextCursor = hasMore ? (offset + items.length).toString() : null;
|
||||
@@ -55,6 +57,13 @@ class PollListNotifier extends _$PollListNotifier
|
||||
}
|
||||
}
|
||||
|
||||
@riverpod
|
||||
Future<SnPollWithStats> pollWithStats(Ref ref, String id) async {
|
||||
final apiClient = ref.watch(apiClientProvider);
|
||||
final resp = await apiClient.get('/sphere/polls/$id');
|
||||
return SnPollWithStats.fromJson(resp.data);
|
||||
}
|
||||
|
||||
class CreatorPollListScreen extends HookConsumerWidget {
|
||||
const CreatorPollListScreen({super.key, required this.pubName});
|
||||
|
||||
@@ -64,7 +73,7 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
||||
final result = await GoRouter.of(
|
||||
context,
|
||||
).pushNamed('creatorPollNew', pathParameters: {'name': pubName});
|
||||
if (result is SnPoll && context.mounted) {
|
||||
if (result is SnPollWithStats && context.mounted) {
|
||||
Navigator.of(context).maybePop(result);
|
||||
}
|
||||
}
|
||||
@@ -92,8 +101,11 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
||||
if (index == widgetCount - 1) {
|
||||
return endItemView;
|
||||
}
|
||||
final poll = data.items[index];
|
||||
return _CreatorPollItem(poll: poll, pubName: pubName);
|
||||
final pollWithStats = data.items[index];
|
||||
return _CreatorPollItem(
|
||||
pollWithStats: pollWithStats,
|
||||
pubName: pubName,
|
||||
);
|
||||
},
|
||||
),
|
||||
),
|
||||
@@ -106,14 +118,14 @@ class CreatorPollListScreen extends HookConsumerWidget {
|
||||
|
||||
class _CreatorPollItem extends StatelessWidget {
|
||||
final String pubName;
|
||||
const _CreatorPollItem({required this.poll, required this.pubName});
|
||||
const _CreatorPollItem({required this.pollWithStats, required this.pubName});
|
||||
|
||||
final SnPoll poll;
|
||||
final SnPollWithStats pollWithStats;
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context) {
|
||||
final theme = Theme.of(context);
|
||||
final ended = poll.endedAt;
|
||||
final ended = pollWithStats.endedAt;
|
||||
final endedText =
|
||||
ended == null
|
||||
? 'No end'
|
||||
@@ -123,15 +135,16 @@ class _CreatorPollItem extends StatelessWidget {
|
||||
margin: const EdgeInsets.symmetric(horizontal: 12, vertical: 6),
|
||||
clipBehavior: Clip.antiAlias,
|
||||
child: ListTile(
|
||||
title: Text(poll.title ?? 'Untitled poll'),
|
||||
title: Text(pollWithStats.title ?? 'Untitled poll'),
|
||||
subtitle: Column(
|
||||
crossAxisAlignment: CrossAxisAlignment.start,
|
||||
children: [
|
||||
if (poll.description != null && poll.description!.isNotEmpty)
|
||||
if (pollWithStats.description != null &&
|
||||
pollWithStats.description!.isNotEmpty)
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
poll.description!,
|
||||
pollWithStats.description!,
|
||||
maxLines: 2,
|
||||
overflow: TextOverflow.ellipsis,
|
||||
),
|
||||
@@ -139,7 +152,7 @@ class _CreatorPollItem extends StatelessWidget {
|
||||
Padding(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
child: Text(
|
||||
'Questions: ${poll.questions.length} · Ends: $endedText',
|
||||
'Questions: ${pollWithStats.questions.length} · Ends: $endedText',
|
||||
style: theme.textTheme.bodySmall,
|
||||
),
|
||||
),
|
||||
@@ -159,7 +172,7 @@ class _CreatorPollItem extends StatelessWidget {
|
||||
onTap: () {
|
||||
GoRouter.of(context).pushNamed(
|
||||
'creatorPollEdit',
|
||||
pathParameters: {'name': pubName, 'id': poll.id},
|
||||
pathParameters: {'name': pubName, 'id': pollWithStats.id},
|
||||
);
|
||||
},
|
||||
),
|
||||
@@ -170,8 +183,7 @@ class _CreatorPollItem extends StatelessWidget {
|
||||
context: context,
|
||||
useRootNavigator: true,
|
||||
isScrollControlled: true,
|
||||
builder:
|
||||
(context) => PollFeedbackSheet(pollId: poll.id, poll: poll),
|
||||
builder: (context) => PollFeedbackSheet(pollId: pollWithStats.id),
|
||||
);
|
||||
},
|
||||
),
|
||||
|
@@ -6,7 +6,7 @@ part of 'poll_list.dart';
|
||||
// RiverpodGenerator
|
||||
// **************************************************************************
|
||||
|
||||
String _$pollListNotifierHash() => r'd3da24ff6bbb8f35b06d57fc41625dc0312508e4';
|
||||
String _$pollWithStatsHash() => r'6bb910046ce1e09368f9922dbec52fdc2cc86740';
|
||||
|
||||
/// Copied from Dart SDK
|
||||
class _SystemHash {
|
||||
@@ -29,11 +29,133 @@ class _SystemHash {
|
||||
}
|
||||
}
|
||||
|
||||
/// See also [pollWithStats].
|
||||
@ProviderFor(pollWithStats)
|
||||
const pollWithStatsProvider = PollWithStatsFamily();
|
||||
|
||||
/// See also [pollWithStats].
|
||||
class PollWithStatsFamily extends Family<AsyncValue<SnPollWithStats>> {
|
||||
/// See also [pollWithStats].
|
||||
const PollWithStatsFamily();
|
||||
|
||||
/// See also [pollWithStats].
|
||||
PollWithStatsProvider call(String id) {
|
||||
return PollWithStatsProvider(id);
|
||||
}
|
||||
|
||||
@override
|
||||
PollWithStatsProvider getProviderOverride(
|
||||
covariant PollWithStatsProvider 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'pollWithStatsProvider';
|
||||
}
|
||||
|
||||
/// See also [pollWithStats].
|
||||
class PollWithStatsProvider extends AutoDisposeFutureProvider<SnPollWithStats> {
|
||||
/// See also [pollWithStats].
|
||||
PollWithStatsProvider(String id)
|
||||
: this._internal(
|
||||
(ref) => pollWithStats(ref as PollWithStatsRef, id),
|
||||
from: pollWithStatsProvider,
|
||||
name: r'pollWithStatsProvider',
|
||||
debugGetCreateSourceHash:
|
||||
const bool.fromEnvironment('dart.vm.product')
|
||||
? null
|
||||
: _$pollWithStatsHash,
|
||||
dependencies: PollWithStatsFamily._dependencies,
|
||||
allTransitiveDependencies:
|
||||
PollWithStatsFamily._allTransitiveDependencies,
|
||||
id: id,
|
||||
);
|
||||
|
||||
PollWithStatsProvider._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<SnPollWithStats> Function(PollWithStatsRef provider) create,
|
||||
) {
|
||||
return ProviderOverride(
|
||||
origin: this,
|
||||
override: PollWithStatsProvider._internal(
|
||||
(ref) => create(ref as PollWithStatsRef),
|
||||
from: from,
|
||||
name: null,
|
||||
dependencies: null,
|
||||
allTransitiveDependencies: null,
|
||||
debugGetCreateSourceHash: null,
|
||||
id: id,
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
@override
|
||||
AutoDisposeFutureProviderElement<SnPollWithStats> createElement() {
|
||||
return _PollWithStatsProviderElement(this);
|
||||
}
|
||||
|
||||
@override
|
||||
bool operator ==(Object other) {
|
||||
return other is PollWithStatsProvider && 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 PollWithStatsRef on AutoDisposeFutureProviderRef<SnPollWithStats> {
|
||||
/// The parameter `id` of this provider.
|
||||
String get id;
|
||||
}
|
||||
|
||||
class _PollWithStatsProviderElement
|
||||
extends AutoDisposeFutureProviderElement<SnPollWithStats>
|
||||
with PollWithStatsRef {
|
||||
_PollWithStatsProviderElement(super.provider);
|
||||
|
||||
@override
|
||||
String get id => (origin as PollWithStatsProvider).id;
|
||||
}
|
||||
|
||||
String _$pollListNotifierHash() => r'd5b822e737788be8982f5cb3b501d460441930c1';
|
||||
|
||||
abstract class _$PollListNotifier
|
||||
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPoll>> {
|
||||
extends
|
||||
BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnPollWithStats>> {
|
||||
late final String? pubName;
|
||||
|
||||
FutureOr<CursorPagingData<SnPoll>> build(String? pubName);
|
||||
FutureOr<CursorPagingData<SnPollWithStats>> build(String? pubName);
|
||||
}
|
||||
|
||||
/// See also [PollListNotifier].
|
||||
@@ -42,7 +164,7 @@ const pollListNotifierProvider = PollListNotifierFamily();
|
||||
|
||||
/// See also [PollListNotifier].
|
||||
class PollListNotifierFamily
|
||||
extends Family<AsyncValue<CursorPagingData<SnPoll>>> {
|
||||
extends Family<AsyncValue<CursorPagingData<SnPollWithStats>>> {
|
||||
/// See also [PollListNotifier].
|
||||
const PollListNotifierFamily();
|
||||
|
||||
@@ -78,7 +200,7 @@ class PollListNotifierProvider
|
||||
extends
|
||||
AutoDisposeAsyncNotifierProviderImpl<
|
||||
PollListNotifier,
|
||||
CursorPagingData<SnPoll>
|
||||
CursorPagingData<SnPollWithStats>
|
||||
> {
|
||||
/// See also [PollListNotifier].
|
||||
PollListNotifierProvider(String? pubName)
|
||||
@@ -109,7 +231,7 @@ class PollListNotifierProvider
|
||||
final String? pubName;
|
||||
|
||||
@override
|
||||
FutureOr<CursorPagingData<SnPoll>> runNotifierBuild(
|
||||
FutureOr<CursorPagingData<SnPollWithStats>> runNotifierBuild(
|
||||
covariant PollListNotifier notifier,
|
||||
) {
|
||||
return notifier.build(pubName);
|
||||
@@ -134,7 +256,7 @@ class PollListNotifierProvider
|
||||
@override
|
||||
AutoDisposeAsyncNotifierProviderElement<
|
||||
PollListNotifier,
|
||||
CursorPagingData<SnPoll>
|
||||
CursorPagingData<SnPollWithStats>
|
||||
>
|
||||
createElement() {
|
||||
return _PollListNotifierProviderElement(this);
|
||||
@@ -157,7 +279,7 @@ class PollListNotifierProvider
|
||||
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||
// ignore: unused_element
|
||||
mixin PollListNotifierRef
|
||||
on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnPoll>> {
|
||||
on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnPollWithStats>> {
|
||||
/// The parameter `pubName` of this provider.
|
||||
String? get pubName;
|
||||
}
|
||||
@@ -166,7 +288,7 @@ class _PollListNotifierProviderElement
|
||||
extends
|
||||
AutoDisposeAsyncNotifierProviderElement<
|
||||
PollListNotifier,
|
||||
CursorPagingData<SnPoll>
|
||||
CursorPagingData<SnPollWithStats>
|
||||
>
|
||||
with PollListNotifierRef {
|
||||
_PollListNotifierProviderElement(super.provider);
|
||||
|
@@ -19,7 +19,7 @@ import 'package:island/services/responsive.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/realms/selection_dropdown.dart';
|
||||
import 'package:island/widgets/realm/realm_selection_dropdown.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
import 'package:styled_widget/styled_widget.dart';
|
||||
|
@@ -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>> {
|
||||
|
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
|
167
lib/screens/developers/bots.dart
Normal file
167
lib/screens/developers/bots.dart
Normal file
@@ -0,0 +1,167 @@
|
||||
import 'package:flutter/material.dart';
|
||||
import 'package:easy_localization/easy_localization.dart';
|
||||
import 'package:go_router/go_router.dart';
|
||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||
import 'package:island/models/bot.dart';
|
||||
import 'package:island/pods/network.dart';
|
||||
import 'package:island/widgets/alert.dart';
|
||||
import 'package:island/widgets/content/cloud_files.dart';
|
||||
import 'package:island/widgets/response.dart';
|
||||
import 'package:material_symbols_icons/symbols.dart';
|
||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||
|
||||
part 'bots.g.dart';
|
||||
|
||||
@riverpod
|
||||
Future<List<Bot>> bots(Ref ref, String publisherName, String projectId) async {
|
||||
final client = ref.watch(apiClientProvider);
|
||||
final resp = await client.get(
|
||||
'/develop/developers/$publisherName/projects/$projectId/bots',
|
||||
);
|
||||
return (resp.data as List).map((e) => Bot.fromJson(e)).cast<Bot>().toList();
|
||||
}
|
||||
|
||||
class BotsScreen extends HookConsumerWidget {
|
||||
final String publisherName;
|
||||
final String projectId;
|
||||
const BotsScreen({
|
||||
super.key,
|
||||
required this.publisherName,
|
||||
required this.projectId,
|
||||
});
|
||||
|
||||
@override
|
||||
Widget build(BuildContext context, WidgetRef ref) {
|
||||
final botsList = ref.watch(botsProvider(publisherName, projectId));
|
||||
|
||||
return botsList.when(
|
||||
data: (data) {
|
||||
if (data.isEmpty) {
|
||||
return Center(
|
||||
child: Column(
|
||||
mainAxisAlignment: MainAxisAlignment.center,
|
||||
children: [
|
||||
Text('noBots').tr(),
|
||||
const SizedBox(height: 16),
|
||||
ElevatedButton.icon(
|
||||
onPressed: () {
|
||||
context.pushNamed(
|
||||
'developerBotNew',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
},
|
||||
);
|
||||
},
|
||||
icon: const Icon(Symbols.add),
|
||||
label: Text('createBot').tr(),
|
||||
),
|
||||
],
|
||||
),
|
||||
);
|
||||
}
|
||||
return RefreshIndicator(
|
||||
onRefresh:
|
||||
() => ref.refresh(botsProvider(publisherName, projectId).future),
|
||||
child: ListView.builder(
|
||||
padding: const EdgeInsets.only(top: 4),
|
||||
itemCount: data.length,
|
||||
itemBuilder: (context, index) {
|
||||
final bot = data[index];
|
||||
return Card(
|
||||
margin: const EdgeInsets.all(8.0),
|
||||
child: ListTile(
|
||||
shape: const RoundedRectangleBorder(
|
||||
borderRadius: BorderRadius.all(Radius.circular(8.0)),
|
||||
),
|
||||
leading: CircleAvatar(
|
||||
child:
|
||||
bot.account.profile.picture != null
|
||||
? ProfilePictureWidget(
|
||||
file: bot.account.profile.picture!,
|
||||
)
|
||||
: const Icon(Symbols.smart_toy),
|
||||
),
|
||||
title: Text(bot.account.nick),
|
||||
subtitle: Text(bot.account.name),
|
||||
trailing: PopupMenuButton(
|
||||
itemBuilder:
|
||||
(context) => [
|
||||
PopupMenuItem(
|
||||
value: 'edit',
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Symbols.edit),
|
||||
const SizedBox(width: 12),
|
||||
Text('edit').tr(),
|
||||
],
|
||||
),
|
||||
),
|
||||
PopupMenuItem(
|
||||
value: 'delete',
|
||||
child: Row(
|
||||
children: [
|
||||
const Icon(Symbols.delete, color: Colors.red),
|
||||
const SizedBox(width: 12),
|
||||
Text(
|
||||
'delete',
|
||||
style: TextStyle(color: Colors.red),
|
||||
).tr(),
|
||||
],
|
||||
),
|
||||
),
|
||||
],
|
||||
onSelected: (value) {
|
||||
if (value == 'edit') {
|
||||
context.pushNamed(
|
||||
'developerBotEdit',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
'id': bot.id,
|
||||
},
|
||||
);
|
||||
} else if (value == 'delete') {
|
||||
showConfirmAlert(
|
||||
'deleteBotHint'.tr(),
|
||||
'deleteBot'.tr(),
|
||||
).then((confirm) {
|
||||
if (confirm) {
|
||||
final client = ref.read(apiClientProvider);
|
||||
client.delete(
|
||||
'/develop/developers/$publisherName/projects/$projectId/bots/${bot.id}',
|
||||
);
|
||||
ref.invalidate(
|
||||
botsProvider(publisherName, projectId),
|
||||
);
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
),
|
||||
onTap: () {
|
||||
context.pushNamed(
|
||||
'developerBotDetail',
|
||||
pathParameters: {
|
||||
'name': publisherName,
|
||||
'projectId': projectId,
|
||||
'botId': bot.id,
|
||||
},
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
),
|
||||
);
|
||||
},
|
||||
loading: () => const Center(child: CircularProgressIndicator()),
|
||||
error:
|
||||
(err, stack) => ResponseErrorWidget(
|
||||
error: err,
|
||||
onRetry:
|
||||
() => ref.invalidate(botsProvider(publisherName, projectId)),
|
||||
),
|
||||
);
|
||||
}
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user