Compare commits
58 Commits
3.0.0+93
...
61e61866d7
| Author | SHA1 | Date | |
|---|---|---|---|
| 61e61866d7 | |||
| 280c261ea1 | |||
| 49bc6b9a98 | |||
| 461f32545a | |||
| 36b9026e9e | |||
| 78f258dcea | |||
| 044fb983d6 | |||
| 2a7876e22f | |||
| 0bbfa6ddde | |||
| 1f46f89056 | |||
| 7740cf7830 | |||
| d165e488ad | |||
| 37f5c61905 | |||
| 723e17ff47 | |||
| 20e6cc4283 | |||
| b2a118bbd0 | |||
| 3dd7c8a5b2 | |||
| d832729278 | |||
| dff8532229 | |||
| bf77bfce64 | |||
|
|
accb99bb24 | ||
|
|
e67429e513 | ||
|
|
a87f5d61e6 | ||
| b84fafb53c | |||
| 9e9d8b6fab | |||
| 088cb4d5a2 | |||
| 33e84805d7 | |||
| 9aca6eb674 | |||
| e431a54a89 | |||
| c00987dfdc | |||
| 4187ceb248 | |||
| 152e076d44 | |||
| 7f36c86c55 | |||
| 311420e1f7 | |||
| afe1c700eb | |||
| b0c1981c9a | |||
| d943275ed5 | |||
| 010a49251c | |||
| bdc13978c3 | |||
| 5d8c73e468 | |||
| 360572d7d1 | |||
| 9c1a983466 | |||
| bfa97dcd11 | |||
| aaa505e83e | |||
| 552bdfa58f | |||
| ebde4eeed5 | |||
| 688f035f85 | |||
| fd587270da | |||
| 6b4189a93b | |||
| fed8171b36 | |||
| f39a066f71 | |||
| edf4ff1c5b | |||
| 9abc61a310 | |||
| 205d52df46 | |||
| a2053aa772 | |||
| 81103ba8b6 | |||
| 76faa4172f | |||
| 9866c22746 |
83
.github/workflows/build.yml
vendored
Normal file
83
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,83 @@
|
|||||||
|
name: Build Release
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- '*'
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-web:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache: true
|
||||||
|
- run: flutter pub get
|
||||||
|
- run: flutter build web --release
|
||||||
|
- name: Archive production artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-output-web
|
||||||
|
path: build/web
|
||||||
|
build-exe:
|
||||||
|
runs-on: windows-latest
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
cache: true
|
||||||
|
- run: flutter pub get
|
||||||
|
- run: flutter build windows
|
||||||
|
- name: Archive production artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-output-windows
|
||||||
|
path: build/windows/x64/runner/Release
|
||||||
|
build-linux:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Clone repository
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Flutter
|
||||||
|
uses: subosito/flutter-action@v2
|
||||||
|
with:
|
||||||
|
channel: stable
|
||||||
|
- run: |
|
||||||
|
sudo apt-get update -y
|
||||||
|
sudo apt-get install -y ninja-build libgtk-3-dev
|
||||||
|
sudo apt-get install -y libmpv-dev mpv
|
||||||
|
sudo apt-get install -y libayatana-appindicator3-dev
|
||||||
|
sudo apt-get install -y keybinder-3.0
|
||||||
|
sudo apt-get install -y libnotify-dev
|
||||||
|
sudo apt-get install -y libgstreamer1.0-dev libgstreamer-plugins-base1.0-dev
|
||||||
|
sudo apt-get install -y gstreamer-1.0
|
||||||
|
- run: flutter pub get
|
||||||
|
- run: flutter build linux
|
||||||
|
- name: Archive production artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-output-linux
|
||||||
|
path: build/linux/x64/release/bundle
|
||||||
|
- name: Build AppImage
|
||||||
|
run: |
|
||||||
|
rm -r Solian.AppDir | true
|
||||||
|
mkdir Solian.AppDir
|
||||||
|
cp -r build/linux/x64/release/bundle/* Solian.AppDir
|
||||||
|
cp -r buildtools/appimage_config/* Solian.AppDir
|
||||||
|
cp assets/icons/icon-padded.png Solian.AppDir
|
||||||
|
sudo chmod +x buildtools/appimagetool-x86_64.AppImage
|
||||||
|
sudo chmod +x Solian.AppDir/AppRun
|
||||||
|
./buildtools/appimagetool-x86_64.AppImage Solian.AppDir
|
||||||
|
- name: Archive production artifacts
|
||||||
|
uses: actions/upload-artifact@v4
|
||||||
|
with:
|
||||||
|
name: build-output-linux-appimage
|
||||||
|
path: './*.AppImage*'
|
||||||
1
.vscode/settings.json
vendored
Normal file
1
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@@ -11,7 +11,7 @@ plugins {
|
|||||||
android {
|
android {
|
||||||
namespace = "dev.solsynth.solian"
|
namespace = "dev.solsynth.solian"
|
||||||
compileSdk = flutter.compileSdkVersion
|
compileSdk = flutter.compileSdkVersion
|
||||||
ndkVersion = "27.0.12077973"
|
ndkVersion = "29.0.13113456"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
|
|||||||
@@ -34,19 +34,22 @@
|
|||||||
while the Flutter UI initializes. After that, this theme continues
|
while the Flutter UI initializes. After that, this theme continues
|
||||||
to determine the Window background behind the Flutter UI. -->
|
to determine the Window background behind the Flutter UI. -->
|
||||||
<meta-data
|
<meta-data
|
||||||
android:name="io.flutter.embedding.android.NormalTheme"
|
android:name="io.flutter.embedding.android.NormalTheme"
|
||||||
android:resource="@style/NormalTheme"
|
android:resource="@style/NormalTheme"
|
||||||
/>
|
/>
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
<action android:name="android.intent.action.MAIN"/>
|
<action android:name="android.intent.action.MAIN" />
|
||||||
<category android:name="android.intent.category.LAUNCHER"/>
|
<category android:name="android.intent.category.LAUNCHER" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
<provider
|
<provider
|
||||||
android:name="com.superlist.super_native_extensions.DataProvider"
|
android:name="androidx.core.content.FileProvider"
|
||||||
android:authorities="dev.solsynth.solian.SuperClipboardDataProvider"
|
android:authorities="dev.solsynth.solian.provider"
|
||||||
android:exported="true"
|
android:exported="false"
|
||||||
android:grantUriPermissions="true" >
|
android:grantUriPermissions="true">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/provider_paths" />
|
||||||
</provider>
|
</provider>
|
||||||
<!-- Don't delete the meta-data below.
|
<!-- Don't delete the meta-data below.
|
||||||
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
|
||||||
@@ -61,8 +64,8 @@
|
|||||||
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
In particular, this is used by the Flutter engine in io.flutter.plugin.text.ProcessTextPlugin. -->
|
||||||
<queries>
|
<queries>
|
||||||
<intent>
|
<intent>
|
||||||
<action android:name="android.intent.action.PROCESS_TEXT"/>
|
<action android:name="android.intent.action.PROCESS_TEXT" />
|
||||||
<data android:mimeType="text/plain"/>
|
<data android:mimeType="text/plain" />
|
||||||
</intent>
|
</intent>
|
||||||
</queries>
|
</queries>
|
||||||
</manifest>
|
</manifest>
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
package dev.solsynth.solian
|
|
||||||
|
|
||||||
import io.flutter.embedding.android.FlutterActivity
|
|
||||||
|
|
||||||
class MainActivity : FlutterActivity()
|
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
package dev.solsynth.solian
|
||||||
|
|
||||||
|
import io.flutter.embedding.android.FlutterActivity
|
||||||
|
import io.flutter.embedding.engine.FlutterEngine
|
||||||
|
import io.flutter.plugins.sharedpreferences.LegacySharedPreferencesPlugin
|
||||||
|
|
||||||
|
class MainActivity : FlutterActivity()
|
||||||
|
{
|
||||||
|
override fun configureFlutterEngine(flutterEngine: FlutterEngine) {
|
||||||
|
super.configureFlutterEngine(flutterEngine)
|
||||||
|
// https://github.com/flutter/flutter/issues/153075#issuecomment-2693189362
|
||||||
|
flutterEngine.plugins.add(LegacySharedPreferencesPlugin())
|
||||||
|
}
|
||||||
|
}
|
||||||
6
android/app/src/main/res/xml/provider_paths.xml
Normal file
6
android/app/src/main/res/xml/provider_paths.xml
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<paths xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
<external-path
|
||||||
|
name="external_files"
|
||||||
|
path="." />
|
||||||
|
</paths>
|
||||||
663
android/build/reports/problems/problems-report.html
Normal file
663
android/build/reports/problems/problems-report.html
Normal file
File diff suppressed because one or more lines are too long
@@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME
|
|||||||
distributionPath=wrapper/dists
|
distributionPath=wrapper/dists
|
||||||
zipStoreBase=GRADLE_USER_HOME
|
zipStoreBase=GRADLE_USER_HOME
|
||||||
zipStorePath=wrapper/dists
|
zipStorePath=wrapper/dists
|
||||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
|
distributionUrl=https\://services.gradle.org/distributions/gradle-8.11.1-all.zip
|
||||||
|
|||||||
@@ -18,7 +18,7 @@ pluginManagement {
|
|||||||
|
|
||||||
plugins {
|
plugins {
|
||||||
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
id("dev.flutter.flutter-plugin-loader") version "1.0.0"
|
||||||
id("com.android.application") version "8.7.0" apply false
|
id("com.android.application") version "8.10.1" apply false
|
||||||
// START: FlutterFire Configuration
|
// START: FlutterFire Configuration
|
||||||
id("com.google.gms.google-services") version("4.3.15") apply false
|
id("com.google.gms.google-services") version("4.3.15") apply false
|
||||||
// END: FlutterFire Configuration
|
// END: FlutterFire Configuration
|
||||||
|
|||||||
@@ -99,6 +99,16 @@
|
|||||||
"permissionMember": "Member",
|
"permissionMember": "Member",
|
||||||
"reply": "Reply",
|
"reply": "Reply",
|
||||||
"forward": "Forward",
|
"forward": "Forward",
|
||||||
|
"repliedTo": "Replied to",
|
||||||
|
"forwarded": "Forwarded",
|
||||||
|
"hasAttachments": {
|
||||||
|
"one": "{} attachment",
|
||||||
|
"other": "{} attachments"
|
||||||
|
},
|
||||||
|
"postHasAttachments": {
|
||||||
|
"one": "{} attachment",
|
||||||
|
"other": "{} attachments"
|
||||||
|
},
|
||||||
"edited": "Edited",
|
"edited": "Edited",
|
||||||
"addVideo": "Add video",
|
"addVideo": "Add video",
|
||||||
"addPhoto": "Add photo",
|
"addPhoto": "Add photo",
|
||||||
@@ -155,7 +165,7 @@
|
|||||||
"status": "Status",
|
"status": "Status",
|
||||||
"statusActivityTitle": "{} is {} {}",
|
"statusActivityTitle": "{} is {} {}",
|
||||||
"statusActivityEndedTitle": "{} is {} {} until {}",
|
"statusActivityEndedTitle": "{} is {} {} until {}",
|
||||||
"appSettings": "App settings",
|
"appSettings": "App Settings",
|
||||||
"accountSettings": "Account Settings",
|
"accountSettings": "Account Settings",
|
||||||
"settings": "Settings",
|
"settings": "Settings",
|
||||||
"language": "Language",
|
"language": "Language",
|
||||||
@@ -272,11 +282,135 @@
|
|||||||
"one": "{} unread message",
|
"one": "{} unread message",
|
||||||
"other": "{} unread messages"
|
"other": "{} unread messages"
|
||||||
},
|
},
|
||||||
|
"chatBreakNone": "None",
|
||||||
"settingsRealmCompactView": "Compact Realm View",
|
"settingsRealmCompactView": "Compact Realm View",
|
||||||
"settingsMixedFeed": "Mixed Feed",
|
"settingsMixedFeed": "Mixed Feed",
|
||||||
"settingsAutoTranslate": "Auto Translate",
|
"settingsAutoTranslate": "Auto Translate",
|
||||||
"settingsHideBottomNav": "Hide Bottom Navigation",
|
"settingsHideBottomNav": "Hide Bottom Navigation",
|
||||||
"settingsSoundEffects": "Sound Effects",
|
"settingsSoundEffects": "Sound Effects",
|
||||||
"settingsAprilFoolFeatures": "April Fool Features",
|
"settingsAprilFoolFeatures": "April Fool Features",
|
||||||
"settingsEnterToSend": "Enter to Send"
|
"settingsEnterToSend": "Enter to Send",
|
||||||
|
"settingsTransparentAppBar": "Transparent App Bar",
|
||||||
|
"settingsCustomFonts": "Custom Fonts",
|
||||||
|
"settingsCustomFontsHint": "Custom fonts will be used for all text in the app. Make sure it is installed on your device.",
|
||||||
|
"settingsColorScheme": "Color Scheme",
|
||||||
|
"postTitle": "Title",
|
||||||
|
"postDescription": "Description",
|
||||||
|
"call": "Call",
|
||||||
|
"done": "Done",
|
||||||
|
"loginResetPasswordSent": "Password reset link sent, please check your email inbox.",
|
||||||
|
"accountDeletion": "Delete Account",
|
||||||
|
"accountDeletionHint": "Are you sure to delete your account? If you confirmed, we will send an confirmation email to your primary email address, you can continue the deletion process by follow the insturctions in the email.",
|
||||||
|
"accountDeletionSent": "Account deletion confirmation email sent, please check your email inbox.",
|
||||||
|
"accountSecurityTitle": "Security",
|
||||||
|
"accountDangerZoneTitle": "Danger Zone",
|
||||||
|
"accountPassword": "Password",
|
||||||
|
"accountPasswordDescription": "Change your account password",
|
||||||
|
"accountPasswordChange": "Change Password",
|
||||||
|
"accountPasswordChangeSent": "Password reset link sent, please check your email inbox.",
|
||||||
|
"accountPasswordChangeDescription": "We will send an email to your primary email address to reset your password.",
|
||||||
|
"accountAuthFactor": "Auth factors",
|
||||||
|
"accountAuthFactorDescription": "Multi-factor authentication to ensure safety and convience",
|
||||||
|
"accountDeletionDescription": "Permanently delete your account and all your data",
|
||||||
|
"accountSettingsHelp": "Account Settings Help",
|
||||||
|
"accountSettingsHelpContent": "This page allows you to manage your account security, privacy, and other settings. If you need assistance, please contact support.",
|
||||||
|
"unauthorized": "Unauthorized",
|
||||||
|
"unauthorizedHint": "You're not signed in or session expired, please sign in again.",
|
||||||
|
"publisherVisitAccountPage": "Visit the profile of {}",
|
||||||
|
"postVisibility": "Visibility",
|
||||||
|
"postVisibilityPublic": "Public",
|
||||||
|
"postVisibilityFriends": "Friends Only",
|
||||||
|
"postVisibilityUnlisted": "Unlisted",
|
||||||
|
"postVisibilityPrivate": "Private",
|
||||||
|
"copyMessage": "Copy Message",
|
||||||
|
"authFactor": "Authentication Factor",
|
||||||
|
"authFactorDelete": "Delete the Factor",
|
||||||
|
"authFactorDeleteHint": "Are you sure you want to delete this authentication factor? This action cannot be undone.",
|
||||||
|
"authFactorDisable": "Disable the Factor",
|
||||||
|
"authFactorDisableHint": "Are you sure you want to disable this authentication factor? You can enable it again later.",
|
||||||
|
"authFactorEnable": "Enable the Factor",
|
||||||
|
"authFactorEnableHint": "Please enter the code that generated by the factor to enable it.",
|
||||||
|
"authFactorNew": "Create Auth Factor",
|
||||||
|
"authFactorSecret": "Secret",
|
||||||
|
"authFactorSecretHint": "Create an secret for this factor.",
|
||||||
|
"authFactorQrCodeScan": "Scan this QR code with your authenticator app to set up TOTP authentication",
|
||||||
|
"authFactorNoQrCode": "No QR code available for this authentication factor",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"confirm": "Confirm",
|
||||||
|
"authFactorAdditional": "One more step",
|
||||||
|
"authFactorHint": "Contact method hint",
|
||||||
|
"authFactorHintHelper": "You need provide a part of your contact method and we will send the verification code to that contact method if it matched our records",
|
||||||
|
"authSessions": "Active Sessions",
|
||||||
|
"authSessionsDescription": "See devices you currently logged in.",
|
||||||
|
"authSessionsCount": {
|
||||||
|
"one": "{} session",
|
||||||
|
"other": "{} sessions"
|
||||||
|
},
|
||||||
|
"authDeviceCurrent": "Current device",
|
||||||
|
"lastActiveAt": "Last active at {}",
|
||||||
|
"authDeviceLogout": "Logout",
|
||||||
|
"authDeviceLogoutHint": "Are you sure you want to logout this device? This will also disable the push notification to this device.",
|
||||||
|
"authDeviceEditLabel": "Edit Label",
|
||||||
|
"authDeviceLabelTitle": "Edit Device Label",
|
||||||
|
"authDeviceLabelHint": "Enter a name for this device",
|
||||||
|
"authDeviceSwipeEditHint": "Swipe left to edit label",
|
||||||
|
"authDeviceSwipeLogoutHint": "Swipe right to logout device",
|
||||||
|
"typingHint": {
|
||||||
|
"one": "{} is typing...",
|
||||||
|
"other": "{} are typing..."
|
||||||
|
},
|
||||||
|
"settingsAppearance": "Appearance",
|
||||||
|
"settingsServer": "Server",
|
||||||
|
"settingsBehavior": "Behavior",
|
||||||
|
"settingsDesktop": "Desktop",
|
||||||
|
"settingsKeyboardShortcuts": "Keyboard Shortcuts",
|
||||||
|
"settingsEnterToSendDesktopHint": "Press Enter to send messages, use Shift+Enter for new line.",
|
||||||
|
"settingsHelp": "Settings Help",
|
||||||
|
"settingsHelpContent": "This page allows you to manage your app settings, appearance, and behavior. If you need assistance, please contact support.",
|
||||||
|
"settingsKeyboardShortcutSearch": "Search",
|
||||||
|
"settingsKeyboardShortcutSettings": "Settings",
|
||||||
|
"settingsKeyboardShortcutNewMessage": "New Message",
|
||||||
|
"settingsKeyboardShortcutCloseDialog": "Close Dialog",
|
||||||
|
"close": "Close",
|
||||||
|
"contactMethod": "Contact Method",
|
||||||
|
"contactMethodType": "Contact Type",
|
||||||
|
"contactMethodTypeEmail": "Email",
|
||||||
|
"contactMethodTypePhone": "Phone",
|
||||||
|
"contactMethodTypeAddress": "Address",
|
||||||
|
"contactMethodEmailHint": "Enter your email address",
|
||||||
|
"contactMethodPhoneHint": "Enter your phone number",
|
||||||
|
"contactMethodAddressHint": "Enter your physical address",
|
||||||
|
"contactMethodEmailDescription": "Your email will be used for account recovery and notifications",
|
||||||
|
"contactMethodPhoneDescription": "Your phone number will be used for account recovery and notifications",
|
||||||
|
"contactMethodAddressDescription": "Your physical address will be used for shipping and billing purposes.",
|
||||||
|
"contactMethodVerified": "Verified",
|
||||||
|
"contactMethodUnverified": "Unverified",
|
||||||
|
"contactMethodVerify": "Verify Contact",
|
||||||
|
"contactMethodDelete": "Delete Contact",
|
||||||
|
"contactMethodNew": "New Contact Method",
|
||||||
|
"contactMethodContentEmpty": "Contact content cannot be empty",
|
||||||
|
"contactMethodVerificationSent": "Verification code sent to your contact method",
|
||||||
|
"contactMethodVerificationNeeded": "The contact method is added, but not verified yet. You can verify it by tapping it and select verify.",
|
||||||
|
"accountContactMethod": "Contact Methods",
|
||||||
|
"accountContactMethodDescription": "Manage your contact methods for account recovery and notifications",
|
||||||
|
"authFactorVerificationNeeded": "The auth factor is added, but it is not enabled yet. You can enable it by tapping it and enter the verification code.",
|
||||||
|
"contactMethodPrimary": "Primary",
|
||||||
|
"contactMethodSetPrimary": "Set as Primary",
|
||||||
|
"contactMethodSetPrimaryHint": "Set this contact method as your primary contact method for account recovery and notifications",
|
||||||
|
"contactMethodDeleteHint": "Are you sure to delete this contact method? This action cannot be undone.",
|
||||||
|
"chatNotifyLevel": "Notify Level",
|
||||||
|
"chatNotifyLevelDescription": "Decide how many notifications you will receive.",
|
||||||
|
"chatNotifyLevelAll": "All",
|
||||||
|
"chatNotifyLevelMention": "Mentions",
|
||||||
|
"chatNotifyLevelNone": "None",
|
||||||
|
"chatNotifyLevelUpdated": "The notify level has been updated to {}.",
|
||||||
|
"chatBreak": "Take a Break",
|
||||||
|
"chatBreakDescription": "Set a time, before that time, your notification level will be metions only, to take a break of the current topic they're talking about.",
|
||||||
|
"chatBreakClear": "Clear the break time",
|
||||||
|
"chatBreakHour": "{} break",
|
||||||
|
"chatBreakDay": "{} day break",
|
||||||
|
"chatBreakSet": "Break set for {}",
|
||||||
|
"chatBreakCleared": "Chat break has been cleared.",
|
||||||
|
"chatBreakCustom": "Custom duration",
|
||||||
|
"chatBreakEnterMinutes": "Enter minutes"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -99,6 +99,14 @@
|
|||||||
"permissionMember": "成员",
|
"permissionMember": "成员",
|
||||||
"reply": "回复",
|
"reply": "回复",
|
||||||
"forward": "转发",
|
"forward": "转发",
|
||||||
|
"repliedTo": "回复了",
|
||||||
|
"forwarded": "转发了",
|
||||||
|
"hasAttachments": {
|
||||||
|
"other": "{}个附件"
|
||||||
|
},
|
||||||
|
"postHasAttachments": {
|
||||||
|
"other": "{}个附件"
|
||||||
|
},
|
||||||
"edited": "已编辑",
|
"edited": "已编辑",
|
||||||
"addVideo": "添加视频",
|
"addVideo": "添加视频",
|
||||||
"addPhoto": "添加照片",
|
"addPhoto": "添加照片",
|
||||||
@@ -278,5 +286,26 @@
|
|||||||
"settingsHideBottomNav": "隐藏底部导航",
|
"settingsHideBottomNav": "隐藏底部导航",
|
||||||
"settingsSoundEffects": "音效",
|
"settingsSoundEffects": "音效",
|
||||||
"settingsAprilFoolFeatures": "愚人节功能",
|
"settingsAprilFoolFeatures": "愚人节功能",
|
||||||
"settingsEnterToSend": "按下 Enter 发送"
|
"settingsEnterToSend": "按下 Enter 发送",
|
||||||
|
"postVisibility": "可见性",
|
||||||
|
"postVisibilityPublic": "公开",
|
||||||
|
"postVisibilityFriends": "仅好友可见",
|
||||||
|
"postVisibilityUnlisted": "不公开",
|
||||||
|
"postVisibilityPrivate": "私密",
|
||||||
|
"chatNotifyLevel": "通知级别",
|
||||||
|
"chatNotifyLevelDescription": "决定您将收到多少通知。",
|
||||||
|
"chatNotifyLevelAll": "全部",
|
||||||
|
"chatNotifyLevelMention": "提及",
|
||||||
|
"chatNotifyLevelNone": "无",
|
||||||
|
"chatNotifyLevelUpdated": "通知级别已更新为 {}。",
|
||||||
|
"chatBreak": "暂停聊天",
|
||||||
|
"chatBreakDescription": "设置一个时间,在该时间之前,您的通知级别将仅为提及,以暂时休息当前讨论的话题。",
|
||||||
|
"chatBreakClear": "清除暂停时间",
|
||||||
|
"chatBreakHour": "暂停 {} 分钟",
|
||||||
|
"chatBreakDay": "暂停 {} 天",
|
||||||
|
"chatBreakSet": "已设置暂停 {}",
|
||||||
|
"chatBreakCleared": "聊天暂停已清除。",
|
||||||
|
"chatBreakCustom": "自定义时长",
|
||||||
|
"chatBreakEnterMinutes": "输入分钟数",
|
||||||
|
"chatBreakNone": "无"
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@
|
|||||||
"createRealmHint": "結識志同道合的朋友、建立社群等等。",
|
"createRealmHint": "結識志同道合的朋友、建立社群等等。",
|
||||||
"editRealm": "編輯領域",
|
"editRealm": "編輯領域",
|
||||||
"deleteRealm": "刪除領域",
|
"deleteRealm": "刪除領域",
|
||||||
"deleteRealmHint": "確定要刪除此領域嗎?這也將刪除此領域下的所有頻道、發佈者和貼文。",
|
"deleteRealmHint": "確定要刪除此領域嗎?這也將刪除該領域下的所有頻道、發佈者和貼文。",
|
||||||
"explore": "探索",
|
"explore": "探索",
|
||||||
"account": "帳號",
|
"account": "帳號",
|
||||||
"name": "名稱",
|
"name": "名稱",
|
||||||
@@ -99,6 +99,14 @@
|
|||||||
"permissionMember": "成員",
|
"permissionMember": "成員",
|
||||||
"reply": "回覆",
|
"reply": "回覆",
|
||||||
"forward": "轉發",
|
"forward": "轉發",
|
||||||
|
"repliedTo": "回覆了",
|
||||||
|
"forwarded": "轉發了",
|
||||||
|
"hasAttachments": {
|
||||||
|
"other": "{}個附件"
|
||||||
|
},
|
||||||
|
"postHasAttachments": {
|
||||||
|
"other": "{}個附件"
|
||||||
|
},
|
||||||
"edited": "已編輯",
|
"edited": "已編輯",
|
||||||
"addVideo": "新增影片",
|
"addVideo": "新增影片",
|
||||||
"addPhoto": "新增照片",
|
"addPhoto": "新增照片",
|
||||||
@@ -278,5 +286,26 @@
|
|||||||
"settingsHideBottomNav": "隱藏底部導航",
|
"settingsHideBottomNav": "隱藏底部導航",
|
||||||
"settingsSoundEffects": "音效",
|
"settingsSoundEffects": "音效",
|
||||||
"settingsAprilFoolFeatures": "愚人節功能",
|
"settingsAprilFoolFeatures": "愚人節功能",
|
||||||
"settingsEnterToSend": "按下 Enter 傳送"
|
"settingsEnterToSend": "按下 Enter 傳送",
|
||||||
|
"postVisibility": "可見性",
|
||||||
|
"postVisibilityPublic": "公開",
|
||||||
|
"postVisibilityFriends": "僅好友可見",
|
||||||
|
"postVisibilityUnlisted": "不公開",
|
||||||
|
"postVisibilityPrivate": "私密",
|
||||||
|
"chatNotifyLevel": "通知等級",
|
||||||
|
"chatNotifyLevelDescription": "決定您將收到多少通知。",
|
||||||
|
"chatNotifyLevelAll": "全部",
|
||||||
|
"chatNotifyLevelMention": "提及",
|
||||||
|
"chatNotifyLevelNone": "無",
|
||||||
|
"chatNotifyLevelUpdated": "通知等級已更新為 {}。",
|
||||||
|
"chatBreak": "暫停聊天",
|
||||||
|
"chatBreakDescription": "設定一個時間,在該時間之前,您的通知等級將僅為提及,以暫時休息當前討論的話題。",
|
||||||
|
"chatBreakClear": "清除暫停時間",
|
||||||
|
"chatBreakHour": "暫停 {} 分鐘",
|
||||||
|
"chatBreakDay": "暫停 {} 天",
|
||||||
|
"chatBreakSet": "已設定暫停 {}",
|
||||||
|
"chatBreakCleared": "聊天暫停已清除。",
|
||||||
|
"chatBreakCustom": "自訂時長",
|
||||||
|
"chatBreakEnterMinutes": "輸入分鐘數",
|
||||||
|
"chatBreakNone": "無"
|
||||||
}
|
}
|
||||||
4
buildtools/appimage_config/AppRun
Executable file
4
buildtools/appimage_config/AppRun
Executable file
@@ -0,0 +1,4 @@
|
|||||||
|
#!/bin/sh
|
||||||
|
|
||||||
|
cd "$(dirname "$0")"
|
||||||
|
exec ./island
|
||||||
8
buildtools/appimage_config/Solian.desktop
Normal file
8
buildtools/appimage_config/Solian.desktop
Normal file
@@ -0,0 +1,8 @@
|
|||||||
|
[Desktop Entry]
|
||||||
|
Version=1.0
|
||||||
|
Type=Application
|
||||||
|
Terminal=false
|
||||||
|
Name=Solian
|
||||||
|
Exec=island %u
|
||||||
|
Icon=icon-padded
|
||||||
|
Categories=Network;
|
||||||
BIN
buildtools/appimagetool-x86_64.AppImage
Executable file
BIN
buildtools/appimagetool-x86_64.AppImage
Executable file
Binary file not shown.
14
ios/Podfile
14
ios/Podfile
@@ -29,17 +29,29 @@ flutter_ios_podfile_setup
|
|||||||
|
|
||||||
target 'Runner' do
|
target 'Runner' do
|
||||||
use_frameworks!
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
pod 'Kingfisher', '~> 8.0'
|
pod 'Alamofire'
|
||||||
|
|
||||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||||
|
|
||||||
target 'RunnerTests' do
|
target 'RunnerTests' do
|
||||||
inherit! :search_paths
|
inherit! :search_paths
|
||||||
end
|
end
|
||||||
|
|
||||||
|
target 'SolianNotificationService' do
|
||||||
|
inherit! :search_paths
|
||||||
|
pod 'Kingfisher', '~> 8.0'
|
||||||
|
pod 'Alamofire'
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
post_install do |installer|
|
||||||
installer.pods_project.targets.each do |target|
|
installer.pods_project.targets.each do |target|
|
||||||
flutter_additional_ios_build_settings(target)
|
flutter_additional_ios_build_settings(target)
|
||||||
|
target.build_configurations.each do |config|
|
||||||
|
# Workaround for https://github.com/flutter/flutter/issues/64502
|
||||||
|
config.build_settings['ONLY_ACTIVE_ARCH'] = 'YES' # <= this line
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|||||||
@@ -1,4 +1,7 @@
|
|||||||
PODS:
|
PODS:
|
||||||
|
- Alamofire (5.10.2)
|
||||||
|
- connectivity_plus (0.0.1):
|
||||||
|
- Flutter
|
||||||
- croppy (0.0.1):
|
- croppy (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- device_info_plus (0.0.1):
|
- device_info_plus (0.0.1):
|
||||||
@@ -84,6 +87,11 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
|
- flutter_webrtc (0.14.0):
|
||||||
|
- Flutter
|
||||||
|
- WebRTC-SDK (= 125.6422.07)
|
||||||
|
- gal (1.0.0):
|
||||||
|
- Flutter
|
||||||
- GoogleDataTransport (10.1.0):
|
- GoogleDataTransport (10.1.0):
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
@@ -116,6 +124,10 @@ PODS:
|
|||||||
- irondash_engine_context (0.0.1):
|
- irondash_engine_context (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Kingfisher (8.3.2)
|
- Kingfisher (8.3.2)
|
||||||
|
- livekit_client (2.4.7):
|
||||||
|
- Flutter
|
||||||
|
- flutter_webrtc
|
||||||
|
- WebRTC-SDK (= 125.6422.07)
|
||||||
- media_kit_libs_ios_video (1.0.4):
|
- media_kit_libs_ios_video (1.0.4):
|
||||||
- Flutter
|
- Flutter
|
||||||
- media_kit_video (0.0.1):
|
- media_kit_video (0.0.1):
|
||||||
@@ -128,10 +140,14 @@ PODS:
|
|||||||
- OrderedSet (6.0.3)
|
- OrderedSet (6.0.3)
|
||||||
- package_info_plus (0.4.5):
|
- package_info_plus (0.4.5):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- pasteboard (0.0.1):
|
||||||
|
- Flutter
|
||||||
- path_provider_foundation (0.0.1):
|
- path_provider_foundation (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- PromisesObjC (2.4.0)
|
- PromisesObjC (2.4.0)
|
||||||
|
- record_ios (1.0.0):
|
||||||
|
- Flutter
|
||||||
- SAMKeychain (1.5.3)
|
- SAMKeychain (1.5.3)
|
||||||
- SDWebImage (5.21.0):
|
- SDWebImage (5.21.0):
|
||||||
- SDWebImage/Core (= 5.21.0)
|
- SDWebImage/Core (= 5.21.0)
|
||||||
@@ -173,8 +189,11 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- WebRTC-SDK (125.6422.07)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
|
- Alamofire
|
||||||
|
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||||
- croppy (from `.symlinks/plugins/croppy/ios`)
|
- croppy (from `.symlinks/plugins/croppy/ios`)
|
||||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||||
@@ -185,13 +204,18 @@ DEPENDENCIES:
|
|||||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||||
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
||||||
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
- flutter_udid (from `.symlinks/plugins/flutter_udid/ios`)
|
||||||
|
- flutter_webrtc (from `.symlinks/plugins/flutter_webrtc/ios`)
|
||||||
|
- gal (from `.symlinks/plugins/gal/ios`)
|
||||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||||
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
|
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
|
||||||
- Kingfisher (~> 8.0)
|
- Kingfisher (~> 8.0)
|
||||||
|
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
||||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||||
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
||||||
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
- package_info_plus (from `.symlinks/plugins/package_info_plus/ios`)
|
||||||
|
- pasteboard (from `.symlinks/plugins/pasteboard/ios`)
|
||||||
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
- path_provider_foundation (from `.symlinks/plugins/path_provider_foundation/darwin`)
|
||||||
|
- record_ios (from `.symlinks/plugins/record_ios/ios`)
|
||||||
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
- shared_preferences_foundation (from `.symlinks/plugins/shared_preferences_foundation/darwin`)
|
||||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||||
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||||
@@ -202,6 +226,7 @@ DEPENDENCIES:
|
|||||||
|
|
||||||
SPEC REPOS:
|
SPEC REPOS:
|
||||||
trunk:
|
trunk:
|
||||||
|
- Alamofire
|
||||||
- DKImagePickerController
|
- DKImagePickerController
|
||||||
- DKPhotoGallery
|
- DKPhotoGallery
|
||||||
- Firebase
|
- Firebase
|
||||||
@@ -219,8 +244,11 @@ SPEC REPOS:
|
|||||||
- SDWebImage
|
- SDWebImage
|
||||||
- sqlite3
|
- sqlite3
|
||||||
- SwiftyGif
|
- SwiftyGif
|
||||||
|
- WebRTC-SDK
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
connectivity_plus:
|
||||||
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
croppy:
|
croppy:
|
||||||
:path: ".symlinks/plugins/croppy/ios"
|
:path: ".symlinks/plugins/croppy/ios"
|
||||||
device_info_plus:
|
device_info_plus:
|
||||||
@@ -241,18 +269,28 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_platform_alert/ios"
|
:path: ".symlinks/plugins/flutter_platform_alert/ios"
|
||||||
flutter_udid:
|
flutter_udid:
|
||||||
:path: ".symlinks/plugins/flutter_udid/ios"
|
:path: ".symlinks/plugins/flutter_udid/ios"
|
||||||
|
flutter_webrtc:
|
||||||
|
:path: ".symlinks/plugins/flutter_webrtc/ios"
|
||||||
|
gal:
|
||||||
|
:path: ".symlinks/plugins/gal/ios"
|
||||||
image_picker_ios:
|
image_picker_ios:
|
||||||
:path: ".symlinks/plugins/image_picker_ios/ios"
|
:path: ".symlinks/plugins/image_picker_ios/ios"
|
||||||
irondash_engine_context:
|
irondash_engine_context:
|
||||||
:path: ".symlinks/plugins/irondash_engine_context/ios"
|
:path: ".symlinks/plugins/irondash_engine_context/ios"
|
||||||
|
livekit_client:
|
||||||
|
:path: ".symlinks/plugins/livekit_client/ios"
|
||||||
media_kit_libs_ios_video:
|
media_kit_libs_ios_video:
|
||||||
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
|
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
|
||||||
media_kit_video:
|
media_kit_video:
|
||||||
:path: ".symlinks/plugins/media_kit_video/ios"
|
:path: ".symlinks/plugins/media_kit_video/ios"
|
||||||
package_info_plus:
|
package_info_plus:
|
||||||
:path: ".symlinks/plugins/package_info_plus/ios"
|
:path: ".symlinks/plugins/package_info_plus/ios"
|
||||||
|
pasteboard:
|
||||||
|
:path: ".symlinks/plugins/pasteboard/ios"
|
||||||
path_provider_foundation:
|
path_provider_foundation:
|
||||||
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
:path: ".symlinks/plugins/path_provider_foundation/darwin"
|
||||||
|
record_ios:
|
||||||
|
:path: ".symlinks/plugins/record_ios/ios"
|
||||||
shared_preferences_foundation:
|
shared_preferences_foundation:
|
||||||
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
:path: ".symlinks/plugins/shared_preferences_foundation/darwin"
|
||||||
sqflite_darwin:
|
sqflite_darwin:
|
||||||
@@ -269,6 +307,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/wakelock_plus/ios"
|
:path: ".symlinks/plugins/wakelock_plus/ios"
|
||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
|
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
||||||
|
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||||
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
||||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
@@ -286,18 +326,23 @@ SPEC CHECKSUMS:
|
|||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
||||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||||
|
flutter_webrtc: fd0d3bdef8766a0736dbbe2e5b7e85f1f3c52117
|
||||||
|
gal: 29e711cd17bccb47f839d9b30afe9bc9750950b2
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||||
Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5
|
Kingfisher: 0621d0ac0c78fecb19f6dc5303bde2b52abaf2f5
|
||||||
|
livekit_client: c30950bf36aa4c0244dd5551b1818cd15f90ba32
|
||||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
|
pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c
|
||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
|
record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
|
SDWebImage: f84b0feeb08d2d11e6a9b843cb06d75ebf5b8868
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||||
@@ -309,7 +354,8 @@ SPEC CHECKSUMS:
|
|||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||||
|
WebRTC-SDK: dff00a3892bc570b6014e046297782084071657e
|
||||||
|
|
||||||
PODFILE CHECKSUM: 4c3fad73fbbc9053a824d880097bda7884240991
|
PODFILE CHECKSUM: 0c13198c20d0416ef589aeb2e1dac5c50262254f
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -10,12 +10,15 @@
|
|||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||||
|
73CDD6812DEC00480059D95D /* SolianNotificationService.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
|
73D4264B2DEB815D006C0AAE /* NotifyDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 73D4264A2DEB815D006C0AAE /* NotifyDelegate.swift */; };
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||||
755557017FD1B99AFC4F9127 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29812C17FFBE7DBBC7203981 /* Pods_RunnerTests.framework */; };
|
755557017FD1B99AFC4F9127 /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 29812C17FFBE7DBBC7203981 /* Pods_RunnerTests.framework */; };
|
||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||||
B87C0E607033790E71B54D73 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D834CA86410B09796B312B /* Pods_Runner.framework */; };
|
B87C0E607033790E71B54D73 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D834CA86410B09796B312B /* Pods_Runner.framework */; };
|
||||||
|
D1772CE196985AE8E8C9F2E5 /* Pods_SolianNotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */; };
|
||||||
E7A0B456EF7AAA71D1397081 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9AE244813FCDFAA941430393 /* GoogleService-Info.plist */; };
|
E7A0B456EF7AAA71D1397081 /* GoogleService-Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 9AE244813FCDFAA941430393 /* GoogleService-Info.plist */; };
|
||||||
/* End PBXBuildFile section */
|
/* End PBXBuildFile section */
|
||||||
|
|
||||||
@@ -27,9 +30,27 @@
|
|||||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||||
remoteInfo = Runner;
|
remoteInfo = Runner;
|
||||||
};
|
};
|
||||||
|
73CDD67F2DEC00480059D95D /* PBXContainerItemProxy */ = {
|
||||||
|
isa = PBXContainerItemProxy;
|
||||||
|
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||||
|
proxyType = 1;
|
||||||
|
remoteGlobalIDString = 73CDD6792DEC00480059D95D;
|
||||||
|
remoteInfo = SolianNotificationService;
|
||||||
|
};
|
||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "";
|
||||||
|
dstSubfolderSpec = 13;
|
||||||
|
files = (
|
||||||
|
73CDD6812DEC00480059D95D /* SolianNotificationService.appex in Embed Foundation Extensions */,
|
||||||
|
);
|
||||||
|
name = "Embed Foundation Extensions";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -47,16 +68,23 @@
|
|||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||||
14DFD79BE7C26E51B117583C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
14DFD79BE7C26E51B117583C /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
192FDACE67D7CB6AED15C634 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
1C14F71D23E4371602065522 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
1C14F71D23E4371602065522 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
252A83CE6862573BB856ED8E /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
29812C17FFBE7DBBC7203981 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
29812C17FFBE7DBBC7203981 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
2D2457F8B2E6EF9C0F935035 /* Pods-NotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.profile.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianNotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
3A1C47BD29CC6AC2587D4DBE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
3A1C47BD29CC6AC2587D4DBE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||||
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
|
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianNotificationService.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
73D4264A2DEB815D006C0AAE /* NotifyDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NotifyDelegate.swift; sourceTree = "<group>"; };
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||||
|
8B40620B1EEBB09456406A3C /* Pods-SolianNotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.profile.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -66,10 +94,50 @@
|
|||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||||
9AE244813FCDFAA941430393 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
9AE244813FCDFAA941430393 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||||
A499FDB2082EB000933AA8C5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
A499FDB2082EB000933AA8C5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
|
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
B93771F2A63E4148DC6142F7 /* Pods-SolianNotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.release.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
E6B10A9A85BECA2E576C91FF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
E6B10A9A85BECA2E576C91FF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
F6D834CA86410B09796B312B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
F6D834CA86410B09796B312B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
F830F535CB92E3F2E1653A11 /* Pods-SolianNotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.debug.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
/* End PBXFileReference section */
|
/* End PBXFileReference section */
|
||||||
|
|
||||||
|
/* Begin PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
73CDD6822DEC00480059D95D /* Exceptions for "SolianNotificationService" folder in "SolianNotificationService" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
Info.plist,
|
||||||
|
);
|
||||||
|
target = 73CDD6792DEC00480059D95D /* SolianNotificationService */;
|
||||||
|
};
|
||||||
|
73CDD68E2DEC00BE0059D95D /* Exceptions for "Services" folder in "SolianNotificationService" target */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedBuildFileExceptionSet;
|
||||||
|
membershipExceptions = (
|
||||||
|
CloudFile.swift,
|
||||||
|
DataExchange.swift,
|
||||||
|
);
|
||||||
|
target = 73CDD6792DEC00480059D95D /* SolianNotificationService */;
|
||||||
|
};
|
||||||
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
73268D272DEB012A0076E970 /* Services */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
73CDD68E2DEC00BE0059D95D /* Exceptions for "Services" folder in "SolianNotificationService" target */,
|
||||||
|
);
|
||||||
|
path = Services;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
73CDD67B2DEC00480059D95D /* SolianNotificationService */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
exceptions = (
|
||||||
|
73CDD6822DEC00480059D95D /* Exceptions for "SolianNotificationService" folder in "SolianNotificationService" target */,
|
||||||
|
);
|
||||||
|
path = SolianNotificationService;
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
|
/* End PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
|
||||||
/* Begin PBXFrameworksBuildPhase section */
|
/* Begin PBXFrameworksBuildPhase section */
|
||||||
1DFF8FEBBD0CF5A990600776 /* Frameworks */ = {
|
1DFF8FEBBD0CF5A990600776 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
@@ -79,6 +147,14 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
73CDD6772DEC00480059D95D /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
D1772CE196985AE8E8C9F2E5 /* Pods_SolianNotificationService.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -103,6 +179,8 @@
|
|||||||
children = (
|
children = (
|
||||||
F6D834CA86410B09796B312B /* Pods_Runner.framework */,
|
F6D834CA86410B09796B312B /* Pods_Runner.framework */,
|
||||||
29812C17FFBE7DBBC7203981 /* Pods_RunnerTests.framework */,
|
29812C17FFBE7DBBC7203981 /* Pods_RunnerTests.framework */,
|
||||||
|
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */,
|
||||||
|
39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -116,6 +194,12 @@
|
|||||||
14DFD79BE7C26E51B117583C /* Pods-RunnerTests.debug.xcconfig */,
|
14DFD79BE7C26E51B117583C /* Pods-RunnerTests.debug.xcconfig */,
|
||||||
14118AC858B441AB16B7309E /* Pods-RunnerTests.release.xcconfig */,
|
14118AC858B441AB16B7309E /* Pods-RunnerTests.release.xcconfig */,
|
||||||
E6B10A9A85BECA2E576C91FF /* Pods-RunnerTests.profile.xcconfig */,
|
E6B10A9A85BECA2E576C91FF /* Pods-RunnerTests.profile.xcconfig */,
|
||||||
|
192FDACE67D7CB6AED15C634 /* Pods-NotificationService.debug.xcconfig */,
|
||||||
|
252A83CE6862573BB856ED8E /* Pods-NotificationService.release.xcconfig */,
|
||||||
|
2D2457F8B2E6EF9C0F935035 /* Pods-NotificationService.profile.xcconfig */,
|
||||||
|
F830F535CB92E3F2E1653A11 /* Pods-SolianNotificationService.debug.xcconfig */,
|
||||||
|
B93771F2A63E4148DC6142F7 /* Pods-SolianNotificationService.release.xcconfig */,
|
||||||
|
8B40620B1EEBB09456406A3C /* Pods-SolianNotificationService.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -136,6 +220,7 @@
|
|||||||
children = (
|
children = (
|
||||||
9740EEB11CF90186004384FC /* Flutter */,
|
9740EEB11CF90186004384FC /* Flutter */,
|
||||||
97C146F01CF9000F007C117D /* Runner */,
|
97C146F01CF9000F007C117D /* Runner */,
|
||||||
|
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
91E124CE95BCB4DCD890160D /* Pods */,
|
91E124CE95BCB4DCD890160D /* Pods */,
|
||||||
@@ -149,6 +234,7 @@
|
|||||||
children = (
|
children = (
|
||||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||||
|
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -156,6 +242,7 @@
|
|||||||
97C146F01CF9000F007C117D /* Runner */ = {
|
97C146F01CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXGroup;
|
isa = PBXGroup;
|
||||||
children = (
|
children = (
|
||||||
|
73268D272DEB012A0076E970 /* Services */,
|
||||||
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */,
|
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */,
|
||||||
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
97C146FA1CF9000F007C117D /* Main.storyboard */,
|
||||||
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
97C146FD1CF9000F007C117D /* Assets.xcassets */,
|
||||||
@@ -165,6 +252,7 @@
|
|||||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||||
|
73D4264A2DEB815D006C0AAE /* NotifyDelegate.swift */,
|
||||||
);
|
);
|
||||||
path = Runner;
|
path = Runner;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -191,6 +279,27 @@
|
|||||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.unit-test";
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
};
|
};
|
||||||
|
73CDD6792DEC00480059D95D /* SolianNotificationService */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 73CDD6832DEC00480059D95D /* Build configuration list for PBXNativeTarget "SolianNotificationService" */;
|
||||||
|
buildPhases = (
|
||||||
|
5FC5C1EF9F17B7166B432FF2 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
73CDD6762DEC00480059D95D /* Sources */,
|
||||||
|
73CDD6772DEC00480059D95D /* Frameworks */,
|
||||||
|
73CDD6782DEC00480059D95D /* Resources */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
||||||
|
);
|
||||||
|
name = SolianNotificationService;
|
||||||
|
productName = SolianNotificationService;
|
||||||
|
productReference = 73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */;
|
||||||
|
productType = "com.apple.product-type.app-extension";
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||||
@@ -199,6 +308,7 @@
|
|||||||
9740EEB61CF901F6004384FC /* Run Script */,
|
9740EEB61CF901F6004384FC /* Run Script */,
|
||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
|
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
@@ -208,6 +318,10 @@
|
|||||||
buildRules = (
|
buildRules = (
|
||||||
);
|
);
|
||||||
dependencies = (
|
dependencies = (
|
||||||
|
73CDD6802DEC00480059D95D /* PBXTargetDependency */,
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
73268D272DEB012A0076E970 /* Services */,
|
||||||
);
|
);
|
||||||
name = Runner;
|
name = Runner;
|
||||||
productName = Runner;
|
productName = Runner;
|
||||||
@@ -221,6 +335,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = YES;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
|
LastSwiftUpdateCheck = 1640;
|
||||||
LastUpgradeCheck = 1510;
|
LastUpgradeCheck = 1510;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
@@ -228,6 +343,9 @@
|
|||||||
CreatedOnToolsVersion = 14.0;
|
CreatedOnToolsVersion = 14.0;
|
||||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||||
};
|
};
|
||||||
|
73CDD6792DEC00480059D95D = {
|
||||||
|
CreatedOnToolsVersion = 16.4;
|
||||||
|
};
|
||||||
97C146ED1CF9000F007C117D = {
|
97C146ED1CF9000F007C117D = {
|
||||||
CreatedOnToolsVersion = 7.3.1;
|
CreatedOnToolsVersion = 7.3.1;
|
||||||
LastSwiftMigration = 1100;
|
LastSwiftMigration = 1100;
|
||||||
@@ -235,7 +353,6 @@
|
|||||||
};
|
};
|
||||||
};
|
};
|
||||||
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
buildConfigurationList = 97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */;
|
||||||
compatibilityVersion = "Xcode 9.3";
|
|
||||||
developmentRegion = en;
|
developmentRegion = en;
|
||||||
hasScannedForEncodings = 0;
|
hasScannedForEncodings = 0;
|
||||||
knownRegions = (
|
knownRegions = (
|
||||||
@@ -243,12 +360,14 @@
|
|||||||
Base,
|
Base,
|
||||||
);
|
);
|
||||||
mainGroup = 97C146E51CF9000F007C117D;
|
mainGroup = 97C146E51CF9000F007C117D;
|
||||||
|
preferredProjectObjectVersion = 77;
|
||||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||||
projectDirPath = "";
|
projectDirPath = "";
|
||||||
projectRoot = "";
|
projectRoot = "";
|
||||||
targets = (
|
targets = (
|
||||||
97C146ED1CF9000F007C117D /* Runner */,
|
97C146ED1CF9000F007C117D /* Runner */,
|
||||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||||
|
73CDD6792DEC00480059D95D /* SolianNotificationService */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -261,6 +380,13 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
73CDD6782DEC00480059D95D /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -331,6 +457,28 @@
|
|||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||||
showEnvVarsInLog = 0;
|
showEnvVarsInLog = 0;
|
||||||
};
|
};
|
||||||
|
5FC5C1EF9F17B7166B432FF2 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-SolianNotificationService-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
8C0351B03869BBF493808288 /* [CP] Embed Pods Frameworks */ = {
|
8C0351B03869BBF493808288 /* [CP] Embed Pods Frameworks */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -396,12 +544,20 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
73CDD6762DEC00480059D95D /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||||
|
73D4264B2DEB815D006C0AAE /* NotifyDelegate.swift in Sources */,
|
||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
@@ -413,6 +569,11 @@
|
|||||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||||
};
|
};
|
||||||
|
73CDD6802DEC00480059D95D /* PBXTargetDependency */ = {
|
||||||
|
isa = PBXTargetDependency;
|
||||||
|
target = 73CDD6792DEC00480059D95D /* SolianNotificationService */;
|
||||||
|
targetProxy = 73CDD67F2DEC00480059D95D /* PBXContainerItemProxy */;
|
||||||
|
};
|
||||||
/* End PBXTargetDependency section */
|
/* End PBXTargetDependency section */
|
||||||
|
|
||||||
/* Begin PBXVariantGroup section */
|
/* Begin PBXVariantGroup section */
|
||||||
@@ -498,6 +659,7 @@
|
|||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -561,6 +723,123 @@
|
|||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
73CDD6842DEC00480059D95D /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = F830F535CB92E3F2E1653A11 /* Pods-SolianNotificationService.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = SolianNotificationService/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianNotificationService;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
73CDD6852DEC00480059D95D /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = B93771F2A63E4148DC6142F7 /* Pods-SolianNotificationService.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = SolianNotificationService/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianNotificationService;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
73CDD6862DEC00480059D95D /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 8B40620B1EEBB09456406A3C /* Pods-SolianNotificationService.profile.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = YES;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_FILE = SolianNotificationService/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = SolianNotificationService;
|
||||||
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 18.5;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
"@executable_path/../../Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianNotificationService;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
97C147031CF9000F007C117D /* Debug */ = {
|
97C147031CF9000F007C117D /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
@@ -683,6 +962,7 @@
|
|||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -708,6 +988,7 @@
|
|||||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
ENABLE_BITCODE = NO;
|
ENABLE_BITCODE = NO;
|
||||||
INFOPLIST_FILE = Runner/Info.plist;
|
INFOPLIST_FILE = Runner/Info.plist;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
@@ -734,6 +1015,16 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
73CDD6832DEC00480059D95D /* Build configuration list for PBXNativeTarget "SolianNotificationService" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
73CDD6842DEC00480059D95D /* Debug */,
|
||||||
|
73CDD6852DEC00480059D95D /* Release */,
|
||||||
|
73CDD6862DEC00480059D95D /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|||||||
@@ -26,6 +26,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
shouldUseLaunchSchemeArgsEnv = "YES">
|
shouldUseLaunchSchemeArgsEnv = "YES">
|
||||||
<MacroExpansion>
|
<MacroExpansion>
|
||||||
<BuildableReference
|
<BuildableReference
|
||||||
@@ -54,6 +55,7 @@
|
|||||||
buildConfiguration = "Debug"
|
buildConfiguration = "Debug"
|
||||||
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
|
||||||
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
|
||||||
|
customLLDBInitFile = "$(SRCROOT)/Flutter/ephemeral/flutter_lldbinit"
|
||||||
launchStyle = "0"
|
launchStyle = "0"
|
||||||
useCustomWorkingDirectory = "NO"
|
useCustomWorkingDirectory = "NO"
|
||||||
ignoresPersistentStateOnLaunch = "NO"
|
ignoresPersistentStateOnLaunch = "NO"
|
||||||
|
|||||||
@@ -3,11 +3,15 @@ import UIKit
|
|||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
|
let notifyDelegate = NotifyDelegate()
|
||||||
|
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||||
) -> Bool {
|
) -> Bool {
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
UNUserNotificationCenter.current().delegate = notifyDelegate
|
||||||
|
|
||||||
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,67 +1,75 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
<plist version="1.0">
|
<plist version="1.0">
|
||||||
<dict>
|
<dict>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>ITSAppUsesNonExemptEncryption</key>
|
||||||
<true/>
|
<false/>
|
||||||
<key>CFBundleDevelopmentRegion</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
<true/>
|
||||||
<key>CFBundleDisplayName</key>
|
<key>CFBundleDevelopmentRegion</key>
|
||||||
<string>Island</string>
|
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||||
<key>CFBundleExecutable</key>
|
<key>CFBundleDisplayName</key>
|
||||||
<string>$(EXECUTABLE_NAME)</string>
|
<string>Solian</string>
|
||||||
<key>CFBundleIdentifier</key>
|
<key>CFBundleExecutable</key>
|
||||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
<string>$(EXECUTABLE_NAME)</string>
|
||||||
<key>CFBundleInfoDictionaryVersion</key>
|
<key>CFBundleIdentifier</key>
|
||||||
<string>6.0</string>
|
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
<key>CFBundleName</key>
|
<key>CFBundleInfoDictionaryVersion</key>
|
||||||
<string>island</string>
|
<string>6.0</string>
|
||||||
<key>CFBundlePackageType</key>
|
<key>CFBundleName</key>
|
||||||
<string>APPL</string>
|
<string>solian</string>
|
||||||
<key>CFBundleShortVersionString</key>
|
<key>CFBundlePackageType</key>
|
||||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
<string>APPL</string>
|
||||||
<key>CFBundleSignature</key>
|
<key>CFBundleShortVersionString</key>
|
||||||
<string>????</string>
|
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleSignature</key>
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>????</string>
|
||||||
<key>LSRequiresIPhoneOS</key>
|
<key>CFBundleVersion</key>
|
||||||
<true/>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
<key>LSRequiresIPhoneOS</key>
|
||||||
<true/>
|
<true/>
|
||||||
<key>UIBackgroundModes</key>
|
<key>NSCalendarsUsageDescription</key>
|
||||||
<array>
|
<string>Grant access to Calander help us to shows Solar Calander with your own events.</string>
|
||||||
<string>fetch</string>
|
<key>NSCameraUsageDescription</key>
|
||||||
<string>audio</string>
|
<string>Grant access to Camera will allow Solian take photo or video for your post.</string>
|
||||||
<string>remote-notification</string>
|
<key>NSMicrophoneUsageDescription</key>
|
||||||
</array>
|
<string>Grant access to Microphone will allow Solian record audio for your post.</string>
|
||||||
<key>UILaunchStoryboardName</key>
|
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||||
<string>LaunchScreen</string>
|
<string>Grant access to Photo Library will allow Solian download photo to album for you.</string>
|
||||||
<key>UIMainStoryboardFile</key>
|
<key>NSPhotoLibraryUsageDescription</key>
|
||||||
<string>Main</string>
|
<string>Grant access to Photo Library will allow Solian upload photo or video for your post.</string>
|
||||||
<key>UISupportedInterfaceOrientations</key>
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
<array>
|
<true/>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
<key>UIBackgroundModes</key>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<array>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<string>fetch</string>
|
||||||
</array>
|
<string>audio</string>
|
||||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
<string>remote-notification</string>
|
||||||
<array>
|
<string>voip</string>
|
||||||
<string>UIInterfaceOrientationPortrait</string>
|
</array>
|
||||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
<key>UILaunchStoryboardName</key>
|
||||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
<string>LaunchScreen</string>
|
||||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
<key>UIMainStoryboardFile</key>
|
||||||
</array>
|
<string>Main</string>
|
||||||
<key>NSCalendarsUsageDescription</key>
|
<key>UIStatusBarHidden</key>
|
||||||
<string>Grant access to Calander help us to shows Solar Calander with your own events.</string>
|
<false/>
|
||||||
<key>NSCameraUsageDescription</key>
|
<key>UISupportedInterfaceOrientations</key>
|
||||||
<string>Grant access to Camera will allow Solian take photo or video for your post.</string>
|
<array>
|
||||||
<key>NSMicrophoneUsageDescription</key>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<string>Grant access to Microphone will allow Solian record audio for your post.</string>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
<string>Grant access to Photo Library will allow Solian download photo to album for you.</string>
|
</array>
|
||||||
<key>NSPhotoLibraryUsageDescription</key>
|
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||||
<string>Grant access to Photo Library will allow Solian upload photo or video for your post.</string>
|
<array>
|
||||||
<key>UIStatusBarHidden</key>
|
<string>UIInterfaceOrientationPortrait</string>
|
||||||
<false/>
|
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||||
</dict>
|
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||||
|
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||||
|
</array>
|
||||||
|
<key>NSUserActivityTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>INStartCallIntent</string>
|
||||||
|
<string>INSendMessageIntent</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@@ -1,153 +0,0 @@
|
|||||||
//
|
|
||||||
// BlurHashDecoder.swift
|
|
||||||
// Runner
|
|
||||||
//
|
|
||||||
// Created by LittleSheep on 2025/4/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
|
|
||||||
extension UIImage {
|
|
||||||
public convenience init?(blurHash: String, size: CGSize, punch: Float = 1) {
|
|
||||||
guard blurHash.count >= 6 else { return nil }
|
|
||||||
|
|
||||||
let sizeFlag = String(blurHash[0]).decode83()
|
|
||||||
let numY = (sizeFlag / 9) + 1
|
|
||||||
let numX = (sizeFlag % 9) + 1
|
|
||||||
|
|
||||||
let quantisedMaximumValue = String(blurHash[1]).decode83()
|
|
||||||
let maximumValue = Float(quantisedMaximumValue + 1) / 166
|
|
||||||
|
|
||||||
guard blurHash.count == 4 + 2 * numX * numY else { return nil }
|
|
||||||
|
|
||||||
let colours: [(Float, Float, Float)] = (0 ..< numX * numY).map { i in
|
|
||||||
if i == 0 {
|
|
||||||
let value = String(blurHash[2 ..< 6]).decode83()
|
|
||||||
return decodeDC(value)
|
|
||||||
} else {
|
|
||||||
let value = String(blurHash[4 + i * 2 ..< 4 + i * 2 + 2]).decode83()
|
|
||||||
return decodeAC(value, maximumValue: maximumValue * punch)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let width = Int(size.width)
|
|
||||||
let height = Int(size.height)
|
|
||||||
let bytesPerRow = width * 3
|
|
||||||
guard let data = CFDataCreateMutable(kCFAllocatorDefault, bytesPerRow * height) else { return nil }
|
|
||||||
CFDataSetLength(data, bytesPerRow * height)
|
|
||||||
guard let pixels = CFDataGetMutableBytePtr(data) else { return nil }
|
|
||||||
|
|
||||||
for y in 0 ..< height {
|
|
||||||
for x in 0 ..< width {
|
|
||||||
var r: Float = 0
|
|
||||||
var g: Float = 0
|
|
||||||
var b: Float = 0
|
|
||||||
|
|
||||||
for j in 0 ..< numY {
|
|
||||||
for i in 0 ..< numX {
|
|
||||||
let basis = cos(Float.pi * Float(x) * Float(i) / Float(width)) * cos(Float.pi * Float(y) * Float(j) / Float(height))
|
|
||||||
let colour = colours[i + j * numX]
|
|
||||||
r += colour.0 * basis
|
|
||||||
g += colour.1 * basis
|
|
||||||
b += colour.2 * basis
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let intR = UInt8(linearTosRGB(r))
|
|
||||||
let intG = UInt8(linearTosRGB(g))
|
|
||||||
let intB = UInt8(linearTosRGB(b))
|
|
||||||
|
|
||||||
pixels[3 * x + 0 + y * bytesPerRow] = intR
|
|
||||||
pixels[3 * x + 1 + y * bytesPerRow] = intG
|
|
||||||
pixels[3 * x + 2 + y * bytesPerRow] = intB
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
let bitmapInfo = CGBitmapInfo(rawValue: CGImageAlphaInfo.none.rawValue)
|
|
||||||
|
|
||||||
guard let provider = CGDataProvider(data: data) else { return nil }
|
|
||||||
guard let cgImage = CGImage(width: width, height: height, bitsPerComponent: 8, bitsPerPixel: 24, bytesPerRow: bytesPerRow,
|
|
||||||
space: CGColorSpaceCreateDeviceRGB(), bitmapInfo: bitmapInfo, provider: provider, decode: nil, shouldInterpolate: true, intent: .defaultIntent) else { return nil }
|
|
||||||
|
|
||||||
self.init(cgImage: cgImage)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private func decodeDC(_ value: Int) -> (Float, Float, Float) {
|
|
||||||
let intR = value >> 16
|
|
||||||
let intG = (value >> 8) & 255
|
|
||||||
let intB = value & 255
|
|
||||||
return (sRGBToLinear(intR), sRGBToLinear(intG), sRGBToLinear(intB))
|
|
||||||
}
|
|
||||||
|
|
||||||
private func decodeAC(_ value: Int, maximumValue: Float) -> (Float, Float, Float) {
|
|
||||||
let quantR = value / (19 * 19)
|
|
||||||
let quantG = (value / 19) % 19
|
|
||||||
let quantB = value % 19
|
|
||||||
|
|
||||||
let rgb = (
|
|
||||||
signPow((Float(quantR) - 9) / 9, 2) * maximumValue,
|
|
||||||
signPow((Float(quantG) - 9) / 9, 2) * maximumValue,
|
|
||||||
signPow((Float(quantB) - 9) / 9, 2) * maximumValue
|
|
||||||
)
|
|
||||||
|
|
||||||
return rgb
|
|
||||||
}
|
|
||||||
|
|
||||||
private func signPow(_ value: Float, _ exp: Float) -> Float {
|
|
||||||
return copysign(pow(abs(value), exp), value)
|
|
||||||
}
|
|
||||||
|
|
||||||
private func linearTosRGB(_ value: Float) -> Int {
|
|
||||||
let v = max(0, min(1, value))
|
|
||||||
if v <= 0.0031308 { return Int(v * 12.92 * 255 + 0.5) }
|
|
||||||
else { return Int((1.055 * pow(v, 1 / 2.4) - 0.055) * 255 + 0.5) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private func sRGBToLinear<Type: BinaryInteger>(_ value: Type) -> Float {
|
|
||||||
let v = Float(Int64(value)) / 255
|
|
||||||
if v <= 0.04045 { return v / 12.92 }
|
|
||||||
else { return pow((v + 0.055) / 1.055, 2.4) }
|
|
||||||
}
|
|
||||||
|
|
||||||
private let encodeCharacters: [String] = {
|
|
||||||
return "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz#$%*+,-.:;=?@[]^_{|}~".map { String($0) }
|
|
||||||
}()
|
|
||||||
|
|
||||||
private let decodeCharacters: [String: Int] = {
|
|
||||||
var dict: [String: Int] = [:]
|
|
||||||
for (index, character) in encodeCharacters.enumerated() {
|
|
||||||
dict[character] = index
|
|
||||||
}
|
|
||||||
return dict
|
|
||||||
}()
|
|
||||||
|
|
||||||
extension String {
|
|
||||||
func decode83() -> Int {
|
|
||||||
var value: Int = 0
|
|
||||||
for character in self {
|
|
||||||
if let digit = decodeCharacters[String(character)] {
|
|
||||||
value = value * 83 + digit
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return value
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private extension String {
|
|
||||||
subscript (offset: Int) -> Character {
|
|
||||||
return self[index(startIndex, offsetBy: offset)]
|
|
||||||
}
|
|
||||||
|
|
||||||
subscript (bounds: CountableClosedRange<Int>) -> Substring {
|
|
||||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
|
||||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
|
||||||
return self[start...end]
|
|
||||||
}
|
|
||||||
|
|
||||||
subscript (bounds: CountableRange<Int>) -> Substring {
|
|
||||||
let start = index(startIndex, offsetBy: bounds.lowerBound)
|
|
||||||
let end = index(startIndex, offsetBy: bounds.upperBound)
|
|
||||||
return self[start..<end]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,42 +0,0 @@
|
|||||||
//
|
|
||||||
// ImageView.swift
|
|
||||||
// Runner
|
|
||||||
//
|
|
||||||
// Created by LittleSheep on 2025/4/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
import UIKit
|
|
||||||
import Kingfisher
|
|
||||||
|
|
||||||
class ImageView: UIImageView {
|
|
||||||
private var _size: CGSize = CGSize(width: 0, height: 0)
|
|
||||||
|
|
||||||
// Initialize the image view
|
|
||||||
override init(frame: CGRect) {
|
|
||||||
super.init(frame: frame)
|
|
||||||
contentMode = .scaleAspectFill
|
|
||||||
clipsToBounds = true
|
|
||||||
}
|
|
||||||
|
|
||||||
required init?(coder: NSCoder) {
|
|
||||||
super.init(coder: coder)
|
|
||||||
contentMode = .scaleAspectFill
|
|
||||||
clipsToBounds = true
|
|
||||||
}
|
|
||||||
|
|
||||||
// Method to set the image from a URL using Kingfisher
|
|
||||||
func setImage(from url: URL, blurHash: String?) {
|
|
||||||
let placeholderImage = blurHash != nil ? UIImage.init(blurHash: blurHash!, size: _size) : nil
|
|
||||||
let processor = DownsamplingImageProcessor(size: _size) |> RoundCornerImageProcessor(cornerRadius: 20)
|
|
||||||
|
|
||||||
self.kf.indicatorType = .activity
|
|
||||||
self.kf.setImage(
|
|
||||||
with: url,
|
|
||||||
placeholder: placeholderImage,
|
|
||||||
options: [
|
|
||||||
.processor(processor),
|
|
||||||
.transition(.fade(0.3))
|
|
||||||
]
|
|
||||||
)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
//
|
|
||||||
// NativeImage.swift
|
|
||||||
// Runner
|
|
||||||
//
|
|
||||||
// Created by LittleSheep on 2025/4/21.
|
|
||||||
//
|
|
||||||
|
|
||||||
import Flutter
|
|
||||||
import UIKit
|
|
||||||
import Kingfisher
|
|
||||||
|
|
||||||
class FLNativeImageFactory : NSObject, FlutterPlatformViewFactory {
|
|
||||||
private var messenger: FlutterBinaryMessenger
|
|
||||||
|
|
||||||
init(messenger: FlutterBinaryMessenger) {
|
|
||||||
self.messenger = messenger
|
|
||||||
super.init()
|
|
||||||
}
|
|
||||||
|
|
||||||
func create(
|
|
||||||
withFrame frame: CGRect,
|
|
||||||
viewIdentifier viewId: Int64,
|
|
||||||
arguments args: Any?
|
|
||||||
) -> FlutterPlatformView {
|
|
||||||
return FLNativeImage(
|
|
||||||
frame: frame,
|
|
||||||
viewIdentifier: viewId,
|
|
||||||
arguments: args,
|
|
||||||
binaryMessenger: messenger)
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Implementing this method is only necessary when the `arguments` in `createWithFrame` is not `nil`.
|
|
||||||
public func createArgsCodec() -> FlutterMessageCodec & NSObjectProtocol {
|
|
||||||
return FlutterStandardMessageCodec.sharedInstance()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class FLNativeImage : NSObject, FlutterPlatformView {
|
|
||||||
private var _view: ImageView
|
|
||||||
|
|
||||||
init(
|
|
||||||
frame: CGRect,
|
|
||||||
viewIdentifier viewId: Int64,
|
|
||||||
arguments args: Any?,
|
|
||||||
binaryMessenger messenger: FlutterBinaryMessenger?
|
|
||||||
) {
|
|
||||||
_view = ImageView(frame: frame)
|
|
||||||
super.init()
|
|
||||||
|
|
||||||
let argsMap = args as! [AnyHashable: Any]
|
|
||||||
let source = argsMap["src"] as! String
|
|
||||||
let blurHash = argsMap["blur"] as? String
|
|
||||||
|
|
||||||
if let url = URL(string: source) {
|
|
||||||
_view.setImage(from: url, blurHash: blurHash)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func view() -> UIView {
|
|
||||||
return _view
|
|
||||||
}
|
|
||||||
}
|
|
||||||
49
ios/Runner/NotifyDelegate.swift
Normal file
49
ios/Runner/NotifyDelegate.swift
Normal file
@@ -0,0 +1,49 @@
|
|||||||
|
//
|
||||||
|
// NotifyDelegate.swift
|
||||||
|
// Runner
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/6/1.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Alamofire
|
||||||
|
|
||||||
|
class NotifyDelegate: UIResponder, UNUserNotificationCenterDelegate {
|
||||||
|
func userNotificationCenter(_ center: UNUserNotificationCenter, didReceive response: UNNotificationResponse, withCompletionHandler completionHandler: @escaping () -> Void) {
|
||||||
|
if let textResponse = response as? UNTextInputNotificationResponse {
|
||||||
|
let content = response.notification.request.content
|
||||||
|
guard let metadata = content.userInfo["meta"] as? [AnyHashable: Any] else {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
var token: String? = UserDefaults.standard.getFlutterToken()
|
||||||
|
if token == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let serverUrl = UserDefaults.standard.getServerUrl()
|
||||||
|
let url = "\(serverUrl)/chat/\(metadata["room_id"] ?? "")/messages"
|
||||||
|
|
||||||
|
let parameters: [String: Any?] = [
|
||||||
|
"content": textResponse.userText,
|
||||||
|
"replied_message_id": metadata["message_id"]
|
||||||
|
]
|
||||||
|
|
||||||
|
AF.request(url, method: .post, parameters: parameters, encoding: JSONEncoding.default, headers: HTTPHeaders(
|
||||||
|
[HTTPHeader(name: "Authorization", value: "AtField \(token!)")]
|
||||||
|
))
|
||||||
|
.validate()
|
||||||
|
.responseString { response in
|
||||||
|
switch response.result {
|
||||||
|
case .success(_):
|
||||||
|
break
|
||||||
|
case .failure(let error):
|
||||||
|
print("Failed to send chat reply message: \(error)")
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
completionHandler()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,5 +4,7 @@
|
|||||||
<dict>
|
<dict>
|
||||||
<key>aps-environment</key>
|
<key>aps-environment</key>
|
||||||
<string>development</string>
|
<string>development</string>
|
||||||
|
<key>com.apple.developer.usernotifications.communication</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
14
ios/Runner/Services/CloudFile.swift
Normal file
14
ios/Runner/Services/CloudFile.swift
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
//
|
||||||
|
// CloudFile.swift
|
||||||
|
// Runner
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/5/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
func getAttachmentUrl(for identifier: String) -> String {
|
||||||
|
let serverBaseUrl = "https://nt.solian.app"
|
||||||
|
|
||||||
|
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/files/\(identifier)"
|
||||||
|
}
|
||||||
31
ios/Runner/Services/DataExchange.swift
Normal file
31
ios/Runner/Services/DataExchange.swift
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
//
|
||||||
|
// DataExchange.swift
|
||||||
|
// Runner
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/6/2.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
extension UserDefaults {
|
||||||
|
func getFlutterValue<T>(forKey key: String) -> T? {
|
||||||
|
let prefixedKey = "flutter.\(key)"
|
||||||
|
return self.object(forKey: prefixedKey) as? T
|
||||||
|
}
|
||||||
|
|
||||||
|
func getFlutterToken(forKey key: String = "dyn_user_tk") -> String? {
|
||||||
|
let prefixedKey = "flutter.\(key)"
|
||||||
|
guard let jsonString = self.string(forKey: prefixedKey),
|
||||||
|
let data = jsonString.data(using: .utf8),
|
||||||
|
let jsonObject = try? JSONSerialization.jsonObject(with: data),
|
||||||
|
let jsonDict = jsonObject as? [String: Any],
|
||||||
|
let token = jsonDict["token"] as? String else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
return token
|
||||||
|
}
|
||||||
|
|
||||||
|
func getServerUrl(forKey key: String = "app_server_url") -> String {
|
||||||
|
return self.getFlutterValue(forKey: key) ?? "https://nt.solian.app"
|
||||||
|
}
|
||||||
|
}
|
||||||
18
ios/SolianNotificationService/Info.plist
Normal file
18
ios/SolianNotificationService/Info.plist
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||||
|
<plist version="1.0">
|
||||||
|
<dict>
|
||||||
|
<key>NSUserActivityTypes</key>
|
||||||
|
<array>
|
||||||
|
<string>INStartCallIntent</string>
|
||||||
|
<string>INSendMessageIntent</string>
|
||||||
|
</array>
|
||||||
|
<key>NSExtension</key>
|
||||||
|
<dict>
|
||||||
|
<key>NSExtensionPointIdentifier</key>
|
||||||
|
<string>com.apple.usernotifications.service</string>
|
||||||
|
<key>NSExtensionPrincipalClass</key>
|
||||||
|
<string>$(PRODUCT_MODULE_NAME).NotificationService</string>
|
||||||
|
</dict>
|
||||||
|
</dict>
|
||||||
|
</plist>
|
||||||
221
ios/SolianNotificationService/NotificationService.swift
Normal file
221
ios/SolianNotificationService/NotificationService.swift
Normal file
@@ -0,0 +1,221 @@
|
|||||||
|
//
|
||||||
|
// NotificationService.swift
|
||||||
|
// NotificationService
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/5/31.
|
||||||
|
//
|
||||||
|
|
||||||
|
import UserNotifications
|
||||||
|
import Intents
|
||||||
|
import Kingfisher
|
||||||
|
import UniformTypeIdentifiers
|
||||||
|
|
||||||
|
enum ParseNotificationPayloadError: Error {
|
||||||
|
case missingMetadata(String)
|
||||||
|
case missingAvatarUrl(String)
|
||||||
|
}
|
||||||
|
|
||||||
|
class NotificationService: UNNotificationServiceExtension {
|
||||||
|
|
||||||
|
private var contentHandler: ((UNNotificationContent) -> Void)?
|
||||||
|
private var bestAttemptContent: UNMutableNotificationContent?
|
||||||
|
|
||||||
|
override func didReceive(
|
||||||
|
_ request: UNNotificationRequest,
|
||||||
|
withContentHandler contentHandler: @escaping (UNNotificationContent) -> Void
|
||||||
|
) {
|
||||||
|
self.contentHandler = contentHandler
|
||||||
|
guard let bestAttemptContent = request.content.mutableCopy() as? UNMutableNotificationContent else {
|
||||||
|
contentHandler(request.content)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self.bestAttemptContent = bestAttemptContent
|
||||||
|
|
||||||
|
do {
|
||||||
|
try processNotification(request: request, content: bestAttemptContent)
|
||||||
|
} catch {
|
||||||
|
contentHandler(bestAttemptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override func serviceExtensionTimeWillExpire() {
|
||||||
|
if let contentHandler = contentHandler, let bestAttemptContent = bestAttemptContent {
|
||||||
|
contentHandler(bestAttemptContent)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func processNotification(request: UNNotificationRequest, content: UNMutableNotificationContent) throws {
|
||||||
|
switch content.userInfo["type"] as? String {
|
||||||
|
case "messages.new":
|
||||||
|
try handleMessagingNotification(request: request, content: content)
|
||||||
|
default:
|
||||||
|
try handleDefaultNotification(content: content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleMessagingNotification(request: UNNotificationRequest, content: UNMutableNotificationContent) throws {
|
||||||
|
guard let meta = content.userInfo["meta"] as? [AnyHashable: Any] else {
|
||||||
|
throw ParseNotificationPayloadError.missingMetadata("The notification has no meta.")
|
||||||
|
}
|
||||||
|
|
||||||
|
let pfpIdentifier = meta["pfp"] as? String
|
||||||
|
|
||||||
|
let replyableMessageCategory = UNNotificationCategory(
|
||||||
|
identifier: content.categoryIdentifier,
|
||||||
|
actions: [
|
||||||
|
UNTextInputNotificationAction(
|
||||||
|
identifier: "reply_action",
|
||||||
|
title: "Reply",
|
||||||
|
options: []
|
||||||
|
),
|
||||||
|
],
|
||||||
|
intentIdentifiers: [],
|
||||||
|
options: []
|
||||||
|
)
|
||||||
|
|
||||||
|
UNUserNotificationCenter.current().setNotificationCategories([replyableMessageCategory])
|
||||||
|
content.categoryIdentifier = replyableMessageCategory.identifier
|
||||||
|
|
||||||
|
let metaCopy = meta as? [String: Any] ?? [:]
|
||||||
|
let pfpUrl = pfpIdentifier != nil ? getAttachmentUrl(for: pfpIdentifier!) : nil
|
||||||
|
|
||||||
|
let targetSize = 512
|
||||||
|
let scaleProcessor = ResizingImageProcessor(referenceSize: CGSize(width: targetSize, height: targetSize), mode: .aspectFit)
|
||||||
|
|
||||||
|
KingfisherManager.shared.retrieveImage(with: URL(string: pfpUrl!)!, options: [.processor(scaleProcessor)], completionHandler: { result in
|
||||||
|
var image: Data?
|
||||||
|
switch result {
|
||||||
|
case .success(let value):
|
||||||
|
image = value.image.pngData()
|
||||||
|
case .failure(let error):
|
||||||
|
print("Unable to get pfp url: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
let handle = INPersonHandle(value: "\(metaCopy["user_id"] ?? "")", type: .unknown)
|
||||||
|
let sender = INPerson(
|
||||||
|
personHandle: handle,
|
||||||
|
nameComponents: PersonNameComponents(nickname: "\(metaCopy["sender_name"] ?? "")"),
|
||||||
|
displayName: content.title,
|
||||||
|
image: image == nil ? nil : INImage(imageData: image!),
|
||||||
|
contactIdentifier: nil,
|
||||||
|
customIdentifier: nil
|
||||||
|
)
|
||||||
|
|
||||||
|
let intent = self.createMessageIntent(with: sender, meta: metaCopy, body: content.body)
|
||||||
|
self.donateInteraction(for: intent)
|
||||||
|
let updatedContent = try? request.content.updating(from: intent)
|
||||||
|
self.contentHandler?(updatedContent ?? content)
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
private func handleDefaultNotification(content: UNMutableNotificationContent) throws {
|
||||||
|
guard let meta = content.userInfo["meta"] as? [AnyHashable: Any] else {
|
||||||
|
throw ParseNotificationPayloadError.missingMetadata("The notification has no meta.")
|
||||||
|
}
|
||||||
|
|
||||||
|
if let imageIdentifier = meta["image"] as? String {
|
||||||
|
attachMedia(to: content, withIdentifier: [imageIdentifier], fileType: UTType.webP, doScaleDown: true)
|
||||||
|
} else if let pfpIdentifier = meta["pfp"] as? String {
|
||||||
|
attachMedia(to: content, withIdentifier: [pfpIdentifier], fileType: UTType.webP, doScaleDown: true)
|
||||||
|
} else if let imagesIdentifier = meta["images"] as? Array<String> {
|
||||||
|
attachMedia(to: content, withIdentifier: imagesIdentifier, fileType: UTType.webP, doScaleDown: true)
|
||||||
|
} else {
|
||||||
|
contentHandler?(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func attachMedia(to content: UNMutableNotificationContent, withIdentifier identifier: Array<String>, fileType type: UTType?, doScaleDown scaleDown: Bool = false) {
|
||||||
|
let attachmentUrls = identifier.compactMap { element in
|
||||||
|
return getAttachmentUrl(for: element)
|
||||||
|
}
|
||||||
|
|
||||||
|
guard !attachmentUrls.isEmpty else {
|
||||||
|
print("Invalid URLs for attachments: \(attachmentUrls)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
let targetSize = 512
|
||||||
|
let scaleProcessor = ResizingImageProcessor(referenceSize: CGSize(width: targetSize, height: targetSize), mode: .aspectFit)
|
||||||
|
|
||||||
|
for attachmentUrl in attachmentUrls {
|
||||||
|
guard let remoteUrl = URL(string: attachmentUrl) else {
|
||||||
|
print("Invalid URL for attachment: \(attachmentUrl)")
|
||||||
|
continue // Skip this URL and move to the next one
|
||||||
|
}
|
||||||
|
|
||||||
|
KingfisherManager.shared.retrieveImage(with: remoteUrl, options: scaleDown ? [
|
||||||
|
.processor(scaleProcessor)
|
||||||
|
] : nil) { [weak self] result in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
switch result {
|
||||||
|
case .success(let retrievalResult):
|
||||||
|
// The image is either retrieved from cache or downloaded
|
||||||
|
let tempDirectory = FileManager.default.temporaryDirectory
|
||||||
|
let cachedFileUrl = tempDirectory.appendingPathComponent(UUID().uuidString) // Unique identifier for each file
|
||||||
|
|
||||||
|
do {
|
||||||
|
// Write the image data to a temporary file for UNNotificationAttachment
|
||||||
|
try retrievalResult.image.pngData()?.write(to: cachedFileUrl)
|
||||||
|
self.attachLocalMedia(to: content, fileType: type?.identifier, from: cachedFileUrl, withIdentifier: attachmentUrl)
|
||||||
|
} catch {
|
||||||
|
print("Failed to write media to temporary file: \(error.localizedDescription)")
|
||||||
|
self.contentHandler?(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
case .failure(let error):
|
||||||
|
print("Failed to retrieve image: \(error.localizedDescription)")
|
||||||
|
self.contentHandler?(content)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func attachLocalMedia(to content: UNMutableNotificationContent, fileType type: String?, from localUrl: URL, withIdentifier identifier: String) {
|
||||||
|
do {
|
||||||
|
let attachment = try UNNotificationAttachment(identifier: identifier, url: localUrl, options: [
|
||||||
|
UNNotificationAttachmentOptionsTypeHintKey: type as Any,
|
||||||
|
UNNotificationAttachmentOptionsThumbnailHiddenKey: 0,
|
||||||
|
])
|
||||||
|
content.attachments = [attachment]
|
||||||
|
} catch let error as NSError {
|
||||||
|
// Log detailed error information
|
||||||
|
print("Failed to create attachment from file at \(localUrl.path)")
|
||||||
|
print("Error: \(error.localizedDescription)")
|
||||||
|
|
||||||
|
// Check specific error codes if needed
|
||||||
|
if error.domain == NSCocoaErrorDomain {
|
||||||
|
switch error.code {
|
||||||
|
case NSFileReadNoSuchFileError:
|
||||||
|
print("File does not exist at \(localUrl.path)")
|
||||||
|
case NSFileReadNoPermissionError:
|
||||||
|
print("No permission to read file at \(localUrl.path)")
|
||||||
|
default:
|
||||||
|
print("Unhandled file error: \(error.code)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Call content handler regardless of success or failure
|
||||||
|
self.contentHandler?(content)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func createMessageIntent(with sender: INPerson, meta: [AnyHashable: Any], body: String) -> INSendMessageIntent {
|
||||||
|
INSendMessageIntent(
|
||||||
|
recipients: nil,
|
||||||
|
outgoingMessageType: .outgoingMessageText,
|
||||||
|
content: body,
|
||||||
|
speakableGroupName: meta["room_name"] != nil ? INSpeakableString(spokenPhrase: meta["room_name"] as! String) : nil,
|
||||||
|
conversationIdentifier: "\(meta["room_id"] ?? "")",
|
||||||
|
serviceName: nil,
|
||||||
|
sender: sender,
|
||||||
|
attachments: nil
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func donateInteraction(for intent: INIntent) {
|
||||||
|
let interaction = INInteraction(intent: intent, response: nil)
|
||||||
|
interaction.direction = .incoming
|
||||||
|
interaction.donate(completion: nil)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -186,7 +186,7 @@ class MessageRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<LocalChatMessage> sendMessage(
|
Future<LocalChatMessage> sendMessage(
|
||||||
String atk,
|
String token,
|
||||||
String baseUrl,
|
String baseUrl,
|
||||||
String roomId,
|
String roomId,
|
||||||
String content,
|
String content,
|
||||||
@@ -231,8 +231,8 @@ class MessageRepository {
|
|||||||
for (var idx = 0; idx < attachments.length; idx++) {
|
for (var idx = 0; idx < attachments.length; idx++) {
|
||||||
final cloudFile =
|
final cloudFile =
|
||||||
await putMediaToCloud(
|
await putMediaToCloud(
|
||||||
fileData: attachments[idx].data,
|
fileData: attachments[idx],
|
||||||
atk: atk,
|
atk: token,
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
filename: attachments[idx].data.name ?? 'Post media',
|
filename: attachments[idx].data.name ?? 'Post media',
|
||||||
mimetype:
|
mimetype:
|
||||||
@@ -299,7 +299,7 @@ class MessageRepository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Future<LocalChatMessage> retryMessage(String pendingMessageId) async {
|
Future<LocalChatMessage> retryMessage(String pendingMessageId) async {
|
||||||
final message = pendingMessages[pendingMessageId];
|
final message = await getMessageById(pendingMessageId);
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
throw Exception('Message not found');
|
throw Exception('Message not found');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -85,4 +85,5 @@ class DefaultFirebaseOptions {
|
|||||||
storageBucket: 'solian-0x001.firebasestorage.app',
|
storageBucket: 'solian-0x001.firebasestorage.app',
|
||||||
measurementId: 'G-JD1YEG9D6F',
|
measurementId: 'G-JD1YEG9D6F',
|
||||||
);
|
);
|
||||||
}
|
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@ import 'package:island/pods/websocket.dart';
|
|||||||
import 'package:island/route.dart';
|
import 'package:island/route.dart';
|
||||||
import 'package:island/screens/auth/tabs.dart';
|
import 'package:island/screens/auth/tabs.dart';
|
||||||
import 'package:island/services/notify.dart';
|
import 'package:island/services/notify.dart';
|
||||||
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:relative_time/relative_time.dart';
|
import 'package:relative_time/relative_time.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
@@ -28,11 +29,21 @@ import 'package:flutter_native_splash/flutter_native_splash.dart';
|
|||||||
void main() async {
|
void main() async {
|
||||||
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
final widgetsBinding = WidgetsFlutterBinding.ensureInitialized();
|
||||||
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
|
log(
|
||||||
|
"[SplashScreen] Keeping the flash screen to loading other resources...",
|
||||||
|
);
|
||||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||||
}
|
}
|
||||||
|
|
||||||
await EasyLocalization.ensureInitialized();
|
try {
|
||||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
await EasyLocalization.ensureInitialized();
|
||||||
|
await Firebase.initializeApp(
|
||||||
|
options: DefaultFirebaseOptions.currentPlatform,
|
||||||
|
);
|
||||||
|
log("[SplashScreen] Firebase is ready!");
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
@@ -43,6 +54,7 @@ void main() async {
|
|||||||
appWindow.size = initialSize;
|
appWindow.size = initialSize;
|
||||||
appWindow.alignment = Alignment.center;
|
appWindow.alignment = Alignment.center;
|
||||||
appWindow.show();
|
appWindow.show();
|
||||||
|
log("[SplashScreen] Desktop window is ready!");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -52,10 +64,12 @@ void main() async {
|
|||||||
if (imagePickerImplementation is ImagePickerAndroid) {
|
if (imagePickerImplementation is ImagePickerAndroid) {
|
||||||
imagePickerImplementation.useAndroidPhotoPicker = true;
|
imagePickerImplementation.useAndroidPhotoPicker = true;
|
||||||
}
|
}
|
||||||
|
log("[SplashScreen] Android image picker is ready!");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
if (!kIsWeb && (Platform.isAndroid || Platform.isIOS)) {
|
||||||
FlutterNativeSplash.remove();
|
FlutterNativeSplash.remove();
|
||||||
|
log("[SplashScreen] Now hiding the splash screen...");
|
||||||
}
|
}
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
|
|||||||
@@ -5,18 +5,15 @@ part 'activity.freezed.dart';
|
|||||||
part 'activity.g.dart';
|
part 'activity.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnActivity with _$SnActivity {
|
sealed class SnActivity with _$SnActivity {
|
||||||
const factory SnActivity({
|
const factory SnActivity({
|
||||||
required String id,
|
required String id,
|
||||||
required String type,
|
required String type,
|
||||||
required String resourceIdentifier,
|
required String resourceIdentifier,
|
||||||
required int visibility,
|
|
||||||
required String accountId,
|
|
||||||
required SnAccount account,
|
|
||||||
required dynamic data,
|
required dynamic data,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required dynamic deletedAt,
|
required DateTime? deletedAt,
|
||||||
}) = _SnActivity;
|
}) = _SnActivity;
|
||||||
|
|
||||||
factory SnActivity.fromJson(Map<String, dynamic> json) =>
|
factory SnActivity.fromJson(Map<String, dynamic> json) =>
|
||||||
@@ -24,7 +21,7 @@ abstract class SnActivity with _$SnActivity {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnCheckInResult with _$SnCheckInResult {
|
sealed class SnCheckInResult with _$SnCheckInResult {
|
||||||
const factory SnCheckInResult({
|
const factory SnCheckInResult({
|
||||||
required String id,
|
required String id,
|
||||||
required int level,
|
required int level,
|
||||||
@@ -41,7 +38,7 @@ abstract class SnCheckInResult with _$SnCheckInResult {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnFortuneTip with _$SnFortuneTip {
|
sealed class SnFortuneTip with _$SnFortuneTip {
|
||||||
const factory SnFortuneTip({
|
const factory SnFortuneTip({
|
||||||
required bool isPositive,
|
required bool isPositive,
|
||||||
required String title,
|
required String title,
|
||||||
@@ -53,7 +50,7 @@ abstract class SnFortuneTip with _$SnFortuneTip {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnEventCalendarEntry with _$SnEventCalendarEntry {
|
sealed class SnEventCalendarEntry with _$SnEventCalendarEntry {
|
||||||
const factory SnEventCalendarEntry({
|
const factory SnEventCalendarEntry({
|
||||||
required DateTime date,
|
required DateTime date,
|
||||||
required SnCheckInResult? checkInResult,
|
required SnCheckInResult? checkInResult,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnActivity {
|
mixin _$SnActivity {
|
||||||
|
|
||||||
String get id; String get type; String get resourceIdentifier; int get visibility; String get accountId; SnAccount get account; dynamic get data; DateTime get createdAt; DateTime get updatedAt; dynamic get deletedAt;
|
String get id; String get type; String get resourceIdentifier; dynamic get data; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnActivity
|
/// Create a copy of SnActivity
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -29,16 +29,16 @@ $SnActivityCopyWith<SnActivity> get copyWith => _$SnActivityCopyWithImpl<SnActiv
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnActivity&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.resourceIdentifier, resourceIdentifier) || other.resourceIdentifier == resourceIdentifier)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&const DeepCollectionEquality().equals(other.deletedAt, deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnActivity&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.resourceIdentifier, resourceIdentifier) || other.resourceIdentifier == resourceIdentifier)&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,type,resourceIdentifier,visibility,accountId,account,const DeepCollectionEquality().hash(data),createdAt,updatedAt,const DeepCollectionEquality().hash(deletedAt));
|
int get hashCode => Object.hash(runtimeType,id,type,resourceIdentifier,const DeepCollectionEquality().hash(data),createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnActivity(id: $id, type: $type, resourceIdentifier: $resourceIdentifier, visibility: $visibility, accountId: $accountId, account: $account, data: $data, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnActivity(id: $id, type: $type, resourceIdentifier: $resourceIdentifier, data: $data, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -49,11 +49,11 @@ abstract mixin class $SnActivityCopyWith<$Res> {
|
|||||||
factory $SnActivityCopyWith(SnActivity value, $Res Function(SnActivity) _then) = _$SnActivityCopyWithImpl;
|
factory $SnActivityCopyWith(SnActivity value, $Res Function(SnActivity) _then) = _$SnActivityCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String type, String resourceIdentifier, int visibility, String accountId, SnAccount account, dynamic data, DateTime createdAt, DateTime updatedAt, dynamic deletedAt
|
String id, String type, String resourceIdentifier, dynamic data, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnAccountCopyWith<$Res> get account;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -66,31 +66,19 @@ class _$SnActivityCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnActivity
|
/// Create a copy of SnActivity
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? resourceIdentifier = null,Object? visibility = null,Object? accountId = null,Object? account = null,Object? data = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? resourceIdentifier = null,Object? data = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as String,resourceIdentifier: null == resourceIdentifier ? _self.resourceIdentifier : resourceIdentifier // ignore: cast_nullable_to_non_nullable
|
as String,resourceIdentifier: null == resourceIdentifier ? _self.resourceIdentifier : resourceIdentifier // ignore: cast_nullable_to_non_nullable
|
||||||
as String,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||||
as int,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnAccount,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
|
||||||
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnActivity
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnAccountCopyWith<$Res> get account {
|
|
||||||
|
|
||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
|
||||||
return _then(_self.copyWith(account: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -98,19 +86,16 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnActivity implements SnActivity {
|
class _SnActivity implements SnActivity {
|
||||||
const _SnActivity({required this.id, required this.type, required this.resourceIdentifier, required this.visibility, required this.accountId, required this.account, required this.data, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
const _SnActivity({required this.id, required this.type, required this.resourceIdentifier, required this.data, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||||
factory _SnActivity.fromJson(Map<String, dynamic> json) => _$SnActivityFromJson(json);
|
factory _SnActivity.fromJson(Map<String, dynamic> json) => _$SnActivityFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@override final String type;
|
@override final String type;
|
||||||
@override final String resourceIdentifier;
|
@override final String resourceIdentifier;
|
||||||
@override final int visibility;
|
|
||||||
@override final String accountId;
|
|
||||||
@override final SnAccount account;
|
|
||||||
@override final dynamic data;
|
@override final dynamic data;
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final dynamic deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
|
|
||||||
/// Create a copy of SnActivity
|
/// Create a copy of SnActivity
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -125,16 +110,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnActivity&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.resourceIdentifier, resourceIdentifier) || other.resourceIdentifier == resourceIdentifier)&&(identical(other.visibility, visibility) || other.visibility == visibility)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&const DeepCollectionEquality().equals(other.deletedAt, deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnActivity&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.resourceIdentifier, resourceIdentifier) || other.resourceIdentifier == resourceIdentifier)&&const DeepCollectionEquality().equals(other.data, data)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,type,resourceIdentifier,visibility,accountId,account,const DeepCollectionEquality().hash(data),createdAt,updatedAt,const DeepCollectionEquality().hash(deletedAt));
|
int get hashCode => Object.hash(runtimeType,id,type,resourceIdentifier,const DeepCollectionEquality().hash(data),createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnActivity(id: $id, type: $type, resourceIdentifier: $resourceIdentifier, visibility: $visibility, accountId: $accountId, account: $account, data: $data, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnActivity(id: $id, type: $type, resourceIdentifier: $resourceIdentifier, data: $data, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -145,11 +130,11 @@ abstract mixin class _$SnActivityCopyWith<$Res> implements $SnActivityCopyWith<$
|
|||||||
factory _$SnActivityCopyWith(_SnActivity value, $Res Function(_SnActivity) _then) = __$SnActivityCopyWithImpl;
|
factory _$SnActivityCopyWith(_SnActivity value, $Res Function(_SnActivity) _then) = __$SnActivityCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String type, String resourceIdentifier, int visibility, String accountId, SnAccount account, dynamic data, DateTime createdAt, DateTime updatedAt, dynamic deletedAt
|
String id, String type, String resourceIdentifier, dynamic data, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnAccountCopyWith<$Res> get account;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -162,32 +147,20 @@ class __$SnActivityCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnActivity
|
/// Create a copy of SnActivity
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? resourceIdentifier = null,Object? visibility = null,Object? accountId = null,Object? account = null,Object? data = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? resourceIdentifier = null,Object? data = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnActivity(
|
return _then(_SnActivity(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as String,resourceIdentifier: null == resourceIdentifier ? _self.resourceIdentifier : resourceIdentifier // ignore: cast_nullable_to_non_nullable
|
as String,resourceIdentifier: null == resourceIdentifier ? _self.resourceIdentifier : resourceIdentifier // ignore: cast_nullable_to_non_nullable
|
||||||
as String,visibility: null == visibility ? _self.visibility : visibility // ignore: cast_nullable_to_non_nullable
|
as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||||
as int,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,account: null == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnAccount,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
|
||||||
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as dynamic,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as dynamic,
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Create a copy of SnActivity
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnAccountCopyWith<$Res> get account {
|
|
||||||
|
|
||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
|
||||||
return _then(_self.copyWith(account: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -10,13 +10,13 @@ _SnActivity _$SnActivityFromJson(Map<String, dynamic> json) => _SnActivity(
|
|||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
type: json['type'] as String,
|
type: json['type'] as String,
|
||||||
resourceIdentifier: json['resource_identifier'] as String,
|
resourceIdentifier: json['resource_identifier'] as String,
|
||||||
visibility: (json['visibility'] as num).toInt(),
|
|
||||||
accountId: json['account_id'] as String,
|
|
||||||
account: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
|
||||||
data: json['data'],
|
data: json['data'],
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
deletedAt: json['deleted_at'],
|
deletedAt:
|
||||||
|
json['deleted_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnActivityToJson(_SnActivity instance) =>
|
Map<String, dynamic> _$SnActivityToJson(_SnActivity instance) =>
|
||||||
@@ -24,13 +24,10 @@ Map<String, dynamic> _$SnActivityToJson(_SnActivity instance) =>
|
|||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'type': instance.type,
|
'type': instance.type,
|
||||||
'resource_identifier': instance.resourceIdentifier,
|
'resource_identifier': instance.resourceIdentifier,
|
||||||
'visibility': instance.visibility,
|
|
||||||
'account_id': instance.accountId,
|
|
||||||
'account': instance.account.toJson(),
|
|
||||||
'data': instance.data,
|
'data': instance.data,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt,
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
};
|
};
|
||||||
|
|
||||||
_SnCheckInResult _$SnCheckInResultFromJson(Map<String, dynamic> json) =>
|
_SnCheckInResult _$SnCheckInResultFromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -4,30 +4,32 @@ part 'auth.freezed.dart';
|
|||||||
part 'auth.g.dart';
|
part 'auth.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class AppTokenPair with _$AppTokenPair {
|
sealed class AppToken with _$AppToken {
|
||||||
const factory AppTokenPair({
|
const factory AppToken({required String token}) = _AppToken;
|
||||||
required String accessToken,
|
|
||||||
required String refreshToken,
|
|
||||||
}) = _AppTokenPair;
|
|
||||||
|
|
||||||
factory AppTokenPair.fromJson(Map<String, dynamic> json) =>
|
factory AppToken.fromJson(Map<String, dynamic> json) =>
|
||||||
_$AppTokenPairFromJson(json);
|
_$AppTokenFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnAuthChallenge with _$SnAuthChallenge {
|
sealed class SnAuthChallenge with _$SnAuthChallenge {
|
||||||
const factory SnAuthChallenge({
|
const factory SnAuthChallenge({
|
||||||
required String id,
|
required String id,
|
||||||
required DateTime expiredAt,
|
required DateTime expiredAt,
|
||||||
required int stepRemain,
|
required int stepRemain,
|
||||||
required int stepTotal,
|
required int stepTotal,
|
||||||
|
required int failedAttempts,
|
||||||
|
required int platform,
|
||||||
|
required int type,
|
||||||
required List<String> blacklistFactors,
|
required List<String> blacklistFactors,
|
||||||
required List<String> audiences,
|
required List<dynamic> audiences,
|
||||||
required List<String> scopes,
|
required List<dynamic> scopes,
|
||||||
required String ipAddress,
|
required String ipAddress,
|
||||||
required String userAgent,
|
required String userAgent,
|
||||||
required String? deviceId,
|
required String deviceId,
|
||||||
required String? nonce,
|
required String? nonce,
|
||||||
|
required String? location,
|
||||||
|
required String accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
@@ -38,15 +40,54 @@ abstract class SnAuthChallenge with _$SnAuthChallenge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnAuthFactor with _$SnAuthFactor {
|
sealed class SnAuthSession with _$SnAuthSession {
|
||||||
|
const factory SnAuthSession({
|
||||||
|
required String id,
|
||||||
|
required String? label,
|
||||||
|
required DateTime lastGrantedAt,
|
||||||
|
required DateTime expiredAt,
|
||||||
|
required String accountId,
|
||||||
|
required String challengeId,
|
||||||
|
required SnAuthChallenge challenge,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
required DateTime? deletedAt,
|
||||||
|
}) = _SnAuthSession;
|
||||||
|
|
||||||
|
factory SnAuthSession.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnAuthSessionFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnAuthFactor with _$SnAuthFactor {
|
||||||
const factory SnAuthFactor({
|
const factory SnAuthFactor({
|
||||||
required String id,
|
required String id,
|
||||||
required int type,
|
required int type,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
|
required DateTime? expiredAt,
|
||||||
|
required DateTime? enabledAt,
|
||||||
|
required int trustworthy,
|
||||||
|
required Map<String, dynamic>? createdResponse,
|
||||||
}) = _SnAuthFactor;
|
}) = _SnAuthFactor;
|
||||||
|
|
||||||
factory SnAuthFactor.fromJson(Map<String, dynamic> json) =>
|
factory SnAuthFactor.fromJson(Map<String, dynamic> json) =>
|
||||||
_$SnAuthFactorFromJson(json);
|
_$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);
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,42 +14,42 @@ part of 'auth.dart';
|
|||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$AppTokenPair {
|
mixin _$AppToken {
|
||||||
|
|
||||||
String get accessToken; String get refreshToken;
|
String get token;
|
||||||
/// Create a copy of AppTokenPair
|
/// Create a copy of AppToken
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
$AppTokenPairCopyWith<AppTokenPair> get copyWith => _$AppTokenPairCopyWithImpl<AppTokenPair>(this as AppTokenPair, _$identity);
|
$AppTokenCopyWith<AppToken> get copyWith => _$AppTokenCopyWithImpl<AppToken>(this as AppToken, _$identity);
|
||||||
|
|
||||||
/// Serializes this AppTokenPair to a JSON map.
|
/// Serializes this AppToken to a JSON map.
|
||||||
Map<String, dynamic> toJson();
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppTokenPair&&(identical(other.accessToken, accessToken) || other.accessToken == accessToken)&&(identical(other.refreshToken, refreshToken) || other.refreshToken == refreshToken));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppToken&&(identical(other.token, token) || other.token == token));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,accessToken,refreshToken);
|
int get hashCode => Object.hash(runtimeType,token);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppTokenPair(accessToken: $accessToken, refreshToken: $refreshToken)';
|
return 'AppToken(token: $token)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract mixin class $AppTokenPairCopyWith<$Res> {
|
abstract mixin class $AppTokenCopyWith<$Res> {
|
||||||
factory $AppTokenPairCopyWith(AppTokenPair value, $Res Function(AppTokenPair) _then) = _$AppTokenPairCopyWithImpl;
|
factory $AppTokenCopyWith(AppToken value, $Res Function(AppToken) _then) = _$AppTokenCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String accessToken, String refreshToken
|
String token
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -57,19 +57,18 @@ $Res call({
|
|||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class _$AppTokenPairCopyWithImpl<$Res>
|
class _$AppTokenCopyWithImpl<$Res>
|
||||||
implements $AppTokenPairCopyWith<$Res> {
|
implements $AppTokenCopyWith<$Res> {
|
||||||
_$AppTokenPairCopyWithImpl(this._self, this._then);
|
_$AppTokenCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
final AppTokenPair _self;
|
final AppToken _self;
|
||||||
final $Res Function(AppTokenPair) _then;
|
final $Res Function(AppToken) _then;
|
||||||
|
|
||||||
/// Create a copy of AppTokenPair
|
/// Create a copy of AppToken
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? accessToken = null,Object? refreshToken = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? token = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
accessToken: null == accessToken ? _self.accessToken : accessToken // ignore: cast_nullable_to_non_nullable
|
token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||||
as String,refreshToken: null == refreshToken ? _self.refreshToken : refreshToken // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
as String,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -80,47 +79,46 @@ as String,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _AppTokenPair implements AppTokenPair {
|
class _AppToken implements AppToken {
|
||||||
const _AppTokenPair({required this.accessToken, required this.refreshToken});
|
const _AppToken({required this.token});
|
||||||
factory _AppTokenPair.fromJson(Map<String, dynamic> json) => _$AppTokenPairFromJson(json);
|
factory _AppToken.fromJson(Map<String, dynamic> json) => _$AppTokenFromJson(json);
|
||||||
|
|
||||||
@override final String accessToken;
|
@override final String token;
|
||||||
@override final String refreshToken;
|
|
||||||
|
|
||||||
/// Create a copy of AppTokenPair
|
/// Create a copy of AppToken
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
_$AppTokenPairCopyWith<_AppTokenPair> get copyWith => __$AppTokenPairCopyWithImpl<_AppTokenPair>(this, _$identity);
|
_$AppTokenCopyWith<_AppToken> get copyWith => __$AppTokenCopyWithImpl<_AppToken>(this, _$identity);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Map<String, dynamic> toJson() {
|
Map<String, dynamic> toJson() {
|
||||||
return _$AppTokenPairToJson(this, );
|
return _$AppTokenToJson(this, );
|
||||||
}
|
}
|
||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppTokenPair&&(identical(other.accessToken, accessToken) || other.accessToken == accessToken)&&(identical(other.refreshToken, refreshToken) || other.refreshToken == refreshToken));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppToken&&(identical(other.token, token) || other.token == token));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,accessToken,refreshToken);
|
int get hashCode => Object.hash(runtimeType,token);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppTokenPair(accessToken: $accessToken, refreshToken: $refreshToken)';
|
return 'AppToken(token: $token)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
abstract mixin class _$AppTokenPairCopyWith<$Res> implements $AppTokenPairCopyWith<$Res> {
|
abstract mixin class _$AppTokenCopyWith<$Res> implements $AppTokenCopyWith<$Res> {
|
||||||
factory _$AppTokenPairCopyWith(_AppTokenPair value, $Res Function(_AppTokenPair) _then) = __$AppTokenPairCopyWithImpl;
|
factory _$AppTokenCopyWith(_AppToken value, $Res Function(_AppToken) _then) = __$AppTokenCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String accessToken, String refreshToken
|
String token
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -128,19 +126,18 @@ $Res call({
|
|||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
class __$AppTokenPairCopyWithImpl<$Res>
|
class __$AppTokenCopyWithImpl<$Res>
|
||||||
implements _$AppTokenPairCopyWith<$Res> {
|
implements _$AppTokenCopyWith<$Res> {
|
||||||
__$AppTokenPairCopyWithImpl(this._self, this._then);
|
__$AppTokenCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
final _AppTokenPair _self;
|
final _AppToken _self;
|
||||||
final $Res Function(_AppTokenPair) _then;
|
final $Res Function(_AppToken) _then;
|
||||||
|
|
||||||
/// Create a copy of AppTokenPair
|
/// Create a copy of AppToken
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? accessToken = null,Object? refreshToken = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? token = null,}) {
|
||||||
return _then(_AppTokenPair(
|
return _then(_AppToken(
|
||||||
accessToken: null == accessToken ? _self.accessToken : accessToken // ignore: cast_nullable_to_non_nullable
|
token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||||
as String,refreshToken: null == refreshToken ? _self.refreshToken : refreshToken // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,
|
as String,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -152,7 +149,7 @@ as String,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAuthChallenge {
|
mixin _$SnAuthChallenge {
|
||||||
|
|
||||||
String get id; DateTime get expiredAt; int get stepRemain; int get stepTotal; List<String> get blacklistFactors; List<String> get audiences; List<String> get scopes; String get ipAddress; String get userAgent; String? get deviceId; String? get nonce; 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 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;
|
||||||
/// Create a copy of SnAuthChallenge
|
/// Create a copy of SnAuthChallenge
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -165,16 +162,16 @@ $SnAuthChallengeCopyWith<SnAuthChallenge> get copyWith => _$SnAuthChallengeCopyW
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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)&&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.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.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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,expiredAt,stepRemain,stepTotal,const DeepCollectionEquality().hash(blacklistFactors),const DeepCollectionEquality().hash(audiences),const DeepCollectionEquality().hash(scopes),ipAddress,userAgent,deviceId,nonce,createdAt,updatedAt,deletedAt);
|
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]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, deviceId: $deviceId, nonce: $nonce, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
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)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -185,7 +182,7 @@ abstract mixin class $SnAuthChallengeCopyWith<$Res> {
|
|||||||
factory $SnAuthChallengeCopyWith(SnAuthChallenge value, $Res Function(SnAuthChallenge) _then) = _$SnAuthChallengeCopyWithImpl;
|
factory $SnAuthChallengeCopyWith(SnAuthChallenge value, $Res Function(SnAuthChallenge) _then) = _$SnAuthChallengeCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, DateTime expiredAt, int stepRemain, int stepTotal, List<String> blacklistFactors, List<String> audiences, List<String> scopes, String ipAddress, String userAgent, String? deviceId, String? nonce, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -202,20 +199,25 @@ class _$SnAuthChallengeCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAuthChallenge
|
/// Create a copy of SnAuthChallenge
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? expiredAt = null,Object? stepRemain = null,Object? stepTotal = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? deviceId = freezed,Object? nonce = freezed,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? 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,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // 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 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,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 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<String>,audiences: null == audiences ? _self.audiences : audiences // ignore: cast_nullable_to_non_nullable
|
||||||
as List<String>,scopes: null == scopes ? _self.scopes : scopes // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,scopes: null == scopes ? _self.scopes : scopes // ignore: cast_nullable_to_non_nullable
|
||||||
as List<String>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // 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,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||||
as String,deviceId: freezed == deviceId ? _self.deviceId : deviceId // 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,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as 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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -229,13 +231,16 @@ as DateTime?,
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnAuthChallenge implements SnAuthChallenge {
|
class _SnAuthChallenge implements SnAuthChallenge {
|
||||||
const _SnAuthChallenge({required this.id, required this.expiredAt, required this.stepRemain, required this.stepTotal, required final List<String> blacklistFactors, required final List<String> audiences, required final List<String> scopes, required this.ipAddress, required this.userAgent, required this.deviceId, required this.nonce, 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.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;
|
||||||
factory _SnAuthChallenge.fromJson(Map<String, dynamic> json) => _$SnAuthChallengeFromJson(json);
|
factory _SnAuthChallenge.fromJson(Map<String, dynamic> json) => _$SnAuthChallengeFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@override final DateTime expiredAt;
|
@override final DateTime expiredAt;
|
||||||
@override final int stepRemain;
|
@override final int stepRemain;
|
||||||
@override final int stepTotal;
|
@override final int stepTotal;
|
||||||
|
@override final int failedAttempts;
|
||||||
|
@override final int platform;
|
||||||
|
@override final int type;
|
||||||
final List<String> _blacklistFactors;
|
final List<String> _blacklistFactors;
|
||||||
@override List<String> get blacklistFactors {
|
@override List<String> get blacklistFactors {
|
||||||
if (_blacklistFactors is EqualUnmodifiableListView) return _blacklistFactors;
|
if (_blacklistFactors is EqualUnmodifiableListView) return _blacklistFactors;
|
||||||
@@ -243,15 +248,15 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
|||||||
return EqualUnmodifiableListView(_blacklistFactors);
|
return EqualUnmodifiableListView(_blacklistFactors);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<String> _audiences;
|
final List<dynamic> _audiences;
|
||||||
@override List<String> get audiences {
|
@override List<dynamic> get audiences {
|
||||||
if (_audiences is EqualUnmodifiableListView) return _audiences;
|
if (_audiences is EqualUnmodifiableListView) return _audiences;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_audiences);
|
return EqualUnmodifiableListView(_audiences);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<String> _scopes;
|
final List<dynamic> _scopes;
|
||||||
@override List<String> get scopes {
|
@override List<dynamic> get scopes {
|
||||||
if (_scopes is EqualUnmodifiableListView) return _scopes;
|
if (_scopes is EqualUnmodifiableListView) return _scopes;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_scopes);
|
return EqualUnmodifiableListView(_scopes);
|
||||||
@@ -259,8 +264,10 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
|||||||
|
|
||||||
@override final String ipAddress;
|
@override final String ipAddress;
|
||||||
@override final String userAgent;
|
@override final String userAgent;
|
||||||
@override final String? deviceId;
|
@override final String deviceId;
|
||||||
@override final String? nonce;
|
@override final String? nonce;
|
||||||
|
@override final String? location;
|
||||||
|
@override final String accountId;
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
@@ -278,16 +285,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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)&&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.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.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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,expiredAt,stepRemain,stepTotal,const DeepCollectionEquality().hash(_blacklistFactors),const DeepCollectionEquality().hash(_audiences),const DeepCollectionEquality().hash(_scopes),ipAddress,userAgent,deviceId,nonce,createdAt,updatedAt,deletedAt);
|
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]);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAuthChallenge(id: $id, expiredAt: $expiredAt, stepRemain: $stepRemain, stepTotal: $stepTotal, blacklistFactors: $blacklistFactors, audiences: $audiences, scopes: $scopes, ipAddress: $ipAddress, userAgent: $userAgent, deviceId: $deviceId, nonce: $nonce, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
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)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -298,7 +305,7 @@ abstract mixin class _$SnAuthChallengeCopyWith<$Res> implements $SnAuthChallenge
|
|||||||
factory _$SnAuthChallengeCopyWith(_SnAuthChallenge value, $Res Function(_SnAuthChallenge) _then) = __$SnAuthChallengeCopyWithImpl;
|
factory _$SnAuthChallengeCopyWith(_SnAuthChallenge value, $Res Function(_SnAuthChallenge) _then) = __$SnAuthChallengeCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, DateTime expiredAt, int stepRemain, int stepTotal, List<String> blacklistFactors, List<String> audiences, List<String> scopes, String ipAddress, String userAgent, String? deviceId, String? nonce, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -315,20 +322,25 @@ class __$SnAuthChallengeCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAuthChallenge
|
/// Create a copy of SnAuthChallenge
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? expiredAt = null,Object? stepRemain = null,Object? stepTotal = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? deviceId = freezed,Object? nonce = freezed,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? 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,}) {
|
||||||
return _then(_SnAuthChallenge(
|
return _then(_SnAuthChallenge(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // 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 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,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 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<String>,audiences: null == audiences ? _self._audiences : audiences // ignore: cast_nullable_to_non_nullable
|
||||||
as List<String>,scopes: null == scopes ? _self._scopes : scopes // ignore: cast_nullable_to_non_nullable
|
as List<dynamic>,scopes: null == scopes ? _self._scopes : scopes // ignore: cast_nullable_to_non_nullable
|
||||||
as List<String>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // 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,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||||
as String,deviceId: freezed == deviceId ? _self.deviceId : deviceId // 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,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as 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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -339,10 +351,188 @@ as DateTime?,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnAuthSession {
|
||||||
|
|
||||||
|
String get id; String? get label; DateTime get lastGrantedAt; DateTime get expiredAt; String get accountId; String get challengeId; SnAuthChallenge get challenge; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
|
/// Create a copy of SnAuthSession
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAuthSessionCopyWith<SnAuthSession> get copyWith => _$SnAuthSessionCopyWithImpl<SnAuthSession>(this as SnAuthSession, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnAuthSession to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthSession&&(identical(other.id, id) || other.id == id)&&(identical(other.label, label) || other.label == label)&&(identical(other.lastGrantedAt, lastGrantedAt) || other.lastGrantedAt == lastGrantedAt)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.challengeId, challengeId) || other.challengeId == challengeId)&&(identical(other.challenge, challenge) || other.challenge == challenge)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,label,lastGrantedAt,expiredAt,accountId,challengeId,challenge,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnAuthSession(id: $id, label: $label, lastGrantedAt: $lastGrantedAt, expiredAt: $expiredAt, accountId: $accountId, challengeId: $challengeId, challenge: $challenge, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnAuthSessionCopyWith<$Res> {
|
||||||
|
factory $SnAuthSessionCopyWith(SnAuthSession value, $Res Function(SnAuthSession) _then) = _$SnAuthSessionCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$SnAuthChallengeCopyWith<$Res> get challenge;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnAuthSessionCopyWithImpl<$Res>
|
||||||
|
implements $SnAuthSessionCopyWith<$Res> {
|
||||||
|
_$SnAuthSessionCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnAuthSession _self;
|
||||||
|
final $Res Function(SnAuthSession) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnAuthSession
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = null,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,lastGrantedAt: null == lastGrantedAt ? _self.lastGrantedAt : lastGrantedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,challengeId: null == challengeId ? _self.challengeId : challengeId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,challenge: null == challenge ? _self.challenge : challenge // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAuthChallenge,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
/// Create a copy of SnAuthSession
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAuthChallengeCopyWith<$Res> get challenge {
|
||||||
|
|
||||||
|
return $SnAuthChallengeCopyWith<$Res>(_self.challenge, (value) {
|
||||||
|
return _then(_self.copyWith(challenge: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnAuthSession implements SnAuthSession {
|
||||||
|
const _SnAuthSession({required this.id, required this.label, required this.lastGrantedAt, required this.expiredAt, required this.accountId, required this.challengeId, required this.challenge, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||||
|
factory _SnAuthSession.fromJson(Map<String, dynamic> json) => _$SnAuthSessionFromJson(json);
|
||||||
|
|
||||||
|
@override final String id;
|
||||||
|
@override final String? label;
|
||||||
|
@override final DateTime lastGrantedAt;
|
||||||
|
@override final DateTime expiredAt;
|
||||||
|
@override final String accountId;
|
||||||
|
@override final String challengeId;
|
||||||
|
@override final SnAuthChallenge challenge;
|
||||||
|
@override final DateTime createdAt;
|
||||||
|
@override final DateTime updatedAt;
|
||||||
|
@override final DateTime? deletedAt;
|
||||||
|
|
||||||
|
/// Create a copy of SnAuthSession
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnAuthSessionCopyWith<_SnAuthSession> get copyWith => __$SnAuthSessionCopyWithImpl<_SnAuthSession>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnAuthSessionToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAuthSession&&(identical(other.id, id) || other.id == id)&&(identical(other.label, label) || other.label == label)&&(identical(other.lastGrantedAt, lastGrantedAt) || other.lastGrantedAt == lastGrantedAt)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.challengeId, challengeId) || other.challengeId == challengeId)&&(identical(other.challenge, challenge) || other.challenge == challenge)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,label,lastGrantedAt,expiredAt,accountId,challengeId,challenge,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnAuthSession(id: $id, label: $label, lastGrantedAt: $lastGrantedAt, expiredAt: $expiredAt, accountId: $accountId, challengeId: $challengeId, challenge: $challenge, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnAuthSessionCopyWith<$Res> implements $SnAuthSessionCopyWith<$Res> {
|
||||||
|
factory _$SnAuthSessionCopyWith(_SnAuthSession value, $Res Function(_SnAuthSession) _then) = __$SnAuthSessionCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $SnAuthChallengeCopyWith<$Res> get challenge;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnAuthSessionCopyWithImpl<$Res>
|
||||||
|
implements _$SnAuthSessionCopyWith<$Res> {
|
||||||
|
__$SnAuthSessionCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnAuthSession _self;
|
||||||
|
final $Res Function(_SnAuthSession) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnAuthSession
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = null,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
|
return _then(_SnAuthSession(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,label: freezed == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,lastGrantedAt: null == lastGrantedAt ? _self.lastGrantedAt : lastGrantedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,expiredAt: null == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,challengeId: null == challengeId ? _self.challengeId : challengeId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,challenge: null == challenge ? _self.challenge : challenge // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAuthChallenge,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SnAuthSession
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAuthChallengeCopyWith<$Res> get challenge {
|
||||||
|
|
||||||
|
return $SnAuthChallengeCopyWith<$Res>(_self.challenge, (value) {
|
||||||
|
return _then(_self.copyWith(challenge: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAuthFactor {
|
mixin _$SnAuthFactor {
|
||||||
|
|
||||||
String get id; int get type; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; int get type; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; DateTime? get expiredAt; DateTime? get enabledAt; int get trustworthy; Map<String, dynamic>? get createdResponse;
|
||||||
/// Create a copy of SnAuthFactor
|
/// Create a copy of SnAuthFactor
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -355,16 +545,16 @@ $SnAuthFactorCopyWith<SnAuthFactor> get copyWith => _$SnAuthFactorCopyWithImpl<S
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAuthFactor&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(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 SnAuthFactor&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.enabledAt, enabledAt) || other.enabledAt == enabledAt)&&(identical(other.trustworthy, trustworthy) || other.trustworthy == trustworthy)&&const DeepCollectionEquality().equals(other.createdResponse, createdResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,type,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,type,createdAt,updatedAt,deletedAt,expiredAt,enabledAt,trustworthy,const DeepCollectionEquality().hash(createdResponse));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAuthFactor(id: $id, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAuthFactor(id: $id, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, expiredAt: $expiredAt, enabledAt: $enabledAt, trustworthy: $trustworthy, createdResponse: $createdResponse)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -375,7 +565,7 @@ abstract mixin class $SnAuthFactorCopyWith<$Res> {
|
|||||||
factory $SnAuthFactorCopyWith(SnAuthFactor value, $Res Function(SnAuthFactor) _then) = _$SnAuthFactorCopyWithImpl;
|
factory $SnAuthFactorCopyWith(SnAuthFactor value, $Res Function(SnAuthFactor) _then) = _$SnAuthFactorCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, int type, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, int type, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? expiredAt, DateTime? enabledAt, int trustworthy, Map<String, dynamic>? createdResponse
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -392,14 +582,18 @@ class _$SnAuthFactorCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAuthFactor
|
/// Create a copy of SnAuthFactor
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? expiredAt = freezed,Object? enabledAt = freezed,Object? trustworthy = null,Object? createdResponse = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,enabledAt: freezed == enabledAt ? _self.enabledAt : enabledAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,trustworthy: null == trustworthy ? _self.trustworthy : trustworthy // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,createdResponse: freezed == createdResponse ? _self.createdResponse : createdResponse // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, dynamic>?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -410,7 +604,7 @@ as DateTime?,
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnAuthFactor implements SnAuthFactor {
|
class _SnAuthFactor implements SnAuthFactor {
|
||||||
const _SnAuthFactor({required this.id, required this.type, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
const _SnAuthFactor({required this.id, required this.type, required this.createdAt, required this.updatedAt, required this.deletedAt, required this.expiredAt, required this.enabledAt, required this.trustworthy, required final Map<String, dynamic>? createdResponse}): _createdResponse = createdResponse;
|
||||||
factory _SnAuthFactor.fromJson(Map<String, dynamic> json) => _$SnAuthFactorFromJson(json);
|
factory _SnAuthFactor.fromJson(Map<String, dynamic> json) => _$SnAuthFactorFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -418,6 +612,18 @@ class _SnAuthFactor implements SnAuthFactor {
|
|||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
|
@override final DateTime? expiredAt;
|
||||||
|
@override final DateTime? enabledAt;
|
||||||
|
@override final int trustworthy;
|
||||||
|
final Map<String, dynamic>? _createdResponse;
|
||||||
|
@override Map<String, dynamic>? get createdResponse {
|
||||||
|
final value = _createdResponse;
|
||||||
|
if (value == null) return null;
|
||||||
|
if (_createdResponse is EqualUnmodifiableMapView) return _createdResponse;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// Create a copy of SnAuthFactor
|
/// Create a copy of SnAuthFactor
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -432,16 +638,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAuthFactor&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(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 _SnAuthFactor&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.expiredAt, expiredAt) || other.expiredAt == expiredAt)&&(identical(other.enabledAt, enabledAt) || other.enabledAt == enabledAt)&&(identical(other.trustworthy, trustworthy) || other.trustworthy == trustworthy)&&const DeepCollectionEquality().equals(other._createdResponse, _createdResponse));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,type,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,type,createdAt,updatedAt,deletedAt,expiredAt,enabledAt,trustworthy,const DeepCollectionEquality().hash(_createdResponse));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAuthFactor(id: $id, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAuthFactor(id: $id, type: $type, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, expiredAt: $expiredAt, enabledAt: $enabledAt, trustworthy: $trustworthy, createdResponse: $createdResponse)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -452,7 +658,7 @@ abstract mixin class _$SnAuthFactorCopyWith<$Res> implements $SnAuthFactorCopyWi
|
|||||||
factory _$SnAuthFactorCopyWith(_SnAuthFactor value, $Res Function(_SnAuthFactor) _then) = __$SnAuthFactorCopyWithImpl;
|
factory _$SnAuthFactorCopyWith(_SnAuthFactor value, $Res Function(_SnAuthFactor) _then) = __$SnAuthFactorCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, int type, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, int type, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? expiredAt, DateTime? enabledAt, int trustworthy, Map<String, dynamic>? createdResponse
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -469,14 +675,174 @@ class __$SnAuthFactorCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAuthFactor
|
/// Create a copy of SnAuthFactor
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? expiredAt = freezed,Object? enabledAt = freezed,Object? trustworthy = null,Object? createdResponse = freezed,}) {
|
||||||
return _then(_SnAuthFactor(
|
return _then(_SnAuthFactor(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,enabledAt: freezed == enabledAt ? _self.enabledAt : enabledAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,trustworthy: null == trustworthy ? _self.trustworthy : trustworthy // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,createdResponse: freezed == createdResponse ? _self._createdResponse : createdResponse // ignore: cast_nullable_to_non_nullable
|
||||||
|
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,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @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,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,17 +6,12 @@ part of 'auth.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
_AppTokenPair _$AppTokenPairFromJson(Map<String, dynamic> json) =>
|
_AppToken _$AppTokenFromJson(Map<String, dynamic> json) =>
|
||||||
_AppTokenPair(
|
_AppToken(token: json['token'] as String);
|
||||||
accessToken: json['access_token'] as String,
|
|
||||||
refreshToken: json['refresh_token'] as String,
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$AppTokenPairToJson(_AppTokenPair instance) =>
|
Map<String, dynamic> _$AppTokenToJson(_AppToken instance) => <String, dynamic>{
|
||||||
<String, dynamic>{
|
'token': instance.token,
|
||||||
'access_token': instance.accessToken,
|
};
|
||||||
'refresh_token': instance.refreshToken,
|
|
||||||
};
|
|
||||||
|
|
||||||
_SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
_SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||||
_SnAuthChallenge(
|
_SnAuthChallenge(
|
||||||
@@ -24,18 +19,21 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
|||||||
expiredAt: DateTime.parse(json['expired_at'] as String),
|
expiredAt: DateTime.parse(json['expired_at'] as String),
|
||||||
stepRemain: (json['step_remain'] as num).toInt(),
|
stepRemain: (json['step_remain'] as num).toInt(),
|
||||||
stepTotal: (json['step_total'] 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:
|
blacklistFactors:
|
||||||
(json['blacklist_factors'] as List<dynamic>)
|
(json['blacklist_factors'] as List<dynamic>)
|
||||||
.map((e) => e as String)
|
.map((e) => e as String)
|
||||||
.toList(),
|
.toList(),
|
||||||
audiences:
|
audiences: json['audiences'] as List<dynamic>,
|
||||||
(json['audiences'] as List<dynamic>).map((e) => e as String).toList(),
|
scopes: json['scopes'] as List<dynamic>,
|
||||||
scopes:
|
|
||||||
(json['scopes'] as List<dynamic>).map((e) => e as String).toList(),
|
|
||||||
ipAddress: json['ip_address'] as String,
|
ipAddress: json['ip_address'] as String,
|
||||||
userAgent: json['user_agent'] as String,
|
userAgent: json['user_agent'] as String,
|
||||||
deviceId: json['device_id'] as String?,
|
deviceId: json['device_id'] as String,
|
||||||
nonce: json['nonce'] as String?,
|
nonce: json['nonce'] as String?,
|
||||||
|
location: json['location'] as String?,
|
||||||
|
accountId: json['account_id'] as String,
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
deletedAt:
|
deletedAt:
|
||||||
@@ -50,6 +48,9 @@ Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
|||||||
'expired_at': instance.expiredAt.toIso8601String(),
|
'expired_at': instance.expiredAt.toIso8601String(),
|
||||||
'step_remain': instance.stepRemain,
|
'step_remain': instance.stepRemain,
|
||||||
'step_total': instance.stepTotal,
|
'step_total': instance.stepTotal,
|
||||||
|
'failed_attempts': instance.failedAttempts,
|
||||||
|
'platform': instance.platform,
|
||||||
|
'type': instance.type,
|
||||||
'blacklist_factors': instance.blacklistFactors,
|
'blacklist_factors': instance.blacklistFactors,
|
||||||
'audiences': instance.audiences,
|
'audiences': instance.audiences,
|
||||||
'scopes': instance.scopes,
|
'scopes': instance.scopes,
|
||||||
@@ -57,6 +58,41 @@ Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
|||||||
'user_agent': instance.userAgent,
|
'user_agent': instance.userAgent,
|
||||||
'device_id': instance.deviceId,
|
'device_id': instance.deviceId,
|
||||||
'nonce': instance.nonce,
|
'nonce': instance.nonce,
|
||||||
|
'location': instance.location,
|
||||||
|
'account_id': instance.accountId,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
};
|
||||||
|
|
||||||
|
_SnAuthSession _$SnAuthSessionFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnAuthSession(
|
||||||
|
id: json['id'] as String,
|
||||||
|
label: json['label'] as String?,
|
||||||
|
lastGrantedAt: DateTime.parse(json['last_granted_at'] as String),
|
||||||
|
expiredAt: DateTime.parse(json['expired_at'] as String),
|
||||||
|
accountId: json['account_id'] as String,
|
||||||
|
challengeId: json['challenge_id'] as String,
|
||||||
|
challenge: SnAuthChallenge.fromJson(
|
||||||
|
json['challenge'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
deletedAt:
|
||||||
|
json['deleted_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnAuthSessionToJson(_SnAuthSession instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'label': instance.label,
|
||||||
|
'last_granted_at': instance.lastGrantedAt.toIso8601String(),
|
||||||
|
'expired_at': instance.expiredAt.toIso8601String(),
|
||||||
|
'account_id': instance.accountId,
|
||||||
|
'challenge_id': instance.challengeId,
|
||||||
|
'challenge': instance.challenge.toJson(),
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
@@ -72,6 +108,16 @@ _SnAuthFactor _$SnAuthFactorFromJson(Map<String, dynamic> json) =>
|
|||||||
json['deleted_at'] == null
|
json['deleted_at'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['deleted_at'] as String),
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
expiredAt:
|
||||||
|
json['expired_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['expired_at'] as String),
|
||||||
|
enabledAt:
|
||||||
|
json['enabled_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['enabled_at'] as String),
|
||||||
|
trustworthy: (json['trustworthy'] as num).toInt(),
|
||||||
|
createdResponse: json['created_response'] as Map<String, dynamic>?,
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnAuthFactorToJson(_SnAuthFactor instance) =>
|
Map<String, dynamic> _$SnAuthFactorToJson(_SnAuthFactor instance) =>
|
||||||
@@ -81,4 +127,31 @@ Map<String, dynamic> _$SnAuthFactorToJson(_SnAuthFactor instance) =>
|
|||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||||
|
'enabled_at': instance.enabledAt?.toIso8601String(),
|
||||||
|
'trustworthy': instance.trustworthy,
|
||||||
|
'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,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -7,16 +7,14 @@ part 'chat.freezed.dart';
|
|||||||
part 'chat.g.dart';
|
part 'chat.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnChatRoom with _$SnChatRoom {
|
sealed class SnChatRoom with _$SnChatRoom {
|
||||||
const factory SnChatRoom({
|
const factory SnChatRoom({
|
||||||
required String id,
|
required String id,
|
||||||
required String? name,
|
required String? name,
|
||||||
required String? description,
|
required String? description,
|
||||||
required int type,
|
required int type,
|
||||||
required bool isPublic,
|
required bool isPublic,
|
||||||
required String? pictureId,
|
|
||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required String? backgroundId,
|
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
required String? realmId,
|
required String? realmId,
|
||||||
required SnRealm? realm,
|
required SnRealm? realm,
|
||||||
@@ -31,12 +29,13 @@ abstract class SnChatRoom with _$SnChatRoom {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnChatMessage with _$SnChatMessage {
|
sealed class SnChatMessage with _$SnChatMessage {
|
||||||
const factory SnChatMessage({
|
const factory SnChatMessage({
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
DateTime? deletedAt,
|
DateTime? deletedAt,
|
||||||
required String id,
|
required String id,
|
||||||
|
@Default('text') String type,
|
||||||
String? content,
|
String? content,
|
||||||
String? nonce,
|
String? nonce,
|
||||||
@Default({}) Map<String, dynamic> meta,
|
@Default({}) Map<String, dynamic> meta,
|
||||||
@@ -56,7 +55,7 @@ abstract class SnChatMessage with _$SnChatMessage {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnChatReaction with _$SnChatReaction {
|
sealed class SnChatReaction with _$SnChatReaction {
|
||||||
const factory SnChatReaction({
|
const factory SnChatReaction({
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
@@ -74,7 +73,7 @@ abstract class SnChatReaction with _$SnChatReaction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnChatMember with _$SnChatMember {
|
sealed class SnChatMember with _$SnChatMember {
|
||||||
const factory SnChatMember({
|
const factory SnChatMember({
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
@@ -88,7 +87,11 @@ abstract class SnChatMember with _$SnChatMember {
|
|||||||
required int role,
|
required int role,
|
||||||
required int notify,
|
required int notify,
|
||||||
required DateTime? joinedAt,
|
required DateTime? joinedAt,
|
||||||
|
required DateTime? breakUntil,
|
||||||
|
required DateTime? timeoutUntil,
|
||||||
required bool isBot,
|
required bool isBot,
|
||||||
|
// Frontend data
|
||||||
|
DateTime? lastTyped,
|
||||||
}) = _SnChatMember;
|
}) = _SnChatMember;
|
||||||
|
|
||||||
factory SnChatMember.fromJson(Map<String, dynamic> json) =>
|
factory SnChatMember.fromJson(Map<String, dynamic> json) =>
|
||||||
@@ -96,7 +99,7 @@ abstract class SnChatMember with _$SnChatMember {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnChatSummary with _$SnChatSummary {
|
sealed class SnChatSummary with _$SnChatSummary {
|
||||||
const factory SnChatSummary({
|
const factory SnChatSummary({
|
||||||
required int unreadCount,
|
required int unreadCount,
|
||||||
required SnChatMessage lastMessage,
|
required SnChatMessage lastMessage,
|
||||||
@@ -113,7 +116,7 @@ class MessageChangeAction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class MessageChange with _$MessageChange {
|
sealed class MessageChange with _$MessageChange {
|
||||||
const factory MessageChange({
|
const factory MessageChange({
|
||||||
required String messageId,
|
required String messageId,
|
||||||
required String action,
|
required String action,
|
||||||
@@ -126,7 +129,7 @@ abstract class MessageChange with _$MessageChange {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class MessageSyncResponse with _$MessageSyncResponse {
|
sealed class MessageSyncResponse with _$MessageSyncResponse {
|
||||||
const factory MessageSyncResponse({
|
const factory MessageSyncResponse({
|
||||||
@Default([]) List<MessageChange> changes,
|
@Default([]) List<MessageChange> changes,
|
||||||
required DateTime currentTimestamp,
|
required DateTime currentTimestamp,
|
||||||
@@ -137,12 +140,52 @@ abstract class MessageSyncResponse with _$MessageSyncResponse {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class ChatRealtimeJoinResponse with _$ChatRealtimeJoinResponse {
|
sealed class ChatRealtimeJoinResponse with _$ChatRealtimeJoinResponse {
|
||||||
const factory ChatRealtimeJoinResponse({
|
const factory ChatRealtimeJoinResponse({
|
||||||
|
required String provider,
|
||||||
|
required String endpoint,
|
||||||
required String token,
|
required String token,
|
||||||
required Map<String, dynamic> config,
|
required String callId,
|
||||||
|
required String roomName,
|
||||||
|
required bool isAdmin,
|
||||||
|
required List<CallParticipant> participants,
|
||||||
}) = _ChatRealtimeJoinResponse;
|
}) = _ChatRealtimeJoinResponse;
|
||||||
|
|
||||||
factory ChatRealtimeJoinResponse.fromJson(Map<String, dynamic> json) =>
|
factory ChatRealtimeJoinResponse.fromJson(Map<String, dynamic> json) =>
|
||||||
_$ChatRealtimeJoinResponseFromJson(json);
|
_$ChatRealtimeJoinResponseFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class CallParticipant with _$CallParticipant {
|
||||||
|
const factory CallParticipant({
|
||||||
|
required String identity,
|
||||||
|
required String name,
|
||||||
|
required DateTime joinedAt,
|
||||||
|
required String? accountId,
|
||||||
|
required SnChatMember? profile,
|
||||||
|
}) = _CallParticipant;
|
||||||
|
|
||||||
|
factory CallParticipant.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$CallParticipantFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnRealtimeCall with _$SnRealtimeCall {
|
||||||
|
const factory SnRealtimeCall({
|
||||||
|
required String id,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
required DateTime? deletedAt,
|
||||||
|
required DateTime? endedAt,
|
||||||
|
required String senderId,
|
||||||
|
required SnChatMember sender,
|
||||||
|
required String roomId,
|
||||||
|
required SnChatRoom room,
|
||||||
|
required Map<String, dynamic> upstreamConfig,
|
||||||
|
String? providerName,
|
||||||
|
String? sessionId,
|
||||||
|
}) = _SnRealtimeCall;
|
||||||
|
|
||||||
|
factory SnRealtimeCall.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnRealtimeCallFromJson(json);
|
||||||
|
}
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnChatRoom {
|
mixin _$SnChatRoom {
|
||||||
|
|
||||||
String get id; String? get name; String? get description; int get type; bool get isPublic; String? get pictureId; SnCloudFile? get picture; String? get backgroundId; SnCloudFile? get background; String? get realmId; SnRealm? get realm; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; List<SnChatMember>? get members;
|
String get id; String? get name; String? get description; int get type; bool get isPublic; SnCloudFile? get picture; SnCloudFile? get background; String? get realmId; SnRealm? get realm; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; List<SnChatMember>? get members;
|
||||||
/// Create a copy of SnChatRoom
|
/// Create a copy of SnChatRoom
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -29,16 +29,16 @@ $SnChatRoomCopyWith<SnChatRoom> get copyWith => _$SnChatRoomCopyWithImpl<SnChatR
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other.members, members));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other.members, members));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,pictureId,picture,backgroundId,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(members));
|
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(members));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
|
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, picture: $picture, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ abstract mixin class $SnChatRoomCopyWith<$Res> {
|
|||||||
factory $SnChatRoomCopyWith(SnChatRoom value, $Res Function(SnChatRoom) _then) = _$SnChatRoomCopyWithImpl;
|
factory $SnChatRoomCopyWith(SnChatRoom value, $Res Function(SnChatRoom) _then) = _$SnChatRoomCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? name, String? description, int type, bool isPublic, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
|
String id, String? name, String? description, int type, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -66,17 +66,15 @@ class _$SnChatRoomCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatRoom
|
/// Create a copy of SnChatRoom
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? picture = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as bool,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnCloudFile?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,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 String?,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||||
as SnRealm?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as SnRealm?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -130,7 +128,7 @@ $SnRealmCopyWith<$Res>? get realm {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnChatRoom implements SnChatRoom {
|
class _SnChatRoom implements SnChatRoom {
|
||||||
const _SnChatRoom({required this.id, required this.name, required this.description, required this.type, required this.isPublic, required this.pictureId, required this.picture, required this.backgroundId, required this.background, required this.realmId, required this.realm, required this.createdAt, required this.updatedAt, required this.deletedAt, required final List<SnChatMember>? members}): _members = members;
|
const _SnChatRoom({required this.id, required this.name, required this.description, required this.type, required this.isPublic, required this.picture, required this.background, required this.realmId, required this.realm, required this.createdAt, required this.updatedAt, required this.deletedAt, required final List<SnChatMember>? members}): _members = members;
|
||||||
factory _SnChatRoom.fromJson(Map<String, dynamic> json) => _$SnChatRoomFromJson(json);
|
factory _SnChatRoom.fromJson(Map<String, dynamic> json) => _$SnChatRoomFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -138,9 +136,7 @@ class _SnChatRoom implements SnChatRoom {
|
|||||||
@override final String? description;
|
@override final String? description;
|
||||||
@override final int type;
|
@override final int type;
|
||||||
@override final bool isPublic;
|
@override final bool isPublic;
|
||||||
@override final String? pictureId;
|
|
||||||
@override final SnCloudFile? picture;
|
@override final SnCloudFile? picture;
|
||||||
@override final String? backgroundId;
|
|
||||||
@override final SnCloudFile? background;
|
@override final SnCloudFile? background;
|
||||||
@override final String? realmId;
|
@override final String? realmId;
|
||||||
@override final SnRealm? realm;
|
@override final SnRealm? realm;
|
||||||
@@ -170,16 +166,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other._members, _members));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatRoom&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.type, type) || other.type == type)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.realm, realm) || other.realm == realm)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&const DeepCollectionEquality().equals(other._members, _members));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,pictureId,picture,backgroundId,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_members));
|
int get hashCode => Object.hash(runtimeType,id,name,description,type,isPublic,picture,background,realmId,realm,createdAt,updatedAt,deletedAt,const DeepCollectionEquality().hash(_members));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
|
return 'SnChatRoom(id: $id, name: $name, description: $description, type: $type, isPublic: $isPublic, picture: $picture, background: $background, realmId: $realmId, realm: $realm, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, members: $members)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -190,7 +186,7 @@ abstract mixin class _$SnChatRoomCopyWith<$Res> implements $SnChatRoomCopyWith<$
|
|||||||
factory _$SnChatRoomCopyWith(_SnChatRoom value, $Res Function(_SnChatRoom) _then) = __$SnChatRoomCopyWithImpl;
|
factory _$SnChatRoomCopyWith(_SnChatRoom value, $Res Function(_SnChatRoom) _then) = __$SnChatRoomCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? name, String? description, int type, bool isPublic, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
|
String id, String? name, String? description, int type, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String? realmId, SnRealm? realm, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, List<SnChatMember>? members
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -207,17 +203,15 @@ class __$SnChatRoomCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatRoom
|
/// Create a copy of SnChatRoom
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = freezed,Object? description = freezed,Object? type = null,Object? isPublic = null,Object? picture = freezed,Object? background = freezed,Object? realmId = freezed,Object? realm = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? members = freezed,}) {
|
||||||
return _then(_SnChatRoom(
|
return _then(_SnChatRoom(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: freezed == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
as String?,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String?,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
as int,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as bool,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnCloudFile?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,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 String?,realm: freezed == realm ? _self.realm : realm // ignore: cast_nullable_to_non_nullable
|
||||||
as SnRealm?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as SnRealm?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -271,7 +265,7 @@ $SnRealmCopyWith<$Res>? get realm {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnChatMessage {
|
mixin _$SnChatMessage {
|
||||||
|
|
||||||
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String? get content; String? get nonce; Map<String, dynamic> get meta; List<String> get membersMetioned; DateTime? get editedAt; List<SnCloudFile> get attachments; List<SnChatReaction> get reactions; String? get repliedMessageId; String? get forwardedMessageId; String get senderId; SnChatMember get sender; String get chatRoomId;
|
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String get type; String? get content; String? get nonce; Map<String, dynamic> get meta; List<String> get membersMetioned; DateTime? get editedAt; List<SnCloudFile> get attachments; List<SnChatReaction> get reactions; String? get repliedMessageId; String? get forwardedMessageId; String get senderId; SnChatMember get sender; String get chatRoomId;
|
||||||
/// Create a copy of SnChatMessage
|
/// Create a copy of SnChatMessage
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -284,16 +278,16 @@ $SnChatMessageCopyWith<SnChatMessage> get copyWith => _$SnChatMessageCopyWithImp
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMessage&&(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.content, content) || other.content == content)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&const DeepCollectionEquality().equals(other.meta, meta)&&const DeepCollectionEquality().equals(other.membersMetioned, membersMetioned)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&(identical(other.repliedMessageId, repliedMessageId) || other.repliedMessageId == repliedMessageId)&&(identical(other.forwardedMessageId, forwardedMessageId) || other.forwardedMessageId == forwardedMessageId)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMessage&&(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.type, type) || other.type == type)&&(identical(other.content, content) || other.content == content)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&const DeepCollectionEquality().equals(other.meta, meta)&&const DeepCollectionEquality().equals(other.membersMetioned, membersMetioned)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&const DeepCollectionEquality().equals(other.attachments, attachments)&&const DeepCollectionEquality().equals(other.reactions, reactions)&&(identical(other.repliedMessageId, repliedMessageId) || other.repliedMessageId == repliedMessageId)&&(identical(other.forwardedMessageId, forwardedMessageId) || other.forwardedMessageId == forwardedMessageId)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,content,nonce,const DeepCollectionEquality().hash(meta),const DeepCollectionEquality().hash(membersMetioned),editedAt,const DeepCollectionEquality().hash(attachments),const DeepCollectionEquality().hash(reactions),repliedMessageId,forwardedMessageId,senderId,sender,chatRoomId);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,type,content,nonce,const DeepCollectionEquality().hash(meta),const DeepCollectionEquality().hash(membersMetioned),editedAt,const DeepCollectionEquality().hash(attachments),const DeepCollectionEquality().hash(reactions),repliedMessageId,forwardedMessageId,senderId,sender,chatRoomId);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, content: $content, nonce: $nonce, meta: $meta, membersMetioned: $membersMetioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
|
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, type: $type, content: $content, nonce: $nonce, meta: $meta, membersMetioned: $membersMetioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -304,7 +298,7 @@ abstract mixin class $SnChatMessageCopyWith<$Res> {
|
|||||||
factory $SnChatMessageCopyWith(SnChatMessage value, $Res Function(SnChatMessage) _then) = _$SnChatMessageCopyWithImpl;
|
factory $SnChatMessageCopyWith(SnChatMessage value, $Res Function(SnChatMessage) _then) = _$SnChatMessageCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMetioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMetioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -321,12 +315,13 @@ class _$SnChatMessageCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMessage
|
/// Create a copy of SnChatMessage
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? content = freezed,Object? nonce = freezed,Object? meta = null,Object? membersMetioned = null,Object? editedAt = freezed,Object? attachments = null,Object? reactions = null,Object? repliedMessageId = freezed,Object? forwardedMessageId = freezed,Object? senderId = null,Object? sender = null,Object? chatRoomId = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? type = null,Object? content = freezed,Object? nonce = freezed,Object? meta = null,Object? membersMetioned = null,Object? editedAt = freezed,Object? attachments = null,Object? reactions = null,Object? repliedMessageId = freezed,Object? forwardedMessageId = freezed,Object? senderId = null,Object? sender = null,Object? chatRoomId = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
as DateTime?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as String,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
as String,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
as String?,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,meta: null == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
as String?,meta: null == meta ? _self.meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -359,13 +354,14 @@ $SnChatMemberCopyWith<$Res> get sender {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnChatMessage implements SnChatMessage {
|
class _SnChatMessage implements SnChatMessage {
|
||||||
const _SnChatMessage({required this.createdAt, required this.updatedAt, this.deletedAt, required this.id, this.content, this.nonce, final Map<String, dynamic> meta = const {}, final List<String> membersMetioned = const [], this.editedAt, final List<SnCloudFile> attachments = const [], final List<SnChatReaction> reactions = const [], this.repliedMessageId, this.forwardedMessageId, required this.senderId, required this.sender, required this.chatRoomId}): _meta = meta,_membersMetioned = membersMetioned,_attachments = attachments,_reactions = reactions;
|
const _SnChatMessage({required this.createdAt, required this.updatedAt, this.deletedAt, required this.id, this.type = 'text', this.content, this.nonce, final Map<String, dynamic> meta = const {}, final List<String> membersMetioned = const [], this.editedAt, final List<SnCloudFile> attachments = const [], final List<SnChatReaction> reactions = const [], this.repliedMessageId, this.forwardedMessageId, required this.senderId, required this.sender, required this.chatRoomId}): _meta = meta,_membersMetioned = membersMetioned,_attachments = attachments,_reactions = reactions;
|
||||||
factory _SnChatMessage.fromJson(Map<String, dynamic> json) => _$SnChatMessageFromJson(json);
|
factory _SnChatMessage.fromJson(Map<String, dynamic> json) => _$SnChatMessageFromJson(json);
|
||||||
|
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
@override final String id;
|
@override final String id;
|
||||||
|
@override@JsonKey() final String type;
|
||||||
@override final String? content;
|
@override final String? content;
|
||||||
@override final String? nonce;
|
@override final String? nonce;
|
||||||
final Map<String, dynamic> _meta;
|
final Map<String, dynamic> _meta;
|
||||||
@@ -416,16 +412,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMessage&&(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.content, content) || other.content == content)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&const DeepCollectionEquality().equals(other._meta, _meta)&&const DeepCollectionEquality().equals(other._membersMetioned, _membersMetioned)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&(identical(other.repliedMessageId, repliedMessageId) || other.repliedMessageId == repliedMessageId)&&(identical(other.forwardedMessageId, forwardedMessageId) || other.forwardedMessageId == forwardedMessageId)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMessage&&(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.type, type) || other.type == type)&&(identical(other.content, content) || other.content == content)&&(identical(other.nonce, nonce) || other.nonce == nonce)&&const DeepCollectionEquality().equals(other._meta, _meta)&&const DeepCollectionEquality().equals(other._membersMetioned, _membersMetioned)&&(identical(other.editedAt, editedAt) || other.editedAt == editedAt)&&const DeepCollectionEquality().equals(other._attachments, _attachments)&&const DeepCollectionEquality().equals(other._reactions, _reactions)&&(identical(other.repliedMessageId, repliedMessageId) || other.repliedMessageId == repliedMessageId)&&(identical(other.forwardedMessageId, forwardedMessageId) || other.forwardedMessageId == forwardedMessageId)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,content,nonce,const DeepCollectionEquality().hash(_meta),const DeepCollectionEquality().hash(_membersMetioned),editedAt,const DeepCollectionEquality().hash(_attachments),const DeepCollectionEquality().hash(_reactions),repliedMessageId,forwardedMessageId,senderId,sender,chatRoomId);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,type,content,nonce,const DeepCollectionEquality().hash(_meta),const DeepCollectionEquality().hash(_membersMetioned),editedAt,const DeepCollectionEquality().hash(_attachments),const DeepCollectionEquality().hash(_reactions),repliedMessageId,forwardedMessageId,senderId,sender,chatRoomId);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, content: $content, nonce: $nonce, meta: $meta, membersMetioned: $membersMetioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
|
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, type: $type, content: $content, nonce: $nonce, meta: $meta, membersMetioned: $membersMetioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -436,7 +432,7 @@ abstract mixin class _$SnChatMessageCopyWith<$Res> implements $SnChatMessageCopy
|
|||||||
factory _$SnChatMessageCopyWith(_SnChatMessage value, $Res Function(_SnChatMessage) _then) = __$SnChatMessageCopyWithImpl;
|
factory _$SnChatMessageCopyWith(_SnChatMessage value, $Res Function(_SnChatMessage) _then) = __$SnChatMessageCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMetioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMetioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -453,12 +449,13 @@ class __$SnChatMessageCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMessage
|
/// Create a copy of SnChatMessage
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? content = freezed,Object? nonce = freezed,Object? meta = null,Object? membersMetioned = null,Object? editedAt = freezed,Object? attachments = null,Object? reactions = null,Object? repliedMessageId = freezed,Object? forwardedMessageId = freezed,Object? senderId = null,Object? sender = null,Object? chatRoomId = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? type = null,Object? content = freezed,Object? nonce = freezed,Object? meta = null,Object? membersMetioned = null,Object? editedAt = freezed,Object? attachments = null,Object? reactions = null,Object? repliedMessageId = freezed,Object? forwardedMessageId = freezed,Object? senderId = null,Object? sender = null,Object? chatRoomId = null,}) {
|
||||||
return _then(_SnChatMessage(
|
return _then(_SnChatMessage(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
as DateTime?,id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as String,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
as String,content: freezed == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
as String?,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,meta: null == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
as String?,meta: null == meta ? _self._meta : meta // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -666,7 +663,8 @@ $SnChatMemberCopyWith<$Res> get sender {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnChatMember {
|
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; bool get isBot;
|
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 lastTyped;
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -679,16 +677,16 @@ $SnChatMemberCopyWith<SnChatMember> get copyWith => _$SnChatMemberCopyWithImpl<S
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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.isBot, isBot) || other.isBot == isBot));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,isBot);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,lastTyped);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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, isBot: $isBot)';
|
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)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -699,7 +697,7 @@ abstract mixin class $SnChatMemberCopyWith<$Res> {
|
|||||||
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$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, bool isBot
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -716,7 +714,7 @@ class _$SnChatMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? 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? isBot = null,}) {
|
@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,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -730,8 +728,11 @@ as SnAccount,nick: freezed == nick ? _self.nick : nick // ignore: cast_nullable_
|
|||||||
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
||||||
as int,notify: null == notify ? _self.notify : notify // ignore: cast_nullable_to_non_nullable
|
as int,notify: null == notify ? _self.notify : notify // ignore: cast_nullable_to_non_nullable
|
||||||
as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
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 DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
@@ -763,7 +764,7 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnChatMember implements SnChatMember {
|
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.isBot});
|
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});
|
||||||
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
||||||
|
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@@ -778,7 +779,11 @@ class _SnChatMember implements SnChatMember {
|
|||||||
@override final int role;
|
@override final int role;
|
||||||
@override final int notify;
|
@override final int notify;
|
||||||
@override final DateTime? joinedAt;
|
@override final DateTime? joinedAt;
|
||||||
|
@override final DateTime? breakUntil;
|
||||||
|
@override final DateTime? timeoutUntil;
|
||||||
@override final bool isBot;
|
@override final bool isBot;
|
||||||
|
// Frontend data
|
||||||
|
@override final DateTime? lastTyped;
|
||||||
|
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -793,16 +798,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
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.isBot, isBot) || other.isBot == isBot));
|
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));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,isBot);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,lastTyped);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
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, isBot: $isBot)';
|
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)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -813,7 +818,7 @@ abstract mixin class _$SnChatMemberCopyWith<$Res> implements $SnChatMemberCopyWi
|
|||||||
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$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, bool isBot
|
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
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -830,7 +835,7 @@ class __$SnChatMemberCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatMember
|
/// Create a copy of SnChatMember
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? 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? isBot = null,}) {
|
@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,}) {
|
||||||
return _then(_SnChatMember(
|
return _then(_SnChatMember(
|
||||||
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -844,8 +849,11 @@ as SnAccount,nick: freezed == nick ? _self.nick : nick // ignore: cast_nullable_
|
|||||||
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
as String?,role: null == role ? _self.role : role // ignore: cast_nullable_to_non_nullable
|
||||||
as int,notify: null == notify ? _self.notify : notify // ignore: cast_nullable_to_non_nullable
|
as int,notify: null == notify ? _self.notify : notify // ignore: cast_nullable_to_non_nullable
|
||||||
as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
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 DateTime?,isBot: null == isBot ? _self.isBot : isBot // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1339,7 +1347,7 @@ as DateTime,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$ChatRealtimeJoinResponse {
|
mixin _$ChatRealtimeJoinResponse {
|
||||||
|
|
||||||
String get token; Map<String, dynamic> get config;
|
String get provider; String get endpoint; String get token; String get callId; String get roomName; bool get isAdmin; List<CallParticipant> get participants;
|
||||||
/// Create a copy of ChatRealtimeJoinResponse
|
/// Create a copy of ChatRealtimeJoinResponse
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -1352,16 +1360,16 @@ $ChatRealtimeJoinResponseCopyWith<ChatRealtimeJoinResponse> get copyWith => _$Ch
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChatRealtimeJoinResponse&&(identical(other.token, token) || other.token == token)&&const DeepCollectionEquality().equals(other.config, config));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is ChatRealtimeJoinResponse&&(identical(other.provider, provider) || other.provider == provider)&&(identical(other.endpoint, endpoint) || other.endpoint == endpoint)&&(identical(other.token, token) || other.token == token)&&(identical(other.callId, callId) || other.callId == callId)&&(identical(other.roomName, roomName) || other.roomName == roomName)&&(identical(other.isAdmin, isAdmin) || other.isAdmin == isAdmin)&&const DeepCollectionEquality().equals(other.participants, participants));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,token,const DeepCollectionEquality().hash(config));
|
int get hashCode => Object.hash(runtimeType,provider,endpoint,token,callId,roomName,isAdmin,const DeepCollectionEquality().hash(participants));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ChatRealtimeJoinResponse(token: $token, config: $config)';
|
return 'ChatRealtimeJoinResponse(provider: $provider, endpoint: $endpoint, token: $token, callId: $callId, roomName: $roomName, isAdmin: $isAdmin, participants: $participants)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1372,7 +1380,7 @@ abstract mixin class $ChatRealtimeJoinResponseCopyWith<$Res> {
|
|||||||
factory $ChatRealtimeJoinResponseCopyWith(ChatRealtimeJoinResponse value, $Res Function(ChatRealtimeJoinResponse) _then) = _$ChatRealtimeJoinResponseCopyWithImpl;
|
factory $ChatRealtimeJoinResponseCopyWith(ChatRealtimeJoinResponse value, $Res Function(ChatRealtimeJoinResponse) _then) = _$ChatRealtimeJoinResponseCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String token, Map<String, dynamic> config
|
String provider, String endpoint, String token, String callId, String roomName, bool isAdmin, List<CallParticipant> participants
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -1389,11 +1397,16 @@ class _$ChatRealtimeJoinResponseCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of ChatRealtimeJoinResponse
|
/// Create a copy of ChatRealtimeJoinResponse
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? token = null,Object? config = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? provider = null,Object? endpoint = null,Object? token = null,Object? callId = null,Object? roomName = null,Object? isAdmin = null,Object? participants = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
provider: null == provider ? _self.provider : provider // ignore: cast_nullable_to_non_nullable
|
||||||
as String,config: null == config ? _self.config : config // ignore: cast_nullable_to_non_nullable
|
as String,endpoint: null == endpoint ? _self.endpoint : endpoint // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>,
|
as String,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,callId: null == callId ? _self.callId : callId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,roomName: null == roomName ? _self.roomName : roomName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,isAdmin: null == isAdmin ? _self.isAdmin : isAdmin // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,participants: null == participants ? _self.participants : participants // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<CallParticipant>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1404,15 +1417,20 @@ as Map<String, dynamic>,
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _ChatRealtimeJoinResponse implements ChatRealtimeJoinResponse {
|
class _ChatRealtimeJoinResponse implements ChatRealtimeJoinResponse {
|
||||||
const _ChatRealtimeJoinResponse({required this.token, required final Map<String, dynamic> config}): _config = config;
|
const _ChatRealtimeJoinResponse({required this.provider, required this.endpoint, required this.token, required this.callId, required this.roomName, required this.isAdmin, required final List<CallParticipant> participants}): _participants = participants;
|
||||||
factory _ChatRealtimeJoinResponse.fromJson(Map<String, dynamic> json) => _$ChatRealtimeJoinResponseFromJson(json);
|
factory _ChatRealtimeJoinResponse.fromJson(Map<String, dynamic> json) => _$ChatRealtimeJoinResponseFromJson(json);
|
||||||
|
|
||||||
|
@override final String provider;
|
||||||
|
@override final String endpoint;
|
||||||
@override final String token;
|
@override final String token;
|
||||||
final Map<String, dynamic> _config;
|
@override final String callId;
|
||||||
@override Map<String, dynamic> get config {
|
@override final String roomName;
|
||||||
if (_config is EqualUnmodifiableMapView) return _config;
|
@override final bool isAdmin;
|
||||||
|
final List<CallParticipant> _participants;
|
||||||
|
@override List<CallParticipant> get participants {
|
||||||
|
if (_participants is EqualUnmodifiableListView) return _participants;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableMapView(_config);
|
return EqualUnmodifiableListView(_participants);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1429,16 +1447,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChatRealtimeJoinResponse&&(identical(other.token, token) || other.token == token)&&const DeepCollectionEquality().equals(other._config, _config));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _ChatRealtimeJoinResponse&&(identical(other.provider, provider) || other.provider == provider)&&(identical(other.endpoint, endpoint) || other.endpoint == endpoint)&&(identical(other.token, token) || other.token == token)&&(identical(other.callId, callId) || other.callId == callId)&&(identical(other.roomName, roomName) || other.roomName == roomName)&&(identical(other.isAdmin, isAdmin) || other.isAdmin == isAdmin)&&const DeepCollectionEquality().equals(other._participants, _participants));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,token,const DeepCollectionEquality().hash(_config));
|
int get hashCode => Object.hash(runtimeType,provider,endpoint,token,callId,roomName,isAdmin,const DeepCollectionEquality().hash(_participants));
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'ChatRealtimeJoinResponse(token: $token, config: $config)';
|
return 'ChatRealtimeJoinResponse(provider: $provider, endpoint: $endpoint, token: $token, callId: $callId, roomName: $roomName, isAdmin: $isAdmin, participants: $participants)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1449,7 +1467,7 @@ abstract mixin class _$ChatRealtimeJoinResponseCopyWith<$Res> implements $ChatRe
|
|||||||
factory _$ChatRealtimeJoinResponseCopyWith(_ChatRealtimeJoinResponse value, $Res Function(_ChatRealtimeJoinResponse) _then) = __$ChatRealtimeJoinResponseCopyWithImpl;
|
factory _$ChatRealtimeJoinResponseCopyWith(_ChatRealtimeJoinResponse value, $Res Function(_ChatRealtimeJoinResponse) _then) = __$ChatRealtimeJoinResponseCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String token, Map<String, dynamic> config
|
String provider, String endpoint, String token, String callId, String roomName, bool isAdmin, List<CallParticipant> participants
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -1466,15 +1484,397 @@ class __$ChatRealtimeJoinResponseCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of ChatRealtimeJoinResponse
|
/// Create a copy of ChatRealtimeJoinResponse
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? token = null,Object? config = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? provider = null,Object? endpoint = null,Object? token = null,Object? callId = null,Object? roomName = null,Object? isAdmin = null,Object? participants = null,}) {
|
||||||
return _then(_ChatRealtimeJoinResponse(
|
return _then(_ChatRealtimeJoinResponse(
|
||||||
token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
provider: null == provider ? _self.provider : provider // ignore: cast_nullable_to_non_nullable
|
||||||
as String,config: null == config ? _self._config : config // ignore: cast_nullable_to_non_nullable
|
as String,endpoint: null == endpoint ? _self.endpoint : endpoint // ignore: cast_nullable_to_non_nullable
|
||||||
as Map<String, dynamic>,
|
as String,token: null == token ? _self.token : token // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,callId: null == callId ? _self.callId : callId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,roomName: null == roomName ? _self.roomName : roomName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,isAdmin: null == isAdmin ? _self.isAdmin : isAdmin // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,participants: null == participants ? _self._participants : participants // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<CallParticipant>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$CallParticipant {
|
||||||
|
|
||||||
|
String get identity; String get name; DateTime get joinedAt; String? get accountId; SnChatMember? get profile;
|
||||||
|
/// Create a copy of CallParticipant
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$CallParticipantCopyWith<CallParticipant> get copyWith => _$CallParticipantCopyWithImpl<CallParticipant>(this as CallParticipant, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this CallParticipant to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallParticipant&&(identical(other.identity, identity) || other.identity == identity)&&(identical(other.name, name) || other.name == name)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.profile, profile) || other.profile == profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,identity,name,joinedAt,accountId,profile);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt, accountId: $accountId, profile: $profile)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $CallParticipantCopyWith<$Res> {
|
||||||
|
factory $CallParticipantCopyWith(CallParticipant value, $Res Function(CallParticipant) _then) = _$CallParticipantCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$SnChatMemberCopyWith<$Res>? get profile;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$CallParticipantCopyWithImpl<$Res>
|
||||||
|
implements $CallParticipantCopyWith<$Res> {
|
||||||
|
_$CallParticipantCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final CallParticipant _self;
|
||||||
|
final $Res Function(CallParticipant) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipant
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? identity = null,Object? name = null,Object? joinedAt = null,Object? accountId = freezed,Object? profile = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
identity: null == identity ? _self.identity : identity // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,joinedAt: null == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,profile: freezed == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChatMember?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
/// Create a copy of CallParticipant
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnChatMemberCopyWith<$Res>? get profile {
|
||||||
|
if (_self.profile == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnChatMemberCopyWith<$Res>(_self.profile!, (value) {
|
||||||
|
return _then(_self.copyWith(profile: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _CallParticipant implements CallParticipant {
|
||||||
|
const _CallParticipant({required this.identity, required this.name, required this.joinedAt, required this.accountId, required this.profile});
|
||||||
|
factory _CallParticipant.fromJson(Map<String, dynamic> json) => _$CallParticipantFromJson(json);
|
||||||
|
|
||||||
|
@override final String identity;
|
||||||
|
@override final String name;
|
||||||
|
@override final DateTime joinedAt;
|
||||||
|
@override final String? accountId;
|
||||||
|
@override final SnChatMember? profile;
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipant
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$CallParticipantCopyWith<_CallParticipant> get copyWith => __$CallParticipantCopyWithImpl<_CallParticipant>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$CallParticipantToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallParticipant&&(identical(other.identity, identity) || other.identity == identity)&&(identical(other.name, name) || other.name == name)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.profile, profile) || other.profile == profile));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,identity,name,joinedAt,accountId,profile);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CallParticipant(identity: $identity, name: $name, joinedAt: $joinedAt, accountId: $accountId, profile: $profile)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$CallParticipantCopyWith<$Res> implements $CallParticipantCopyWith<$Res> {
|
||||||
|
factory _$CallParticipantCopyWith(_CallParticipant value, $Res Function(_CallParticipant) _then) = __$CallParticipantCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String identity, String name, DateTime joinedAt, String? accountId, SnChatMember? profile
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $SnChatMemberCopyWith<$Res>? get profile;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$CallParticipantCopyWithImpl<$Res>
|
||||||
|
implements _$CallParticipantCopyWith<$Res> {
|
||||||
|
__$CallParticipantCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _CallParticipant _self;
|
||||||
|
final $Res Function(_CallParticipant) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipant
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? identity = null,Object? name = null,Object? joinedAt = null,Object? accountId = freezed,Object? profile = freezed,}) {
|
||||||
|
return _then(_CallParticipant(
|
||||||
|
identity: null == identity ? _self.identity : identity // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,joinedAt: null == joinedAt ? _self.joinedAt : joinedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,profile: freezed == profile ? _self.profile : profile // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChatMember?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipant
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnChatMemberCopyWith<$Res>? get profile {
|
||||||
|
if (_self.profile == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnChatMemberCopyWith<$Res>(_self.profile!, (value) {
|
||||||
|
return _then(_self.copyWith(profile: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnRealtimeCall {
|
||||||
|
|
||||||
|
String get id; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; DateTime? get endedAt; String get senderId; SnChatMember get sender; String get roomId; SnChatRoom get room; Map<String, dynamic> get upstreamConfig; String? get providerName; String? get sessionId;
|
||||||
|
/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnRealtimeCallCopyWith<SnRealtimeCall> get copyWith => _$SnRealtimeCallCopyWithImpl<SnRealtimeCall>(this as SnRealtimeCall, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnRealtimeCall to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRealtimeCall&&(identical(other.id, id) || other.id == id)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.endedAt, endedAt) || other.endedAt == endedAt)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.roomId, roomId) || other.roomId == roomId)&&(identical(other.room, room) || other.room == room)&&const DeepCollectionEquality().equals(other.upstreamConfig, upstreamConfig)&&(identical(other.providerName, providerName) || other.providerName == providerName)&&(identical(other.sessionId, sessionId) || other.sessionId == sessionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,createdAt,updatedAt,deletedAt,endedAt,senderId,sender,roomId,room,const DeepCollectionEquality().hash(upstreamConfig),providerName,sessionId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnRealtimeCall(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, endedAt: $endedAt, senderId: $senderId, sender: $sender, roomId: $roomId, room: $room, upstreamConfig: $upstreamConfig, providerName: $providerName, sessionId: $sessionId)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnRealtimeCallCopyWith<$Res> {
|
||||||
|
factory $SnRealtimeCallCopyWith(SnRealtimeCall value, $Res Function(SnRealtimeCall) _then) = _$SnRealtimeCallCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String id, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? endedAt, String senderId, SnChatMember sender, String roomId, SnChatRoom room, Map<String, dynamic> upstreamConfig, String? providerName, String? sessionId
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$SnChatMemberCopyWith<$Res> get sender;$SnChatRoomCopyWith<$Res> get room;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnRealtimeCallCopyWithImpl<$Res>
|
||||||
|
implements $SnRealtimeCallCopyWith<$Res> {
|
||||||
|
_$SnRealtimeCallCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnRealtimeCall _self;
|
||||||
|
final $Res Function(SnRealtimeCall) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? endedAt = freezed,Object? senderId = null,Object? sender = null,Object? roomId = null,Object? room = null,Object? upstreamConfig = null,Object? providerName = freezed,Object? sessionId = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,endedAt: freezed == endedAt ? _self.endedAt : endedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,senderId: null == senderId ? _self.senderId : senderId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,sender: null == sender ? _self.sender : sender // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChatMember,roomId: null == roomId ? _self.roomId : roomId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,room: null == room ? _self.room : room // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChatRoom,upstreamConfig: null == upstreamConfig ? _self.upstreamConfig : upstreamConfig // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, dynamic>,providerName: freezed == providerName ? _self.providerName : providerName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,sessionId: freezed == sessionId ? _self.sessionId : sessionId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnChatMemberCopyWith<$Res> get sender {
|
||||||
|
|
||||||
|
return $SnChatMemberCopyWith<$Res>(_self.sender, (value) {
|
||||||
|
return _then(_self.copyWith(sender: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnChatRoomCopyWith<$Res> get room {
|
||||||
|
|
||||||
|
return $SnChatRoomCopyWith<$Res>(_self.room, (value) {
|
||||||
|
return _then(_self.copyWith(room: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnRealtimeCall implements SnRealtimeCall {
|
||||||
|
const _SnRealtimeCall({required this.id, required this.createdAt, required this.updatedAt, required this.deletedAt, required this.endedAt, required this.senderId, required this.sender, required this.roomId, required this.room, required final Map<String, dynamic> upstreamConfig, this.providerName, this.sessionId}): _upstreamConfig = upstreamConfig;
|
||||||
|
factory _SnRealtimeCall.fromJson(Map<String, dynamic> json) => _$SnRealtimeCallFromJson(json);
|
||||||
|
|
||||||
|
@override final String id;
|
||||||
|
@override final DateTime createdAt;
|
||||||
|
@override final DateTime updatedAt;
|
||||||
|
@override final DateTime? deletedAt;
|
||||||
|
@override final DateTime? endedAt;
|
||||||
|
@override final String senderId;
|
||||||
|
@override final SnChatMember sender;
|
||||||
|
@override final String roomId;
|
||||||
|
@override final SnChatRoom room;
|
||||||
|
final Map<String, dynamic> _upstreamConfig;
|
||||||
|
@override Map<String, dynamic> get upstreamConfig {
|
||||||
|
if (_upstreamConfig is EqualUnmodifiableMapView) return _upstreamConfig;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableMapView(_upstreamConfig);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override final String? providerName;
|
||||||
|
@override final String? sessionId;
|
||||||
|
|
||||||
|
/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnRealtimeCallCopyWith<_SnRealtimeCall> get copyWith => __$SnRealtimeCallCopyWithImpl<_SnRealtimeCall>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnRealtimeCallToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnRealtimeCall&&(identical(other.id, id) || other.id == id)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.endedAt, endedAt) || other.endedAt == endedAt)&&(identical(other.senderId, senderId) || other.senderId == senderId)&&(identical(other.sender, sender) || other.sender == sender)&&(identical(other.roomId, roomId) || other.roomId == roomId)&&(identical(other.room, room) || other.room == room)&&const DeepCollectionEquality().equals(other._upstreamConfig, _upstreamConfig)&&(identical(other.providerName, providerName) || other.providerName == providerName)&&(identical(other.sessionId, sessionId) || other.sessionId == sessionId));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,createdAt,updatedAt,deletedAt,endedAt,senderId,sender,roomId,room,const DeepCollectionEquality().hash(_upstreamConfig),providerName,sessionId);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnRealtimeCall(id: $id, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, endedAt: $endedAt, senderId: $senderId, sender: $sender, roomId: $roomId, room: $room, upstreamConfig: $upstreamConfig, providerName: $providerName, sessionId: $sessionId)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnRealtimeCallCopyWith<$Res> implements $SnRealtimeCallCopyWith<$Res> {
|
||||||
|
factory _$SnRealtimeCallCopyWith(_SnRealtimeCall value, $Res Function(_SnRealtimeCall) _then) = __$SnRealtimeCallCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String id, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, DateTime? endedAt, String senderId, SnChatMember sender, String roomId, SnChatRoom room, Map<String, dynamic> upstreamConfig, String? providerName, String? sessionId
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $SnChatMemberCopyWith<$Res> get sender;@override $SnChatRoomCopyWith<$Res> get room;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnRealtimeCallCopyWithImpl<$Res>
|
||||||
|
implements _$SnRealtimeCallCopyWith<$Res> {
|
||||||
|
__$SnRealtimeCallCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnRealtimeCall _self;
|
||||||
|
final $Res Function(_SnRealtimeCall) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? endedAt = freezed,Object? senderId = null,Object? sender = null,Object? roomId = null,Object? room = null,Object? upstreamConfig = null,Object? providerName = freezed,Object? sessionId = freezed,}) {
|
||||||
|
return _then(_SnRealtimeCall(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,endedAt: freezed == endedAt ? _self.endedAt : endedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,senderId: null == senderId ? _self.senderId : senderId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,sender: null == sender ? _self.sender : sender // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChatMember,roomId: null == roomId ? _self.roomId : roomId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,room: null == room ? _self.room : room // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnChatRoom,upstreamConfig: null == upstreamConfig ? _self._upstreamConfig : upstreamConfig // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Map<String, dynamic>,providerName: freezed == providerName ? _self.providerName : providerName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,sessionId: freezed == sessionId ? _self.sessionId : sessionId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnChatMemberCopyWith<$Res> get sender {
|
||||||
|
|
||||||
|
return $SnChatMemberCopyWith<$Res>(_self.sender, (value) {
|
||||||
|
return _then(_self.copyWith(sender: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnRealtimeCall
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnChatRoomCopyWith<$Res> get room {
|
||||||
|
|
||||||
|
return $SnChatRoomCopyWith<$Res>(_self.room, (value) {
|
||||||
|
return _then(_self.copyWith(room: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// dart format on
|
// dart format on
|
||||||
|
|||||||
@@ -12,12 +12,10 @@ _SnChatRoom _$SnChatRoomFromJson(Map<String, dynamic> json) => _SnChatRoom(
|
|||||||
description: json['description'] as String?,
|
description: json['description'] as String?,
|
||||||
type: (json['type'] as num).toInt(),
|
type: (json['type'] as num).toInt(),
|
||||||
isPublic: json['is_public'] as bool,
|
isPublic: json['is_public'] as bool,
|
||||||
pictureId: json['picture_id'] as String?,
|
|
||||||
picture:
|
picture:
|
||||||
json['picture'] == null
|
json['picture'] == null
|
||||||
? null
|
? null
|
||||||
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
||||||
backgroundId: json['background_id'] as String?,
|
|
||||||
background:
|
background:
|
||||||
json['background'] == null
|
json['background'] == null
|
||||||
? null
|
? null
|
||||||
@@ -46,9 +44,7 @@ Map<String, dynamic> _$SnChatRoomToJson(_SnChatRoom instance) =>
|
|||||||
'description': instance.description,
|
'description': instance.description,
|
||||||
'type': instance.type,
|
'type': instance.type,
|
||||||
'is_public': instance.isPublic,
|
'is_public': instance.isPublic,
|
||||||
'picture_id': instance.pictureId,
|
|
||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background_id': instance.backgroundId,
|
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
'realm_id': instance.realmId,
|
'realm_id': instance.realmId,
|
||||||
'realm': instance.realm?.toJson(),
|
'realm': instance.realm?.toJson(),
|
||||||
@@ -67,6 +63,7 @@ _SnChatMessage _$SnChatMessageFromJson(Map<String, dynamic> json) =>
|
|||||||
? null
|
? null
|
||||||
: DateTime.parse(json['deleted_at'] as String),
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
|
type: json['type'] as String? ?? 'text',
|
||||||
content: json['content'] as String?,
|
content: json['content'] as String?,
|
||||||
nonce: json['nonce'] as String?,
|
nonce: json['nonce'] as String?,
|
||||||
meta: json['meta'] as Map<String, dynamic>? ?? const {},
|
meta: json['meta'] as Map<String, dynamic>? ?? const {},
|
||||||
@@ -102,6 +99,7 @@ Map<String, dynamic> _$SnChatMessageToJson(_SnChatMessage instance) =>
|
|||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
|
'type': instance.type,
|
||||||
'content': instance.content,
|
'content': instance.content,
|
||||||
'nonce': instance.nonce,
|
'nonce': instance.nonce,
|
||||||
'meta': instance.meta,
|
'meta': instance.meta,
|
||||||
@@ -168,7 +166,19 @@ _SnChatMember _$SnChatMemberFromJson(Map<String, dynamic> json) =>
|
|||||||
json['joined_at'] == null
|
json['joined_at'] == null
|
||||||
? null
|
? null
|
||||||
: DateTime.parse(json['joined_at'] as String),
|
: DateTime.parse(json['joined_at'] as String),
|
||||||
|
breakUntil:
|
||||||
|
json['break_until'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['break_until'] as String),
|
||||||
|
timeoutUntil:
|
||||||
|
json['timeout_until'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['timeout_until'] as String),
|
||||||
isBot: json['is_bot'] as bool,
|
isBot: json['is_bot'] as bool,
|
||||||
|
lastTyped:
|
||||||
|
json['last_typed'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['last_typed'] as String),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
||||||
@@ -185,7 +195,10 @@ Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
|||||||
'role': instance.role,
|
'role': instance.role,
|
||||||
'notify': instance.notify,
|
'notify': instance.notify,
|
||||||
'joined_at': instance.joinedAt?.toIso8601String(),
|
'joined_at': instance.joinedAt?.toIso8601String(),
|
||||||
|
'break_until': instance.breakUntil?.toIso8601String(),
|
||||||
|
'timeout_until': instance.timeoutUntil?.toIso8601String(),
|
||||||
'is_bot': instance.isBot,
|
'is_bot': instance.isBot,
|
||||||
|
'last_typed': instance.lastTyped?.toIso8601String(),
|
||||||
};
|
};
|
||||||
|
|
||||||
_SnChatSummary _$SnChatSummaryFromJson(Map<String, dynamic> json) =>
|
_SnChatSummary _$SnChatSummaryFromJson(Map<String, dynamic> json) =>
|
||||||
@@ -241,10 +254,85 @@ Map<String, dynamic> _$MessageSyncResponseToJson(
|
|||||||
_ChatRealtimeJoinResponse _$ChatRealtimeJoinResponseFromJson(
|
_ChatRealtimeJoinResponse _$ChatRealtimeJoinResponseFromJson(
|
||||||
Map<String, dynamic> json,
|
Map<String, dynamic> json,
|
||||||
) => _ChatRealtimeJoinResponse(
|
) => _ChatRealtimeJoinResponse(
|
||||||
|
provider: json['provider'] as String,
|
||||||
|
endpoint: json['endpoint'] as String,
|
||||||
token: json['token'] as String,
|
token: json['token'] as String,
|
||||||
config: json['config'] as Map<String, dynamic>,
|
callId: json['call_id'] as String,
|
||||||
|
roomName: json['room_name'] as String,
|
||||||
|
isAdmin: json['is_admin'] as bool,
|
||||||
|
participants:
|
||||||
|
(json['participants'] as List<dynamic>)
|
||||||
|
.map((e) => CallParticipant.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$ChatRealtimeJoinResponseToJson(
|
Map<String, dynamic> _$ChatRealtimeJoinResponseToJson(
|
||||||
_ChatRealtimeJoinResponse instance,
|
_ChatRealtimeJoinResponse instance,
|
||||||
) => <String, dynamic>{'token': instance.token, 'config': instance.config};
|
) => <String, dynamic>{
|
||||||
|
'provider': instance.provider,
|
||||||
|
'endpoint': instance.endpoint,
|
||||||
|
'token': instance.token,
|
||||||
|
'call_id': instance.callId,
|
||||||
|
'room_name': instance.roomName,
|
||||||
|
'is_admin': instance.isAdmin,
|
||||||
|
'participants': instance.participants.map((e) => e.toJson()).toList(),
|
||||||
|
};
|
||||||
|
|
||||||
|
_CallParticipant _$CallParticipantFromJson(Map<String, dynamic> json) =>
|
||||||
|
_CallParticipant(
|
||||||
|
identity: json['identity'] as String,
|
||||||
|
name: json['name'] as String,
|
||||||
|
joinedAt: DateTime.parse(json['joined_at'] as String),
|
||||||
|
accountId: json['account_id'] as String?,
|
||||||
|
profile:
|
||||||
|
json['profile'] == null
|
||||||
|
? null
|
||||||
|
: SnChatMember.fromJson(json['profile'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$CallParticipantToJson(_CallParticipant instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'identity': instance.identity,
|
||||||
|
'name': instance.name,
|
||||||
|
'joined_at': instance.joinedAt.toIso8601String(),
|
||||||
|
'account_id': instance.accountId,
|
||||||
|
'profile': instance.profile?.toJson(),
|
||||||
|
};
|
||||||
|
|
||||||
|
_SnRealtimeCall _$SnRealtimeCallFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnRealtimeCall(
|
||||||
|
id: json['id'] as String,
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
deletedAt:
|
||||||
|
json['deleted_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
endedAt:
|
||||||
|
json['ended_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['ended_at'] as String),
|
||||||
|
senderId: json['sender_id'] as String,
|
||||||
|
sender: SnChatMember.fromJson(json['sender'] as Map<String, dynamic>),
|
||||||
|
roomId: json['room_id'] as String,
|
||||||
|
room: SnChatRoom.fromJson(json['room'] as Map<String, dynamic>),
|
||||||
|
upstreamConfig: json['upstream_config'] as Map<String, dynamic>,
|
||||||
|
providerName: json['provider_name'] as String?,
|
||||||
|
sessionId: json['session_id'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnRealtimeCallToJson(_SnRealtimeCall instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
'ended_at': instance.endedAt?.toIso8601String(),
|
||||||
|
'sender_id': instance.senderId,
|
||||||
|
'sender': instance.sender.toJson(),
|
||||||
|
'room_id': instance.roomId,
|
||||||
|
'room': instance.room.toJson(),
|
||||||
|
'upstream_config': instance.upstreamConfig,
|
||||||
|
'provider_name': instance.providerName,
|
||||||
|
'session_id': instance.sessionId,
|
||||||
|
};
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part 'file.g.dart';
|
|||||||
enum UniversalFileType { image, video, audio, file }
|
enum UniversalFileType { image, video, audio, file }
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class UniversalFile with _$UniversalFile {
|
sealed class UniversalFile with _$UniversalFile {
|
||||||
const UniversalFile._();
|
const UniversalFile._();
|
||||||
|
|
||||||
const factory UniversalFile({
|
const factory UniversalFile({
|
||||||
@@ -31,7 +31,7 @@ abstract class UniversalFile with _$UniversalFile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnCloudFile with _$SnCloudFile {
|
sealed class SnCloudFile with _$SnCloudFile {
|
||||||
const factory SnCloudFile({
|
const factory SnCloudFile({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
required String name,
|
||||||
@@ -43,7 +43,6 @@ abstract class SnCloudFile with _$SnCloudFile {
|
|||||||
required int size,
|
required int size,
|
||||||
required DateTime? uploadedAt,
|
required DateTime? uploadedAt,
|
||||||
required String? uploadedTo,
|
required String? uploadedTo,
|
||||||
required int usedCount,
|
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
|
|||||||
@@ -146,7 +146,7 @@ as UniversalFileType,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnCloudFile {
|
mixin _$SnCloudFile {
|
||||||
|
|
||||||
String get id; String get name; String? get description; Map<String, dynamic>? get fileMeta; Map<String, dynamic>? get userMeta; String? get mimeType; String? get hash; int get size; DateTime? get uploadedAt; String? get uploadedTo; int get usedCount; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String get name; String? get description; Map<String, dynamic>? get fileMeta; Map<String, dynamic>? get userMeta; String? get mimeType; String? get hash; int get size; DateTime? get uploadedAt; String? get uploadedTo; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnCloudFile
|
/// Create a copy of SnCloudFile
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -159,16 +159,16 @@ $SnCloudFileCopyWith<SnCloudFile> get copyWith => _$SnCloudFileCopyWithImpl<SnCl
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.fileMeta, fileMeta)&&const DeepCollectionEquality().equals(other.userMeta, userMeta)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.usedCount, usedCount) || other.usedCount == usedCount)&&(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 SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other.fileMeta, fileMeta)&&const DeepCollectionEquality().equals(other.userMeta, userMeta)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(fileMeta),const DeepCollectionEquality().hash(userMeta),mimeType,hash,size,uploadedAt,uploadedTo,usedCount,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(fileMeta),const DeepCollectionEquality().hash(userMeta),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, usedCount: $usedCount, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -179,7 +179,7 @@ abstract mixin class $SnCloudFileCopyWith<$Res> {
|
|||||||
factory $SnCloudFileCopyWith(SnCloudFile value, $Res Function(SnCloudFile) _then) = _$SnCloudFileCopyWithImpl;
|
factory $SnCloudFileCopyWith(SnCloudFile value, $Res Function(SnCloudFile) _then) = _$SnCloudFileCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, int usedCount, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -196,7 +196,7 @@ class _$SnCloudFileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnCloudFile
|
/// Create a copy of SnCloudFile
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? usedCount = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -208,8 +208,7 @@ as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to
|
|||||||
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
||||||
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,uploadedTo: freezed == uploadedTo ? _self.uploadedTo : uploadedTo // ignore: cast_nullable_to_non_nullable
|
as DateTime?,uploadedTo: freezed == uploadedTo ? _self.uploadedTo : uploadedTo // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,usedCount: null == usedCount ? _self.usedCount : usedCount // ignore: cast_nullable_to_non_nullable
|
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -223,7 +222,7 @@ as DateTime?,
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnCloudFile implements SnCloudFile {
|
class _SnCloudFile implements SnCloudFile {
|
||||||
const _SnCloudFile({required this.id, required this.name, required this.description, required final Map<String, dynamic>? fileMeta, required final Map<String, dynamic>? userMeta, required this.mimeType, required this.hash, required this.size, required this.uploadedAt, required this.uploadedTo, required this.usedCount, required this.createdAt, required this.updatedAt, required this.deletedAt}): _fileMeta = fileMeta,_userMeta = userMeta;
|
const _SnCloudFile({required this.id, required this.name, required this.description, required final Map<String, dynamic>? fileMeta, required final Map<String, dynamic>? userMeta, required this.mimeType, required this.hash, required this.size, required this.uploadedAt, required this.uploadedTo, required this.createdAt, required this.updatedAt, required this.deletedAt}): _fileMeta = fileMeta,_userMeta = userMeta;
|
||||||
factory _SnCloudFile.fromJson(Map<String, dynamic> json) => _$SnCloudFileFromJson(json);
|
factory _SnCloudFile.fromJson(Map<String, dynamic> json) => _$SnCloudFileFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -252,7 +251,6 @@ class _SnCloudFile implements SnCloudFile {
|
|||||||
@override final int size;
|
@override final int size;
|
||||||
@override final DateTime? uploadedAt;
|
@override final DateTime? uploadedAt;
|
||||||
@override final String? uploadedTo;
|
@override final String? uploadedTo;
|
||||||
@override final int usedCount;
|
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
@@ -270,16 +268,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._fileMeta, _fileMeta)&&const DeepCollectionEquality().equals(other._userMeta, _userMeta)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.usedCount, usedCount) || other.usedCount == usedCount)&&(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 _SnCloudFile&&(identical(other.id, id) || other.id == id)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&const DeepCollectionEquality().equals(other._fileMeta, _fileMeta)&&const DeepCollectionEquality().equals(other._userMeta, _userMeta)&&(identical(other.mimeType, mimeType) || other.mimeType == mimeType)&&(identical(other.hash, hash) || other.hash == hash)&&(identical(other.size, size) || other.size == size)&&(identical(other.uploadedAt, uploadedAt) || other.uploadedAt == uploadedAt)&&(identical(other.uploadedTo, uploadedTo) || other.uploadedTo == uploadedTo)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(_fileMeta),const DeepCollectionEquality().hash(_userMeta),mimeType,hash,size,uploadedAt,uploadedTo,usedCount,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,name,description,const DeepCollectionEquality().hash(_fileMeta),const DeepCollectionEquality().hash(_userMeta),mimeType,hash,size,uploadedAt,uploadedTo,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, usedCount: $usedCount, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnCloudFile(id: $id, name: $name, description: $description, fileMeta: $fileMeta, userMeta: $userMeta, mimeType: $mimeType, hash: $hash, size: $size, uploadedAt: $uploadedAt, uploadedTo: $uploadedTo, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -290,7 +288,7 @@ abstract mixin class _$SnCloudFileCopyWith<$Res> implements $SnCloudFileCopyWith
|
|||||||
factory _$SnCloudFileCopyWith(_SnCloudFile value, $Res Function(_SnCloudFile) _then) = __$SnCloudFileCopyWithImpl;
|
factory _$SnCloudFileCopyWith(_SnCloudFile value, $Res Function(_SnCloudFile) _then) = __$SnCloudFileCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, int usedCount, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String name, String? description, Map<String, dynamic>? fileMeta, Map<String, dynamic>? userMeta, String? mimeType, String? hash, int size, DateTime? uploadedAt, String? uploadedTo, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -307,7 +305,7 @@ class __$SnCloudFileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnCloudFile
|
/// Create a copy of SnCloudFile
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? usedCount = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? name = null,Object? description = freezed,Object? fileMeta = freezed,Object? userMeta = freezed,Object? mimeType = freezed,Object? hash = freezed,Object? size = null,Object? uploadedAt = freezed,Object? uploadedTo = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnCloudFile(
|
return _then(_SnCloudFile(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as String,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -319,8 +317,7 @@ as String?,hash: freezed == hash ? _self.hash : hash // ignore: cast_nullable_to
|
|||||||
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
as String?,size: null == size ? _self.size : size // ignore: cast_nullable_to_non_nullable
|
||||||
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
as int,uploadedAt: freezed == uploadedAt ? _self.uploadedAt : uploadedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,uploadedTo: freezed == uploadedTo ? _self.uploadedTo : uploadedTo // ignore: cast_nullable_to_non_nullable
|
as DateTime?,uploadedTo: freezed == uploadedTo ? _self.uploadedTo : uploadedTo // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,usedCount: null == usedCount ? _self.usedCount : usedCount // ignore: cast_nullable_to_non_nullable
|
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as int,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
|
|||||||
@@ -20,7 +20,6 @@ _SnCloudFile _$SnCloudFileFromJson(Map<String, dynamic> json) => _SnCloudFile(
|
|||||||
? null
|
? null
|
||||||
: DateTime.parse(json['uploaded_at'] as String),
|
: DateTime.parse(json['uploaded_at'] as String),
|
||||||
uploadedTo: json['uploaded_to'] as String?,
|
uploadedTo: json['uploaded_to'] as String?,
|
||||||
usedCount: (json['used_count'] as num).toInt(),
|
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
deletedAt:
|
deletedAt:
|
||||||
@@ -41,7 +40,6 @@ Map<String, dynamic> _$SnCloudFileToJson(_SnCloudFile instance) =>
|
|||||||
'size': instance.size,
|
'size': instance.size,
|
||||||
'uploaded_at': instance.uploadedAt?.toIso8601String(),
|
'uploaded_at': instance.uploadedAt?.toIso8601String(),
|
||||||
'uploaded_to': instance.uploadedTo,
|
'uploaded_to': instance.uploadedTo,
|
||||||
'used_count': instance.usedCount,
|
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
|||||||
@@ -1,11 +1,12 @@
|
|||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
|
import 'package:island/models/user.dart';
|
||||||
|
|
||||||
part 'post.freezed.dart';
|
part 'post.freezed.dart';
|
||||||
part 'post.g.dart';
|
part 'post.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnPost with _$SnPost {
|
sealed class SnPost with _$SnPost {
|
||||||
const factory SnPost({
|
const factory SnPost({
|
||||||
required String id,
|
required String id,
|
||||||
required String? title,
|
required String? title,
|
||||||
@@ -43,22 +44,22 @@ abstract class SnPost with _$SnPost {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnPublisher with _$SnPublisher {
|
sealed class SnPublisher with _$SnPublisher {
|
||||||
const factory SnPublisher({
|
const factory SnPublisher({
|
||||||
required String id,
|
required String id,
|
||||||
required int type,
|
required int type,
|
||||||
required String name,
|
required String name,
|
||||||
required String nick,
|
required String nick,
|
||||||
@Default('') String bio,
|
@Default('') String bio,
|
||||||
required String? pictureId,
|
|
||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required String? backgroundId,
|
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
|
required SnAccount? account,
|
||||||
required String? accountId,
|
required String? accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
required String? realmId,
|
required String? realmId,
|
||||||
|
required SnVerificationMark? verification,
|
||||||
}) = _SnPublisher;
|
}) = _SnPublisher;
|
||||||
|
|
||||||
factory SnPublisher.fromJson(Map<String, dynamic> json) =>
|
factory SnPublisher.fromJson(Map<String, dynamic> json) =>
|
||||||
@@ -66,7 +67,7 @@ abstract class SnPublisher with _$SnPublisher {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnPublisherStats with _$SnPublisherStats {
|
sealed class SnPublisherStats with _$SnPublisherStats {
|
||||||
const factory SnPublisherStats({
|
const factory SnPublisherStats({
|
||||||
required int postsCreated,
|
required int postsCreated,
|
||||||
required int stickerPacksCreated,
|
required int stickerPacksCreated,
|
||||||
@@ -80,7 +81,7 @@ abstract class SnPublisherStats with _$SnPublisherStats {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnSubscriptionStatus with _$SnSubscriptionStatus {
|
sealed class SnSubscriptionStatus with _$SnSubscriptionStatus {
|
||||||
const factory SnSubscriptionStatus({
|
const factory SnSubscriptionStatus({
|
||||||
required bool isSubscribed,
|
required bool isSubscribed,
|
||||||
required int publisherId,
|
required int publisherId,
|
||||||
@@ -92,7 +93,7 @@ abstract class SnSubscriptionStatus with _$SnSubscriptionStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class ReactInfo with _$ReactInfo {
|
sealed class ReactInfo with _$ReactInfo {
|
||||||
const factory ReactInfo({required String icon, required int attitude}) =
|
const factory ReactInfo({required String icon, required int attitude}) =
|
||||||
_ReactInfo;
|
_ReactInfo;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -370,7 +370,7 @@ $SnPublisherCopyWith<$Res> get publisher {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnPublisher {
|
mixin _$SnPublisher {
|
||||||
|
|
||||||
String get id; int get type; String get name; String get nick; String get bio; String? get pictureId; SnCloudFile? get picture; String? get backgroundId; SnCloudFile? get background; String? get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String? get realmId;
|
String get id; int get type; String get name; String get nick; String get bio; SnCloudFile? get picture; SnCloudFile? get background; SnAccount? get account; String? get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String? get realmId; SnVerificationMark? get verification;
|
||||||
/// Create a copy of SnPublisher
|
/// Create a copy of SnPublisher
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -383,16 +383,16 @@ $SnPublisherCopyWith<SnPublisher> get copyWith => _$SnPublisherCopyWithImpl<SnPu
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPublisher&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(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)&&(identical(other.realmId, realmId) || other.realmId == realmId));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnPublisher&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.account, account) || other.account == account)&&(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)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.verification, verification) || other.verification == verification));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,type,name,nick,bio,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt,realmId);
|
int get hashCode => Object.hash(runtimeType,id,type,name,nick,bio,picture,background,account,accountId,createdAt,updatedAt,deletedAt,realmId,verification);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId)';
|
return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, picture: $picture, background: $background, account: $account, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId, verification: $verification)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -403,11 +403,11 @@ abstract mixin class $SnPublisherCopyWith<$Res> {
|
|||||||
factory $SnPublisherCopyWith(SnPublisher value, $Res Function(SnPublisher) _then) = _$SnPublisherCopyWithImpl;
|
factory $SnPublisherCopyWith(SnPublisher value, $Res Function(SnPublisher) _then) = _$SnPublisherCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, int type, String name, String nick, String bio, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String? realmId
|
String id, int type, String name, String nick, String bio, SnCloudFile? picture, SnCloudFile? background, SnAccount? account, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String? realmId, SnVerificationMark? verification
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;
|
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnAccountCopyWith<$Res>? get account;$SnVerificationMarkCopyWith<$Res>? get verification;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -420,23 +420,23 @@ class _$SnPublisherCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPublisher
|
/// Create a copy of SnPublisher
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? realmId = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? picture = freezed,Object? background = freezed,Object? account = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? realmId = freezed,Object? verification = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
||||||
as String,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
as String,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
||||||
as String,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as String,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
as SnAccount?,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as 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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
as DateTime?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,
|
as String?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnVerificationMark?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnPublisher
|
/// Create a copy of SnPublisher
|
||||||
@@ -463,6 +463,30 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
||||||
return _then(_self.copyWith(background: value));
|
return _then(_self.copyWith(background: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnPublisher
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountCopyWith<$Res>? get account {
|
||||||
|
if (_self.account == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||||
|
return _then(_self.copyWith(account: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnPublisher
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnVerificationMarkCopyWith<$Res>? get verification {
|
||||||
|
if (_self.verification == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||||
|
return _then(_self.copyWith(verification: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -471,7 +495,7 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnPublisher implements SnPublisher {
|
class _SnPublisher implements SnPublisher {
|
||||||
const _SnPublisher({required this.id, required this.type, required this.name, required this.nick, this.bio = '', required this.pictureId, required this.picture, required this.backgroundId, required this.background, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt, required this.realmId});
|
const _SnPublisher({required this.id, required this.type, required this.name, required this.nick, this.bio = '', required this.picture, required this.background, required this.account, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt, required this.realmId, required this.verification});
|
||||||
factory _SnPublisher.fromJson(Map<String, dynamic> json) => _$SnPublisherFromJson(json);
|
factory _SnPublisher.fromJson(Map<String, dynamic> json) => _$SnPublisherFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -479,15 +503,15 @@ class _SnPublisher implements SnPublisher {
|
|||||||
@override final String name;
|
@override final String name;
|
||||||
@override final String nick;
|
@override final String nick;
|
||||||
@override@JsonKey() final String bio;
|
@override@JsonKey() final String bio;
|
||||||
@override final String? pictureId;
|
|
||||||
@override final SnCloudFile? picture;
|
@override final SnCloudFile? picture;
|
||||||
@override final String? backgroundId;
|
|
||||||
@override final SnCloudFile? background;
|
@override final SnCloudFile? background;
|
||||||
|
@override final SnAccount? account;
|
||||||
@override final String? accountId;
|
@override final String? accountId;
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
@override final String? realmId;
|
@override final String? realmId;
|
||||||
|
@override final SnVerificationMark? verification;
|
||||||
|
|
||||||
/// Create a copy of SnPublisher
|
/// Create a copy of SnPublisher
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -502,16 +526,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPublisher&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(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)&&(identical(other.realmId, realmId) || other.realmId == realmId));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnPublisher&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.name, name) || other.name == name)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.account, account) || other.account == account)&&(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)&&(identical(other.realmId, realmId) || other.realmId == realmId)&&(identical(other.verification, verification) || other.verification == verification));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,type,name,nick,bio,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt,realmId);
|
int get hashCode => Object.hash(runtimeType,id,type,name,nick,bio,picture,background,account,accountId,createdAt,updatedAt,deletedAt,realmId,verification);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId)';
|
return 'SnPublisher(id: $id, type: $type, name: $name, nick: $nick, bio: $bio, picture: $picture, background: $background, account: $account, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, realmId: $realmId, verification: $verification)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -522,11 +546,11 @@ abstract mixin class _$SnPublisherCopyWith<$Res> implements $SnPublisherCopyWith
|
|||||||
factory _$SnPublisherCopyWith(_SnPublisher value, $Res Function(_SnPublisher) _then) = __$SnPublisherCopyWithImpl;
|
factory _$SnPublisherCopyWith(_SnPublisher value, $Res Function(_SnPublisher) _then) = __$SnPublisherCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, int type, String name, String nick, String bio, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String? realmId
|
String id, int type, String name, String nick, String bio, SnCloudFile? picture, SnCloudFile? background, SnAccount? account, String? accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String? realmId, SnVerificationMark? verification
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;
|
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnAccountCopyWith<$Res>? get account;@override $SnVerificationMarkCopyWith<$Res>? get verification;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -539,23 +563,23 @@ class __$SnPublisherCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnPublisher
|
/// Create a copy of SnPublisher
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? realmId = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? name = null,Object? nick = null,Object? bio = null,Object? picture = freezed,Object? background = freezed,Object? account = freezed,Object? accountId = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? realmId = freezed,Object? verification = freezed,}) {
|
||||||
return _then(_SnPublisher(
|
return _then(_SnPublisher(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
as int,name: null == name ? _self.name : name // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
as String,nick: null == nick ? _self.nick : nick // ignore: cast_nullable_to_non_nullable
|
||||||
as String,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
as String,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
||||||
as String,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as String,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,account: freezed == account ? _self.account : account // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
as SnAccount?,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,accountId: freezed == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as 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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
as DateTime?,realmId: freezed == realmId ? _self.realmId : realmId // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,
|
as String?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnVerificationMark?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -583,6 +607,30 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
||||||
return _then(_self.copyWith(background: value));
|
return _then(_self.copyWith(background: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnPublisher
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountCopyWith<$Res>? get account {
|
||||||
|
if (_self.account == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountCopyWith<$Res>(_self.account!, (value) {
|
||||||
|
return _then(_self.copyWith(account: value));
|
||||||
|
});
|
||||||
|
}/// Create a copy of SnPublisher
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnVerificationMarkCopyWith<$Res>? get verification {
|
||||||
|
if (_self.verification == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||||
|
return _then(_self.copyWith(verification: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -100,16 +100,18 @@ _SnPublisher _$SnPublisherFromJson(Map<String, dynamic> json) => _SnPublisher(
|
|||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
nick: json['nick'] as String,
|
nick: json['nick'] as String,
|
||||||
bio: json['bio'] as String? ?? '',
|
bio: json['bio'] as String? ?? '',
|
||||||
pictureId: json['picture_id'] as String?,
|
|
||||||
picture:
|
picture:
|
||||||
json['picture'] == null
|
json['picture'] == null
|
||||||
? null
|
? null
|
||||||
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
||||||
backgroundId: json['background_id'] as String?,
|
|
||||||
background:
|
background:
|
||||||
json['background'] == null
|
json['background'] == null
|
||||||
? null
|
? null
|
||||||
: SnCloudFile.fromJson(json['background'] as Map<String, dynamic>),
|
: SnCloudFile.fromJson(json['background'] as Map<String, dynamic>),
|
||||||
|
account:
|
||||||
|
json['account'] == null
|
||||||
|
? null
|
||||||
|
: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||||
accountId: json['account_id'] as String?,
|
accountId: json['account_id'] as String?,
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
@@ -118,6 +120,12 @@ _SnPublisher _$SnPublisherFromJson(Map<String, dynamic> json) => _SnPublisher(
|
|||||||
? null
|
? null
|
||||||
: DateTime.parse(json['deleted_at'] as String),
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
realmId: json['realm_id'] as String?,
|
realmId: json['realm_id'] as String?,
|
||||||
|
verification:
|
||||||
|
json['verification'] == null
|
||||||
|
? null
|
||||||
|
: SnVerificationMark.fromJson(
|
||||||
|
json['verification'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnPublisherToJson(_SnPublisher instance) =>
|
Map<String, dynamic> _$SnPublisherToJson(_SnPublisher instance) =>
|
||||||
@@ -127,15 +135,15 @@ Map<String, dynamic> _$SnPublisherToJson(_SnPublisher instance) =>
|
|||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'nick': instance.nick,
|
'nick': instance.nick,
|
||||||
'bio': instance.bio,
|
'bio': instance.bio,
|
||||||
'picture_id': instance.pictureId,
|
|
||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background_id': instance.backgroundId,
|
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
|
'account': instance.account?.toJson(),
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
'realm_id': instance.realmId,
|
'realm_id': instance.realmId,
|
||||||
|
'verification': instance.verification?.toJson(),
|
||||||
};
|
};
|
||||||
|
|
||||||
_SnPublisherStats _$SnPublisherStatsFromJson(Map<String, dynamic> json) =>
|
_SnPublisherStats _$SnPublisherStatsFromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part 'realm.freezed.dart';
|
|||||||
part 'realm.g.dart';
|
part 'realm.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnRealm with _$SnRealm {
|
sealed class SnRealm with _$SnRealm {
|
||||||
const factory SnRealm({
|
const factory SnRealm({
|
||||||
required String id,
|
required String id,
|
||||||
required String slug,
|
required String slug,
|
||||||
@@ -16,9 +16,7 @@ abstract class SnRealm with _$SnRealm {
|
|||||||
required DateTime? verifiedAt,
|
required DateTime? verifiedAt,
|
||||||
required bool isCommunity,
|
required bool isCommunity,
|
||||||
required bool isPublic,
|
required bool isPublic,
|
||||||
required String? pictureId,
|
|
||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required String? backgroundId,
|
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
required String accountId,
|
required String accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
@@ -31,7 +29,7 @@ abstract class SnRealm with _$SnRealm {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnRealmMember with _$SnRealmMember {
|
sealed class SnRealmMember with _$SnRealmMember {
|
||||||
const factory SnRealmMember({
|
const factory SnRealmMember({
|
||||||
required String realmId,
|
required String realmId,
|
||||||
required SnRealm? realm,
|
required SnRealm? realm,
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnRealm {
|
mixin _$SnRealm {
|
||||||
|
|
||||||
String get id; String get slug; String get name; String get description; String? get verifiedAs; DateTime? get verifiedAt; bool get isCommunity; bool get isPublic; String? get pictureId; SnCloudFile? get picture; String? get backgroundId; SnCloudFile? get background; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String get slug; String get name; String get description; String? get verifiedAs; DateTime? get verifiedAt; bool get isCommunity; bool get isPublic; SnCloudFile? get picture; SnCloudFile? get background; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnRealm
|
/// Create a copy of SnRealm
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -29,16 +29,16 @@ $SnRealmCopyWith<SnRealm> get copyWith => _$SnRealmCopyWithImpl<SnRealm>(this as
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnRealm&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedAs, verifiedAs) || other.verifiedAs == verifiedAs)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isCommunity, isCommunity) || other.isCommunity == isCommunity)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(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 SnRealm&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedAs, verifiedAs) || other.verifiedAs == verifiedAs)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isCommunity, isCommunity) || other.isCommunity == isCommunity)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(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)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,slug,name,description,verifiedAs,verifiedAt,isCommunity,isPublic,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,slug,name,description,verifiedAs,verifiedAt,isCommunity,isPublic,picture,background,accountId,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnRealm(id: $id, slug: $slug, name: $name, description: $description, verifiedAs: $verifiedAs, verifiedAt: $verifiedAt, isCommunity: $isCommunity, isPublic: $isPublic, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnRealm(id: $id, slug: $slug, name: $name, description: $description, verifiedAs: $verifiedAs, verifiedAt: $verifiedAt, isCommunity: $isCommunity, isPublic: $isPublic, picture: $picture, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -49,7 +49,7 @@ abstract mixin class $SnRealmCopyWith<$Res> {
|
|||||||
factory $SnRealmCopyWith(SnRealm value, $Res Function(SnRealm) _then) = _$SnRealmCopyWithImpl;
|
factory $SnRealmCopyWith(SnRealm value, $Res Function(SnRealm) _then) = _$SnRealmCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String name, String description, String? verifiedAs, DateTime? verifiedAt, bool isCommunity, bool isPublic, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String slug, String name, String description, String? verifiedAs, DateTime? verifiedAt, bool isCommunity, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -66,7 +66,7 @@ class _$SnRealmCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnRealm
|
/// Create a copy of SnRealm
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = null,Object? description = null,Object? verifiedAs = freezed,Object? verifiedAt = freezed,Object? isCommunity = null,Object? isPublic = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? slug = null,Object? name = null,Object? description = null,Object? verifiedAs = freezed,Object? verifiedAt = freezed,Object? isCommunity = null,Object? isPublic = null,Object? picture = freezed,Object? background = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -76,10 +76,8 @@ as String,verifiedAs: freezed == verifiedAs ? _self.verifiedAs : verifiedAs // i
|
|||||||
as String?,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable
|
as String?,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,isCommunity: null == isCommunity ? _self.isCommunity : isCommunity // ignore: cast_nullable_to_non_nullable
|
as DateTime?,isCommunity: null == isCommunity ? _self.isCommunity : isCommunity // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
as bool,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as bool,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnCloudFile?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as 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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -119,7 +117,7 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnRealm implements SnRealm {
|
class _SnRealm implements SnRealm {
|
||||||
const _SnRealm({required this.id, required this.slug, required this.name, required this.description, required this.verifiedAs, required this.verifiedAt, required this.isCommunity, required this.isPublic, required this.pictureId, required this.picture, required this.backgroundId, required this.background, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
const _SnRealm({required this.id, required this.slug, required this.name, required this.description, required this.verifiedAs, required this.verifiedAt, required this.isCommunity, required this.isPublic, required this.picture, required this.background, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||||
factory _SnRealm.fromJson(Map<String, dynamic> json) => _$SnRealmFromJson(json);
|
factory _SnRealm.fromJson(Map<String, dynamic> json) => _$SnRealmFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -130,9 +128,7 @@ class _SnRealm implements SnRealm {
|
|||||||
@override final DateTime? verifiedAt;
|
@override final DateTime? verifiedAt;
|
||||||
@override final bool isCommunity;
|
@override final bool isCommunity;
|
||||||
@override final bool isPublic;
|
@override final bool isPublic;
|
||||||
@override final String? pictureId;
|
|
||||||
@override final SnCloudFile? picture;
|
@override final SnCloudFile? picture;
|
||||||
@override final String? backgroundId;
|
|
||||||
@override final SnCloudFile? background;
|
@override final SnCloudFile? background;
|
||||||
@override final String accountId;
|
@override final String accountId;
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@@ -152,16 +148,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnRealm&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedAs, verifiedAs) || other.verifiedAs == verifiedAs)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isCommunity, isCommunity) || other.isCommunity == isCommunity)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(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 _SnRealm&&(identical(other.id, id) || other.id == id)&&(identical(other.slug, slug) || other.slug == slug)&&(identical(other.name, name) || other.name == name)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedAs, verifiedAs) || other.verifiedAs == verifiedAs)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isCommunity, isCommunity) || other.isCommunity == isCommunity)&&(identical(other.isPublic, isPublic) || other.isPublic == isPublic)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(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)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,slug,name,description,verifiedAs,verifiedAt,isCommunity,isPublic,pictureId,picture,backgroundId,background,accountId,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,slug,name,description,verifiedAs,verifiedAt,isCommunity,isPublic,picture,background,accountId,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnRealm(id: $id, slug: $slug, name: $name, description: $description, verifiedAs: $verifiedAs, verifiedAt: $verifiedAt, isCommunity: $isCommunity, isPublic: $isPublic, pictureId: $pictureId, picture: $picture, backgroundId: $backgroundId, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnRealm(id: $id, slug: $slug, name: $name, description: $description, verifiedAs: $verifiedAs, verifiedAt: $verifiedAt, isCommunity: $isCommunity, isPublic: $isPublic, picture: $picture, background: $background, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -172,7 +168,7 @@ abstract mixin class _$SnRealmCopyWith<$Res> implements $SnRealmCopyWith<$Res> {
|
|||||||
factory _$SnRealmCopyWith(_SnRealm value, $Res Function(_SnRealm) _then) = __$SnRealmCopyWithImpl;
|
factory _$SnRealmCopyWith(_SnRealm value, $Res Function(_SnRealm) _then) = __$SnRealmCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String slug, String name, String description, String? verifiedAs, DateTime? verifiedAt, bool isCommunity, bool isPublic, String? pictureId, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String slug, String name, String description, String? verifiedAs, DateTime? verifiedAt, bool isCommunity, bool isPublic, SnCloudFile? picture, SnCloudFile? background, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -189,7 +185,7 @@ class __$SnRealmCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnRealm
|
/// Create a copy of SnRealm
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = null,Object? description = null,Object? verifiedAs = freezed,Object? verifiedAt = freezed,Object? isCommunity = null,Object? isPublic = null,Object? pictureId = freezed,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? slug = null,Object? name = null,Object? description = null,Object? verifiedAs = freezed,Object? verifiedAt = freezed,Object? isCommunity = null,Object? isPublic = null,Object? picture = freezed,Object? background = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnRealm(
|
return _then(_SnRealm(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
as String,slug: null == slug ? _self.slug : slug // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -199,10 +195,8 @@ as String,verifiedAs: freezed == verifiedAs ? _self.verifiedAs : verifiedAs // i
|
|||||||
as String?,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable
|
as String?,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,isCommunity: null == isCommunity ? _self.isCommunity : isCommunity // ignore: cast_nullable_to_non_nullable
|
as DateTime?,isCommunity: null == isCommunity ? _self.isCommunity : isCommunity // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
as bool,isPublic: null == isPublic ? _self.isPublic : isPublic // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as bool,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnCloudFile?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as 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,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
|||||||
@@ -18,12 +18,10 @@ _SnRealm _$SnRealmFromJson(Map<String, dynamic> json) => _SnRealm(
|
|||||||
: DateTime.parse(json['verified_at'] as String),
|
: DateTime.parse(json['verified_at'] as String),
|
||||||
isCommunity: json['is_community'] as bool,
|
isCommunity: json['is_community'] as bool,
|
||||||
isPublic: json['is_public'] as bool,
|
isPublic: json['is_public'] as bool,
|
||||||
pictureId: json['picture_id'] as String?,
|
|
||||||
picture:
|
picture:
|
||||||
json['picture'] == null
|
json['picture'] == null
|
||||||
? null
|
? null
|
||||||
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
||||||
backgroundId: json['background_id'] as String?,
|
|
||||||
background:
|
background:
|
||||||
json['background'] == null
|
json['background'] == null
|
||||||
? null
|
? null
|
||||||
@@ -46,9 +44,7 @@ Map<String, dynamic> _$SnRealmToJson(_SnRealm instance) => <String, dynamic>{
|
|||||||
'verified_at': instance.verifiedAt?.toIso8601String(),
|
'verified_at': instance.verifiedAt?.toIso8601String(),
|
||||||
'is_community': instance.isCommunity,
|
'is_community': instance.isCommunity,
|
||||||
'is_public': instance.isPublic,
|
'is_public': instance.isPublic,
|
||||||
'picture_id': instance.pictureId,
|
|
||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background_id': instance.backgroundId,
|
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part 'relationship.freezed.dart';
|
|||||||
part 'relationship.g.dart';
|
part 'relationship.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnRelationship with _$SnRelationship {
|
sealed class SnRelationship with _$SnRelationship {
|
||||||
const factory SnRelationship({
|
const factory SnRelationship({
|
||||||
required DateTime? createdAt,
|
required DateTime? createdAt,
|
||||||
required DateTime? updatedAt,
|
required DateTime? updatedAt,
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part 'sticker.freezed.dart';
|
|||||||
part 'sticker.g.dart';
|
part 'sticker.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnSticker with _$SnSticker {
|
sealed class SnSticker with _$SnSticker {
|
||||||
const factory SnSticker({
|
const factory SnSticker({
|
||||||
required String id,
|
required String id,
|
||||||
required String slug,
|
required String slug,
|
||||||
@@ -24,7 +24,7 @@ abstract class SnSticker with _$SnSticker {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnStickerPack with _$SnStickerPack {
|
sealed class SnStickerPack with _$SnStickerPack {
|
||||||
const factory SnStickerPack({
|
const factory SnStickerPack({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
required String name,
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ part 'user.freezed.dart';
|
|||||||
part 'user.g.dart';
|
part 'user.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnAccount with _$SnAccount {
|
sealed class SnAccount with _$SnAccount {
|
||||||
const factory SnAccount({
|
const factory SnAccount({
|
||||||
required String id,
|
required String id,
|
||||||
required String name,
|
required String name,
|
||||||
@@ -24,20 +24,19 @@ abstract class SnAccount with _$SnAccount {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnAccountProfile with _$SnAccountProfile {
|
sealed class SnAccountProfile with _$SnAccountProfile {
|
||||||
const factory SnAccountProfile({
|
const factory SnAccountProfile({
|
||||||
required String id,
|
required String id,
|
||||||
required String? firstName,
|
required String? firstName,
|
||||||
required String? middleName,
|
required String? middleName,
|
||||||
required String? lastName,
|
required String? lastName,
|
||||||
@Default('') String bio,
|
@Default('') String bio,
|
||||||
required String? pictureId,
|
|
||||||
required int experience,
|
required int experience,
|
||||||
required int level,
|
required int level,
|
||||||
required double levelingProgress,
|
required double levelingProgress,
|
||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required String? backgroundId,
|
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
|
required SnVerificationMark? verification,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
@@ -48,7 +47,7 @@ abstract class SnAccountProfile with _$SnAccountProfile {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnAccountStatus with _$SnAccountStatus {
|
sealed class SnAccountStatus with _$SnAccountStatus {
|
||||||
const factory SnAccountStatus({
|
const factory SnAccountStatus({
|
||||||
required String id,
|
required String id,
|
||||||
required int attitude,
|
required int attitude,
|
||||||
@@ -69,7 +68,7 @@ abstract class SnAccountStatus with _$SnAccountStatus {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnAccountBadge with _$SnAccountBadge {
|
sealed class SnAccountBadge with _$SnAccountBadge {
|
||||||
const factory SnAccountBadge({
|
const factory SnAccountBadge({
|
||||||
required String id,
|
required String id,
|
||||||
required String type,
|
required String type,
|
||||||
@@ -88,7 +87,25 @@ abstract class SnAccountBadge with _$SnAccountBadge {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnNotification with _$SnNotification {
|
sealed class SnContactMethod with _$SnContactMethod {
|
||||||
|
const factory SnContactMethod({
|
||||||
|
required String id,
|
||||||
|
required int type,
|
||||||
|
required DateTime? verifiedAt,
|
||||||
|
required bool isPrimary,
|
||||||
|
required String content,
|
||||||
|
required String accountId,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
required DateTime? deletedAt,
|
||||||
|
}) = _SnContactMethod;
|
||||||
|
|
||||||
|
factory SnContactMethod.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnContactMethodFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnNotification with _$SnNotification {
|
||||||
const factory SnNotification({
|
const factory SnNotification({
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
@@ -107,3 +124,16 @@ abstract class SnNotification with _$SnNotification {
|
|||||||
factory SnNotification.fromJson(Map<String, dynamic> json) =>
|
factory SnNotification.fromJson(Map<String, dynamic> json) =>
|
||||||
_$SnNotificationFromJson(json);
|
_$SnNotificationFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnVerificationMark with _$SnVerificationMark {
|
||||||
|
const factory SnVerificationMark({
|
||||||
|
required int type,
|
||||||
|
required String? title,
|
||||||
|
required String? description,
|
||||||
|
required String? verifiedBy,
|
||||||
|
}) = _SnVerificationMark;
|
||||||
|
|
||||||
|
factory SnVerificationMark.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnVerificationMarkFromJson(json);
|
||||||
|
}
|
||||||
|
|||||||
@@ -200,7 +200,7 @@ $SnAccountProfileCopyWith<$Res> get profile {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAccountProfile {
|
mixin _$SnAccountProfile {
|
||||||
|
|
||||||
String get id; String? get firstName; String? get middleName; String? get lastName; String get bio; String? get pictureId; int get experience; int get level; double get levelingProgress; SnCloudFile? get picture; String? get backgroundId; SnCloudFile? get background; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String? get firstName; String? get middleName; String? get lastName; String get bio; int get experience; int get level; double get levelingProgress; SnCloudFile? get picture; SnCloudFile? get background; SnVerificationMark? get verification; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnAccountProfile
|
/// Create a copy of SnAccountProfile
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -213,16 +213,16 @@ $SnAccountProfileCopyWith<SnAccountProfile> get copyWith => _$SnAccountProfileCo
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,firstName,middleName,lastName,bio,pictureId,experience,level,levelingProgress,picture,backgroundId,background,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,firstName,middleName,lastName,bio,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, pictureId: $pictureId, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, backgroundId: $backgroundId, background: $background, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -233,11 +233,11 @@ abstract mixin class $SnAccountProfileCopyWith<$Res> {
|
|||||||
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
factory $SnAccountProfileCopyWith(SnAccountProfile value, $Res Function(SnAccountProfile) _then) = _$SnAccountProfileCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? firstName, String? middleName, String? lastName, String bio, String? pictureId, int experience, int level, double levelingProgress, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String? firstName, String? middleName, String? lastName, String bio, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;
|
$SnCloudFileCopyWith<$Res>? get picture;$SnCloudFileCopyWith<$Res>? get background;$SnVerificationMarkCopyWith<$Res>? get verification;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -250,21 +250,20 @@ class _$SnAccountProfileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccountProfile
|
/// Create a copy of SnAccountProfile
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? pictureId = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,middleName: freezed == middleName ? _self.middleName : middleName // ignore: cast_nullable_to_non_nullable
|
as String?,middleName: freezed == middleName ? _self.middleName : middleName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
as String?,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
||||||
as String,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as String,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
|
||||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||||
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
||||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as SnVerificationMark?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -294,6 +293,18 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
||||||
return _then(_self.copyWith(background: value));
|
return _then(_self.copyWith(background: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnAccountProfile
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnVerificationMarkCopyWith<$Res>? get verification {
|
||||||
|
if (_self.verification == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||||
|
return _then(_self.copyWith(verification: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -302,7 +313,7 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnAccountProfile implements SnAccountProfile {
|
class _SnAccountProfile implements SnAccountProfile {
|
||||||
const _SnAccountProfile({required this.id, required this.firstName, required this.middleName, required this.lastName, this.bio = '', required this.pictureId, required this.experience, required this.level, required this.levelingProgress, required this.picture, required this.backgroundId, required this.background, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
const _SnAccountProfile({required this.id, required this.firstName, required this.middleName, required this.lastName, this.bio = '', required this.experience, required this.level, required this.levelingProgress, required this.picture, required this.background, required this.verification, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||||
factory _SnAccountProfile.fromJson(Map<String, dynamic> json) => _$SnAccountProfileFromJson(json);
|
factory _SnAccountProfile.fromJson(Map<String, dynamic> json) => _$SnAccountProfileFromJson(json);
|
||||||
|
|
||||||
@override final String id;
|
@override final String id;
|
||||||
@@ -310,13 +321,12 @@ class _SnAccountProfile implements SnAccountProfile {
|
|||||||
@override final String? middleName;
|
@override final String? middleName;
|
||||||
@override final String? lastName;
|
@override final String? lastName;
|
||||||
@override@JsonKey() final String bio;
|
@override@JsonKey() final String bio;
|
||||||
@override final String? pictureId;
|
|
||||||
@override final int experience;
|
@override final int experience;
|
||||||
@override final int level;
|
@override final int level;
|
||||||
@override final double levelingProgress;
|
@override final double levelingProgress;
|
||||||
@override final SnCloudFile? picture;
|
@override final SnCloudFile? picture;
|
||||||
@override final String? backgroundId;
|
|
||||||
@override final SnCloudFile? background;
|
@override final SnCloudFile? background;
|
||||||
|
@override final SnVerificationMark? verification;
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@override final DateTime? deletedAt;
|
@override final DateTime? deletedAt;
|
||||||
@@ -334,16 +344,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.pictureId, pictureId) || other.pictureId == pictureId)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.backgroundId, backgroundId) || other.backgroundId == backgroundId)&&(identical(other.background, background) || other.background == background)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountProfile&&(identical(other.id, id) || other.id == id)&&(identical(other.firstName, firstName) || other.firstName == firstName)&&(identical(other.middleName, middleName) || other.middleName == middleName)&&(identical(other.lastName, lastName) || other.lastName == lastName)&&(identical(other.bio, bio) || other.bio == bio)&&(identical(other.experience, experience) || other.experience == experience)&&(identical(other.level, level) || other.level == level)&&(identical(other.levelingProgress, levelingProgress) || other.levelingProgress == levelingProgress)&&(identical(other.picture, picture) || other.picture == picture)&&(identical(other.background, background) || other.background == background)&&(identical(other.verification, verification) || other.verification == verification)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,id,firstName,middleName,lastName,bio,pictureId,experience,level,levelingProgress,picture,backgroundId,background,createdAt,updatedAt,deletedAt);
|
int get hashCode => Object.hash(runtimeType,id,firstName,middleName,lastName,bio,experience,level,levelingProgress,picture,background,verification,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, pictureId: $pictureId, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, backgroundId: $backgroundId, background: $background, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
return 'SnAccountProfile(id: $id, firstName: $firstName, middleName: $middleName, lastName: $lastName, bio: $bio, experience: $experience, level: $level, levelingProgress: $levelingProgress, picture: $picture, background: $background, verification: $verification, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -354,11 +364,11 @@ abstract mixin class _$SnAccountProfileCopyWith<$Res> implements $SnAccountProfi
|
|||||||
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
factory _$SnAccountProfileCopyWith(_SnAccountProfile value, $Res Function(_SnAccountProfile) _then) = __$SnAccountProfileCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? firstName, String? middleName, String? lastName, String bio, String? pictureId, int experience, int level, double levelingProgress, SnCloudFile? picture, String? backgroundId, SnCloudFile? background, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String? firstName, String? middleName, String? lastName, String bio, int experience, int level, double levelingProgress, SnCloudFile? picture, SnCloudFile? background, SnVerificationMark? verification, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;
|
@override $SnCloudFileCopyWith<$Res>? get picture;@override $SnCloudFileCopyWith<$Res>? get background;@override $SnVerificationMarkCopyWith<$Res>? get verification;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -371,21 +381,20 @@ class __$SnAccountProfileCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAccountProfile
|
/// Create a copy of SnAccountProfile
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? pictureId = freezed,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? backgroundId = freezed,Object? background = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? firstName = freezed,Object? middleName = freezed,Object? lastName = freezed,Object? bio = null,Object? experience = null,Object? level = null,Object? levelingProgress = null,Object? picture = freezed,Object? background = freezed,Object? verification = freezed,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnAccountProfile(
|
return _then(_SnAccountProfile(
|
||||||
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
as String,firstName: freezed == firstName ? _self.firstName : firstName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,middleName: freezed == middleName ? _self.middleName : middleName // ignore: cast_nullable_to_non_nullable
|
as String?,middleName: freezed == middleName ? _self.middleName : middleName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
as String?,lastName: freezed == lastName ? _self.lastName : lastName // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
as String?,bio: null == bio ? _self.bio : bio // ignore: cast_nullable_to_non_nullable
|
||||||
as String,pictureId: freezed == pictureId ? _self.pictureId : pictureId // ignore: cast_nullable_to_non_nullable
|
as String,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,experience: null == experience ? _self.experience : experience // ignore: cast_nullable_to_non_nullable
|
|
||||||
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
as int,level: null == level ? _self.level : level // ignore: cast_nullable_to_non_nullable
|
||||||
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
as int,levelingProgress: null == levelingProgress ? _self.levelingProgress : levelingProgress // ignore: cast_nullable_to_non_nullable
|
||||||
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
as double,picture: freezed == picture ? _self.picture : picture // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,backgroundId: freezed == backgroundId ? _self.backgroundId : backgroundId // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,background: freezed == background ? _self.background : background // ignore: cast_nullable_to_non_nullable
|
as SnCloudFile?,verification: freezed == verification ? _self.verification : verification // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCloudFile?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as SnVerificationMark?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
@@ -416,6 +425,18 @@ $SnCloudFileCopyWith<$Res>? get background {
|
|||||||
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
return $SnCloudFileCopyWith<$Res>(_self.background!, (value) {
|
||||||
return _then(_self.copyWith(background: value));
|
return _then(_self.copyWith(background: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnAccountProfile
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnVerificationMarkCopyWith<$Res>? get verification {
|
||||||
|
if (_self.verification == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnVerificationMarkCopyWith<$Res>(_self.verification!, (value) {
|
||||||
|
return _then(_self.copyWith(verification: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -752,6 +773,163 @@ as DateTime?,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnContactMethod {
|
||||||
|
|
||||||
|
String get id; int get type; DateTime? get verifiedAt; bool get isPrimary; String get content; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
|
/// Create a copy of SnContactMethod
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnContactMethodCopyWith<SnContactMethod> get copyWith => _$SnContactMethodCopyWithImpl<SnContactMethod>(this as SnContactMethod, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnContactMethod to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnContactMethod&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isPrimary, isPrimary) || other.isPrimary == isPrimary)&&(identical(other.content, content) || other.content == content)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,type,verifiedAt,isPrimary,content,accountId,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnContactMethodCopyWith<$Res> {
|
||||||
|
factory $SnContactMethodCopyWith(SnContactMethod value, $Res Function(SnContactMethod) _then) = _$SnContactMethodCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnContactMethodCopyWithImpl<$Res>
|
||||||
|
implements $SnContactMethodCopyWith<$Res> {
|
||||||
|
_$SnContactMethodCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnContactMethod _self;
|
||||||
|
final $Res Function(SnContactMethod) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnContactMethod
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? type = null,Object? verifiedAt = freezed,Object? isPrimary = null,Object? content = null,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,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,isPrimary: null == isPrimary ? _self.isPrimary : isPrimary // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,content: null == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnContactMethod implements SnContactMethod {
|
||||||
|
const _SnContactMethod({required this.id, required this.type, required this.verifiedAt, required this.isPrimary, required this.content, required this.accountId, required this.createdAt, required this.updatedAt, required this.deletedAt});
|
||||||
|
factory _SnContactMethod.fromJson(Map<String, dynamic> json) => _$SnContactMethodFromJson(json);
|
||||||
|
|
||||||
|
@override final String id;
|
||||||
|
@override final int type;
|
||||||
|
@override final DateTime? verifiedAt;
|
||||||
|
@override final bool isPrimary;
|
||||||
|
@override final String content;
|
||||||
|
@override final String accountId;
|
||||||
|
@override final DateTime createdAt;
|
||||||
|
@override final DateTime updatedAt;
|
||||||
|
@override final DateTime? deletedAt;
|
||||||
|
|
||||||
|
/// Create a copy of SnContactMethod
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnContactMethodCopyWith<_SnContactMethod> get copyWith => __$SnContactMethodCopyWithImpl<_SnContactMethod>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnContactMethodToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnContactMethod&&(identical(other.id, id) || other.id == id)&&(identical(other.type, type) || other.type == type)&&(identical(other.verifiedAt, verifiedAt) || other.verifiedAt == verifiedAt)&&(identical(other.isPrimary, isPrimary) || other.isPrimary == isPrimary)&&(identical(other.content, content) || other.content == content)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,type,verifiedAt,isPrimary,content,accountId,createdAt,updatedAt,deletedAt);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnContactMethod(id: $id, type: $type, verifiedAt: $verifiedAt, isPrimary: $isPrimary, content: $content, accountId: $accountId, createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnContactMethodCopyWith<$Res> implements $SnContactMethodCopyWith<$Res> {
|
||||||
|
factory _$SnContactMethodCopyWith(_SnContactMethod value, $Res Function(_SnContactMethod) _then) = __$SnContactMethodCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String id, int type, DateTime? verifiedAt, bool isPrimary, String content, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnContactMethodCopyWithImpl<$Res>
|
||||||
|
implements _$SnContactMethodCopyWith<$Res> {
|
||||||
|
__$SnContactMethodCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnContactMethod _self;
|
||||||
|
final $Res Function(_SnContactMethod) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnContactMethod
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? type = null,Object? verifiedAt = freezed,Object? isPrimary = null,Object? content = null,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
|
return _then(_SnContactMethod(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,verifiedAt: freezed == verifiedAt ? _self.verifiedAt : verifiedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,isPrimary: null == isPrimary ? _self.isPrimary : isPrimary // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,content: null == content ? _self.content : content // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,deletedAt: freezed == deletedAt ? _self.deletedAt : deletedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnNotification {
|
mixin _$SnNotification {
|
||||||
|
|
||||||
@@ -921,6 +1099,148 @@ as String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnVerificationMark {
|
||||||
|
|
||||||
|
int get type; String? get title; String? get description; String? get verifiedBy;
|
||||||
|
/// Create a copy of SnVerificationMark
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnVerificationMarkCopyWith<SnVerificationMark> get copyWith => _$SnVerificationMarkCopyWithImpl<SnVerificationMark>(this as SnVerificationMark, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnVerificationMark to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnVerificationMark&&(identical(other.type, type) || other.type == type)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedBy, verifiedBy) || other.verifiedBy == verifiedBy));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,type,title,description,verifiedBy);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnVerificationMark(type: $type, title: $title, description: $description, verifiedBy: $verifiedBy)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnVerificationMarkCopyWith<$Res> {
|
||||||
|
factory $SnVerificationMarkCopyWith(SnVerificationMark value, $Res Function(SnVerificationMark) _then) = _$SnVerificationMarkCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
int type, String? title, String? description, String? verifiedBy
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnVerificationMarkCopyWithImpl<$Res>
|
||||||
|
implements $SnVerificationMarkCopyWith<$Res> {
|
||||||
|
_$SnVerificationMarkCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnVerificationMark _self;
|
||||||
|
final $Res Function(SnVerificationMark) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnVerificationMark
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? title = freezed,Object? description = freezed,Object? verifiedBy = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,title: freezed == 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?,verifiedBy: freezed == verifiedBy ? _self.verifiedBy : verifiedBy // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnVerificationMark implements SnVerificationMark {
|
||||||
|
const _SnVerificationMark({required this.type, required this.title, required this.description, required this.verifiedBy});
|
||||||
|
factory _SnVerificationMark.fromJson(Map<String, dynamic> json) => _$SnVerificationMarkFromJson(json);
|
||||||
|
|
||||||
|
@override final int type;
|
||||||
|
@override final String? title;
|
||||||
|
@override final String? description;
|
||||||
|
@override final String? verifiedBy;
|
||||||
|
|
||||||
|
/// Create a copy of SnVerificationMark
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnVerificationMarkCopyWith<_SnVerificationMark> get copyWith => __$SnVerificationMarkCopyWithImpl<_SnVerificationMark>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnVerificationMarkToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnVerificationMark&&(identical(other.type, type) || other.type == type)&&(identical(other.title, title) || other.title == title)&&(identical(other.description, description) || other.description == description)&&(identical(other.verifiedBy, verifiedBy) || other.verifiedBy == verifiedBy));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,type,title,description,verifiedBy);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnVerificationMark(type: $type, title: $title, description: $description, verifiedBy: $verifiedBy)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnVerificationMarkCopyWith<$Res> implements $SnVerificationMarkCopyWith<$Res> {
|
||||||
|
factory _$SnVerificationMarkCopyWith(_SnVerificationMark value, $Res Function(_SnVerificationMark) _then) = __$SnVerificationMarkCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
int type, String? title, String? description, String? verifiedBy
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnVerificationMarkCopyWithImpl<$Res>
|
||||||
|
implements _$SnVerificationMarkCopyWith<$Res> {
|
||||||
|
__$SnVerificationMarkCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnVerificationMark _self;
|
||||||
|
final $Res Function(_SnVerificationMark) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnVerificationMark
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? title = freezed,Object? description = freezed,Object? verifiedBy = freezed,}) {
|
||||||
|
return _then(_SnVerificationMark(
|
||||||
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int,title: freezed == 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?,verifiedBy: freezed == verifiedBy ? _self.verifiedBy : verifiedBy // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// dart format on
|
// dart format on
|
||||||
|
|||||||
@@ -47,7 +47,6 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
|||||||
middleName: json['middle_name'] as String?,
|
middleName: json['middle_name'] as String?,
|
||||||
lastName: json['last_name'] as String?,
|
lastName: json['last_name'] as String?,
|
||||||
bio: json['bio'] as String? ?? '',
|
bio: json['bio'] as String? ?? '',
|
||||||
pictureId: json['picture_id'] as String?,
|
|
||||||
experience: (json['experience'] as num).toInt(),
|
experience: (json['experience'] as num).toInt(),
|
||||||
level: (json['level'] as num).toInt(),
|
level: (json['level'] as num).toInt(),
|
||||||
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
||||||
@@ -55,13 +54,18 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
|||||||
json['picture'] == null
|
json['picture'] == null
|
||||||
? null
|
? null
|
||||||
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
: SnCloudFile.fromJson(json['picture'] as Map<String, dynamic>),
|
||||||
backgroundId: json['background_id'] as String?,
|
|
||||||
background:
|
background:
|
||||||
json['background'] == null
|
json['background'] == null
|
||||||
? null
|
? null
|
||||||
: SnCloudFile.fromJson(
|
: SnCloudFile.fromJson(
|
||||||
json['background'] as Map<String, dynamic>,
|
json['background'] as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
|
verification:
|
||||||
|
json['verification'] == null
|
||||||
|
? null
|
||||||
|
: SnVerificationMark.fromJson(
|
||||||
|
json['verification'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
updatedAt: DateTime.parse(json['updated_at'] as String),
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
deletedAt:
|
deletedAt:
|
||||||
@@ -77,13 +81,12 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
|||||||
'middle_name': instance.middleName,
|
'middle_name': instance.middleName,
|
||||||
'last_name': instance.lastName,
|
'last_name': instance.lastName,
|
||||||
'bio': instance.bio,
|
'bio': instance.bio,
|
||||||
'picture_id': instance.pictureId,
|
|
||||||
'experience': instance.experience,
|
'experience': instance.experience,
|
||||||
'level': instance.level,
|
'level': instance.level,
|
||||||
'leveling_progress': instance.levelingProgress,
|
'leveling_progress': instance.levelingProgress,
|
||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background_id': instance.backgroundId,
|
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
|
'verification': instance.verification?.toJson(),
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
'updated_at': instance.updatedAt.toIso8601String(),
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
@@ -161,6 +164,38 @@ Map<String, dynamic> _$SnAccountBadgeToJson(_SnAccountBadge instance) =>
|
|||||||
'deleted_at': instance.deletedAt?.toIso8601String(),
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_SnContactMethod _$SnContactMethodFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnContactMethod(
|
||||||
|
id: json['id'] as String,
|
||||||
|
type: (json['type'] as num).toInt(),
|
||||||
|
verifiedAt:
|
||||||
|
json['verified_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['verified_at'] as String),
|
||||||
|
isPrimary: json['is_primary'] as bool,
|
||||||
|
content: json['content'] as String,
|
||||||
|
accountId: json['account_id'] as String,
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
deletedAt:
|
||||||
|
json['deleted_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnContactMethodToJson(_SnContactMethod instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'type': instance.type,
|
||||||
|
'verified_at': instance.verifiedAt?.toIso8601String(),
|
||||||
|
'is_primary': instance.isPrimary,
|
||||||
|
'content': instance.content,
|
||||||
|
'account_id': instance.accountId,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
};
|
||||||
|
|
||||||
_SnNotification _$SnNotificationFromJson(Map<String, dynamic> json) =>
|
_SnNotification _$SnNotificationFromJson(Map<String, dynamic> json) =>
|
||||||
_SnNotification(
|
_SnNotification(
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
@@ -198,3 +233,19 @@ Map<String, dynamic> _$SnNotificationToJson(_SnNotification instance) =>
|
|||||||
'viewed_at': instance.viewedAt?.toIso8601String(),
|
'viewed_at': instance.viewedAt?.toIso8601String(),
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_SnVerificationMark _$SnVerificationMarkFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnVerificationMark(
|
||||||
|
type: (json['type'] as num).toInt(),
|
||||||
|
title: json['title'] as String?,
|
||||||
|
description: json['description'] as String?,
|
||||||
|
verifiedBy: json['verified_by'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnVerificationMarkToJson(_SnVerificationMark instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'type': instance.type,
|
||||||
|
'title': instance.title,
|
||||||
|
'description': instance.description,
|
||||||
|
'verified_by': instance.verifiedBy,
|
||||||
|
};
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ part 'wallet.freezed.dart';
|
|||||||
part 'wallet.g.dart';
|
part 'wallet.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnWallet with _$SnWallet {
|
sealed class SnWallet with _$SnWallet {
|
||||||
const factory SnWallet({
|
const factory SnWallet({
|
||||||
required String id,
|
required String id,
|
||||||
required List<SnWalletPocket> pockets,
|
required List<SnWalletPocket> pockets,
|
||||||
@@ -21,7 +21,7 @@ abstract class SnWallet with _$SnWallet {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnWalletPocket with _$SnWalletPocket {
|
sealed class SnWalletPocket with _$SnWalletPocket {
|
||||||
const factory SnWalletPocket({
|
const factory SnWalletPocket({
|
||||||
required String id,
|
required String id,
|
||||||
required String currency,
|
required String currency,
|
||||||
@@ -37,7 +37,7 @@ abstract class SnWalletPocket with _$SnWalletPocket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class SnTransaction with _$SnTransaction {
|
sealed class SnTransaction with _$SnTransaction {
|
||||||
const factory SnTransaction({
|
const factory SnTransaction({
|
||||||
required String id,
|
required String id,
|
||||||
required String currency,
|
required String currency,
|
||||||
|
|||||||
352
lib/pods/call.dart
Normal file
352
lib/pods/call.dart
Normal file
@@ -0,0 +1,352 @@
|
|||||||
|
import 'package:island/pods/userinfo.dart';
|
||||||
|
import 'package:island/screens/chat/chat.dart';
|
||||||
|
import 'package:island/widgets/chat/call_button.dart';
|
||||||
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'dart:async';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/models/chat.dart';
|
||||||
|
import 'package:island/pods/websocket.dart';
|
||||||
|
|
||||||
|
part 'call.g.dart';
|
||||||
|
part 'call.freezed.dart';
|
||||||
|
|
||||||
|
String formatDuration(Duration duration) {
|
||||||
|
String negativeSign = duration.isNegative ? '-' : '';
|
||||||
|
String twoDigits(int n) => n.toString().padLeft(2, "0");
|
||||||
|
String twoDigitMinutes = twoDigits(duration.inMinutes.remainder(60).abs());
|
||||||
|
String twoDigitSeconds = twoDigits(duration.inSeconds.remainder(60).abs());
|
||||||
|
return "$negativeSign${twoDigits(duration.inHours)}:$twoDigitMinutes:$twoDigitSeconds";
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class CallState with _$CallState {
|
||||||
|
const factory CallState({
|
||||||
|
required bool isConnected,
|
||||||
|
required bool isMicrophoneEnabled,
|
||||||
|
required bool isCameraEnabled,
|
||||||
|
required bool isScreenSharing,
|
||||||
|
@Default(Duration(seconds: 0)) Duration duration,
|
||||||
|
String? error,
|
||||||
|
}) = _CallState;
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class CallParticipantLive with _$CallParticipantLive {
|
||||||
|
const CallParticipantLive._();
|
||||||
|
|
||||||
|
const factory CallParticipantLive({
|
||||||
|
required CallParticipant participant,
|
||||||
|
required Participant remoteParticipant,
|
||||||
|
}) = _CallParticipantLive;
|
||||||
|
|
||||||
|
bool get isSpeaking => remoteParticipant.isSpeaking;
|
||||||
|
bool get isMuted => remoteParticipant.isMuted;
|
||||||
|
bool get isScreenSharing => remoteParticipant.isScreenShareEnabled();
|
||||||
|
bool get isScreenSharingWithAudio =>
|
||||||
|
remoteParticipant.isScreenShareAudioEnabled();
|
||||||
|
|
||||||
|
bool get hasVideo => remoteParticipant.hasVideo;
|
||||||
|
bool get hasAudio => remoteParticipant.hasAudio;
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class CallNotifier extends _$CallNotifier {
|
||||||
|
Room? _room;
|
||||||
|
LocalParticipant? _localParticipant;
|
||||||
|
List<CallParticipantLive> _participants = [];
|
||||||
|
final Map<String, CallParticipant> _participantInfoByIdentity = {};
|
||||||
|
StreamSubscription? _wsSubscription;
|
||||||
|
EventsListener? _roomListener;
|
||||||
|
|
||||||
|
List<CallParticipantLive> get participants =>
|
||||||
|
List.unmodifiable(_participants);
|
||||||
|
LocalParticipant? get localParticipant => _localParticipant;
|
||||||
|
|
||||||
|
Timer? _durationTimer;
|
||||||
|
|
||||||
|
@override
|
||||||
|
CallState build() {
|
||||||
|
// Subscribe to websocket updates
|
||||||
|
_subscribeToParticipantsUpdate();
|
||||||
|
return const CallState(
|
||||||
|
isConnected: false,
|
||||||
|
isMicrophoneEnabled: true,
|
||||||
|
isCameraEnabled: false,
|
||||||
|
isScreenSharing: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _subscribeToParticipantsUpdate() {
|
||||||
|
// Only subscribe once
|
||||||
|
if (_wsSubscription != null) return;
|
||||||
|
final ws = ref.read(websocketProvider);
|
||||||
|
_wsSubscription = ws.dataStream.listen((packet) {
|
||||||
|
if (packet.type == 'call.participants.update' && packet.data != null) {
|
||||||
|
final participantsData = packet.data!["participants"];
|
||||||
|
if (participantsData is List) {
|
||||||
|
final parsed =
|
||||||
|
participantsData
|
||||||
|
.map(
|
||||||
|
(e) =>
|
||||||
|
CallParticipant.fromJson(Map<String, dynamic>.from(e)),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
_updateLiveParticipants(parsed);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _initRoomListeners() {
|
||||||
|
if (_room == null) return;
|
||||||
|
_roomListener?.dispose();
|
||||||
|
_roomListener = _room!.createListener();
|
||||||
|
_room!.addListener(_onRoomChange);
|
||||||
|
_roomListener!
|
||||||
|
..on<ParticipantConnectedEvent>((e) {
|
||||||
|
_refreshLiveParticipants();
|
||||||
|
})
|
||||||
|
..on<RoomDisconnectedEvent>((e) {
|
||||||
|
_participants = [];
|
||||||
|
state = state.copyWith();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
void _onRoomChange() {
|
||||||
|
_refreshLiveParticipants();
|
||||||
|
}
|
||||||
|
|
||||||
|
void _refreshLiveParticipants() {
|
||||||
|
if (_room == null) return;
|
||||||
|
final remoteParticipants = _room!.remoteParticipants;
|
||||||
|
_participants = [];
|
||||||
|
// Add local participant first if available
|
||||||
|
if (_localParticipant != null) {
|
||||||
|
final localInfo = _buildParticipant();
|
||||||
|
_participants.add(
|
||||||
|
CallParticipantLive(
|
||||||
|
participant: localInfo,
|
||||||
|
remoteParticipant: _localParticipant!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Add remote participants
|
||||||
|
_participants.addAll(
|
||||||
|
remoteParticipants.values.map((remote) {
|
||||||
|
final match =
|
||||||
|
_participantInfoByIdentity[remote.identity] ??
|
||||||
|
CallParticipant(
|
||||||
|
identity: remote.identity,
|
||||||
|
name: remote.identity,
|
||||||
|
joinedAt: DateTime.now(),
|
||||||
|
accountId: null,
|
||||||
|
profile: null,
|
||||||
|
);
|
||||||
|
return CallParticipantLive(
|
||||||
|
participant: match,
|
||||||
|
remoteParticipant: remote,
|
||||||
|
);
|
||||||
|
}),
|
||||||
|
);
|
||||||
|
state = state.copyWith();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds the CallParticipant object for the local participant.
|
||||||
|
/// Optionally, pass [participants] if you want to prioritize info from the latest list.
|
||||||
|
CallParticipant _buildParticipant({List<CallParticipant>? participants}) {
|
||||||
|
if (_localParticipant == null) {
|
||||||
|
throw StateError('No local participant available');
|
||||||
|
}
|
||||||
|
// Prefer info from the latest participants list if available
|
||||||
|
if (participants != null) {
|
||||||
|
final idx = participants.indexWhere(
|
||||||
|
(p) => p.identity == _localParticipant!.identity,
|
||||||
|
);
|
||||||
|
if (idx != -1) return participants[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
final userInfo = ref.read(userInfoProvider);
|
||||||
|
final roomIdentity = ref.read(chatroomIdentityProvider(_roomId));
|
||||||
|
// Otherwise, use info from the identity map or fallback to minimal
|
||||||
|
return _participantInfoByIdentity[_localParticipant!.identity] ??
|
||||||
|
CallParticipant(
|
||||||
|
identity: _localParticipant!.identity,
|
||||||
|
name: _localParticipant!.identity,
|
||||||
|
joinedAt: DateTime.now(),
|
||||||
|
accountId: userInfo.value?.id,
|
||||||
|
profile: roomIdentity.value,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void _updateLiveParticipants(List<CallParticipant> participants) {
|
||||||
|
// Update the info map for lookup
|
||||||
|
for (final p in participants) {
|
||||||
|
_participantInfoByIdentity[p.identity] = p;
|
||||||
|
}
|
||||||
|
if (_room == null) {
|
||||||
|
// Can't build live objects, just store empty
|
||||||
|
_participants = [];
|
||||||
|
state = state.copyWith();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final remoteParticipants = _room!.remoteParticipants;
|
||||||
|
final remotes = remoteParticipants.values.toList();
|
||||||
|
_participants = [];
|
||||||
|
// Add local participant if present in the list
|
||||||
|
if (_localParticipant != null) {
|
||||||
|
final localInfo = _buildParticipant(participants: participants);
|
||||||
|
_participants.add(
|
||||||
|
CallParticipantLive(
|
||||||
|
participant: localInfo,
|
||||||
|
remoteParticipant: _localParticipant!,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Add remote participants
|
||||||
|
_participants.addAll(
|
||||||
|
participants.map((p) {
|
||||||
|
RemoteParticipant? remote;
|
||||||
|
for (final r in remotes) {
|
||||||
|
if (r.identity == p.identity) {
|
||||||
|
remote = r;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (_localParticipant != null &&
|
||||||
|
p.identity == _localParticipant!.identity) {
|
||||||
|
return null; // Already added local
|
||||||
|
}
|
||||||
|
return remote != null
|
||||||
|
? CallParticipantLive(participant: p, remoteParticipant: remote)
|
||||||
|
: null;
|
||||||
|
}).whereType<CallParticipantLive>(),
|
||||||
|
);
|
||||||
|
state = state.copyWith();
|
||||||
|
}
|
||||||
|
|
||||||
|
String? _roomId;
|
||||||
|
String? get roomId => _roomId;
|
||||||
|
|
||||||
|
Future<void> joinRoom(String roomId) async {
|
||||||
|
_roomId = roomId;
|
||||||
|
if (_room != null) {
|
||||||
|
await _room!.disconnect();
|
||||||
|
await _room!.dispose();
|
||||||
|
_room = null;
|
||||||
|
_localParticipant = null;
|
||||||
|
_participants = [];
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
final apiClient = ref.read(apiClientProvider);
|
||||||
|
final ongoingCall = await ref.read(ongoingCallProvider(roomId).future);
|
||||||
|
final response = await apiClient.get('/chat/realtime/$roomId/join');
|
||||||
|
if (response.statusCode == 200 && response.data != null) {
|
||||||
|
final data = response.data;
|
||||||
|
// Parse join response
|
||||||
|
final joinResponse = ChatRealtimeJoinResponse.fromJson(data);
|
||||||
|
final participants = joinResponse.participants;
|
||||||
|
final String endpoint = joinResponse.endpoint;
|
||||||
|
final String token = joinResponse.token;
|
||||||
|
|
||||||
|
// Setup duration timer
|
||||||
|
_durationTimer?.cancel();
|
||||||
|
_durationTimer = Timer.periodic(const Duration(seconds: 1), (timer) {
|
||||||
|
state = state.copyWith(
|
||||||
|
duration: Duration(
|
||||||
|
milliseconds:
|
||||||
|
(DateTime.now().millisecondsSinceEpoch -
|
||||||
|
(ongoingCall?.createdAt.millisecondsSinceEpoch ?? 0)),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Connect to LiveKit
|
||||||
|
_room = Room();
|
||||||
|
|
||||||
|
await _room!.connect(
|
||||||
|
endpoint,
|
||||||
|
token,
|
||||||
|
connectOptions: ConnectOptions(autoSubscribe: true),
|
||||||
|
roomOptions: RoomOptions(adaptiveStream: true, dynacast: true),
|
||||||
|
fastConnectOptions: FastConnectOptions(
|
||||||
|
microphone: TrackOption(enabled: true),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
_localParticipant = _room!.localParticipant;
|
||||||
|
|
||||||
|
_initRoomListeners();
|
||||||
|
_updateLiveParticipants(participants);
|
||||||
|
|
||||||
|
// Listen for connection updates
|
||||||
|
_room!.addListener(() {
|
||||||
|
state = state.copyWith(
|
||||||
|
isConnected: _room!.connectionState == ConnectionState.connected,
|
||||||
|
isMicrophoneEnabled: _localParticipant!.isMicrophoneEnabled(),
|
||||||
|
isCameraEnabled: _localParticipant!.isCameraEnabled(),
|
||||||
|
isScreenSharing: _localParticipant!.isScreenShareEnabled(),
|
||||||
|
);
|
||||||
|
});
|
||||||
|
state = state.copyWith(isConnected: true);
|
||||||
|
} else {
|
||||||
|
state = state.copyWith(error: 'Failed to join room');
|
||||||
|
}
|
||||||
|
} catch (e) {
|
||||||
|
state = state.copyWith(error: e.toString());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> toggleMicrophone() async {
|
||||||
|
if (_localParticipant != null) {
|
||||||
|
const autostop = true;
|
||||||
|
final target = !_localParticipant!.isMicrophoneEnabled();
|
||||||
|
state = state.copyWith(isMicrophoneEnabled: target);
|
||||||
|
if (target) {
|
||||||
|
await _localParticipant!.audioTrackPublications.firstOrNull?.unmute(
|
||||||
|
stopOnMute: autostop,
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
await _localParticipant!.audioTrackPublications.firstOrNull?.mute(
|
||||||
|
stopOnMute: autostop,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> toggleCamera() async {
|
||||||
|
if (_localParticipant != null) {
|
||||||
|
final target = !_localParticipant!.isCameraEnabled();
|
||||||
|
state = state.copyWith(isCameraEnabled: target);
|
||||||
|
await _localParticipant!.setCameraEnabled(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> toggleScreenShare() async {
|
||||||
|
if (_localParticipant != null) {
|
||||||
|
final target = !_localParticipant!.isScreenShareEnabled();
|
||||||
|
state = state.copyWith(isScreenSharing: target);
|
||||||
|
await _localParticipant!.setScreenShareEnabled(target);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> disconnect() async {
|
||||||
|
if (_room != null) {
|
||||||
|
await _room!.disconnect();
|
||||||
|
state = state.copyWith(
|
||||||
|
isConnected: false,
|
||||||
|
isMicrophoneEnabled: false,
|
||||||
|
isCameraEnabled: false,
|
||||||
|
isScreenSharing: false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void dispose() {
|
||||||
|
_wsSubscription?.cancel();
|
||||||
|
_roomListener?.dispose();
|
||||||
|
_room?.removeListener(_onRoomChange);
|
||||||
|
_room?.dispose();
|
||||||
|
_durationTimer?.cancel();
|
||||||
|
}
|
||||||
|
}
|
||||||
305
lib/pods/call.freezed.dart
Normal file
305
lib/pods/call.freezed.dart
Normal file
@@ -0,0 +1,305 @@
|
|||||||
|
// dart format width=80
|
||||||
|
// coverage:ignore-file
|
||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// 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 'call.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$CallState {
|
||||||
|
|
||||||
|
bool get isConnected; bool get isMicrophoneEnabled; bool get isCameraEnabled; bool get isScreenSharing; Duration get duration; String? get error;
|
||||||
|
/// Create a copy of CallState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$CallStateCopyWith<CallState> get copyWith => _$CallStateCopyWithImpl<CallState>(this as CallState, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallState&&(identical(other.isConnected, isConnected) || other.isConnected == isConnected)&&(identical(other.isMicrophoneEnabled, isMicrophoneEnabled) || other.isMicrophoneEnabled == isMicrophoneEnabled)&&(identical(other.isCameraEnabled, isCameraEnabled) || other.isCameraEnabled == isCameraEnabled)&&(identical(other.isScreenSharing, isScreenSharing) || other.isScreenSharing == isScreenSharing)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.error, error) || other.error == error));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,isConnected,isMicrophoneEnabled,isCameraEnabled,isScreenSharing,duration,error);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CallState(isConnected: $isConnected, isMicrophoneEnabled: $isMicrophoneEnabled, isCameraEnabled: $isCameraEnabled, isScreenSharing: $isScreenSharing, duration: $duration, error: $error)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $CallStateCopyWith<$Res> {
|
||||||
|
factory $CallStateCopyWith(CallState value, $Res Function(CallState) _then) = _$CallStateCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
bool isConnected, bool isMicrophoneEnabled, bool isCameraEnabled, bool isScreenSharing, Duration duration, String? error
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$CallStateCopyWithImpl<$Res>
|
||||||
|
implements $CallStateCopyWith<$Res> {
|
||||||
|
_$CallStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final CallState _self;
|
||||||
|
final $Res Function(CallState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CallState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? isConnected = null,Object? isMicrophoneEnabled = null,Object? isCameraEnabled = null,Object? isScreenSharing = null,Object? duration = null,Object? error = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
isConnected: null == isConnected ? _self.isConnected : isConnected // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,isMicrophoneEnabled: null == isMicrophoneEnabled ? _self.isMicrophoneEnabled : isMicrophoneEnabled // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,isCameraEnabled: null == isCameraEnabled ? _self.isCameraEnabled : isCameraEnabled // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,isScreenSharing: null == isScreenSharing ? _self.isScreenSharing : isScreenSharing // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Duration,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _CallState implements CallState {
|
||||||
|
const _CallState({required this.isConnected, required this.isMicrophoneEnabled, required this.isCameraEnabled, required this.isScreenSharing, this.duration = const Duration(seconds: 0), this.error});
|
||||||
|
|
||||||
|
|
||||||
|
@override final bool isConnected;
|
||||||
|
@override final bool isMicrophoneEnabled;
|
||||||
|
@override final bool isCameraEnabled;
|
||||||
|
@override final bool isScreenSharing;
|
||||||
|
@override@JsonKey() final Duration duration;
|
||||||
|
@override final String? error;
|
||||||
|
|
||||||
|
/// Create a copy of CallState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$CallStateCopyWith<_CallState> get copyWith => __$CallStateCopyWithImpl<_CallState>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallState&&(identical(other.isConnected, isConnected) || other.isConnected == isConnected)&&(identical(other.isMicrophoneEnabled, isMicrophoneEnabled) || other.isMicrophoneEnabled == isMicrophoneEnabled)&&(identical(other.isCameraEnabled, isCameraEnabled) || other.isCameraEnabled == isCameraEnabled)&&(identical(other.isScreenSharing, isScreenSharing) || other.isScreenSharing == isScreenSharing)&&(identical(other.duration, duration) || other.duration == duration)&&(identical(other.error, error) || other.error == error));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,isConnected,isMicrophoneEnabled,isCameraEnabled,isScreenSharing,duration,error);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CallState(isConnected: $isConnected, isMicrophoneEnabled: $isMicrophoneEnabled, isCameraEnabled: $isCameraEnabled, isScreenSharing: $isScreenSharing, duration: $duration, error: $error)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$CallStateCopyWith<$Res> implements $CallStateCopyWith<$Res> {
|
||||||
|
factory _$CallStateCopyWith(_CallState value, $Res Function(_CallState) _then) = __$CallStateCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
bool isConnected, bool isMicrophoneEnabled, bool isCameraEnabled, bool isScreenSharing, Duration duration, String? error
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$CallStateCopyWithImpl<$Res>
|
||||||
|
implements _$CallStateCopyWith<$Res> {
|
||||||
|
__$CallStateCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _CallState _self;
|
||||||
|
final $Res Function(_CallState) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CallState
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? isConnected = null,Object? isMicrophoneEnabled = null,Object? isCameraEnabled = null,Object? isScreenSharing = null,Object? duration = null,Object? error = freezed,}) {
|
||||||
|
return _then(_CallState(
|
||||||
|
isConnected: null == isConnected ? _self.isConnected : isConnected // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,isMicrophoneEnabled: null == isMicrophoneEnabled ? _self.isMicrophoneEnabled : isMicrophoneEnabled // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,isCameraEnabled: null == isCameraEnabled ? _self.isCameraEnabled : isCameraEnabled // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,isScreenSharing: null == isScreenSharing ? _self.isScreenSharing : isScreenSharing // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,duration: null == duration ? _self.duration : duration // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Duration,error: freezed == error ? _self.error : error // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$CallParticipantLive {
|
||||||
|
|
||||||
|
CallParticipant get participant; Participant get remoteParticipant;
|
||||||
|
/// Create a copy of CallParticipantLive
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$CallParticipantLiveCopyWith<CallParticipantLive> get copyWith => _$CallParticipantLiveCopyWithImpl<CallParticipantLive>(this as CallParticipantLive, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is CallParticipantLive&&(identical(other.participant, participant) || other.participant == participant)&&(identical(other.remoteParticipant, remoteParticipant) || other.remoteParticipant == remoteParticipant));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,participant,remoteParticipant);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CallParticipantLive(participant: $participant, remoteParticipant: $remoteParticipant)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $CallParticipantLiveCopyWith<$Res> {
|
||||||
|
factory $CallParticipantLiveCopyWith(CallParticipantLive value, $Res Function(CallParticipantLive) _then) = _$CallParticipantLiveCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
CallParticipant participant, Participant remoteParticipant
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$CallParticipantCopyWith<$Res> get participant;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$CallParticipantLiveCopyWithImpl<$Res>
|
||||||
|
implements $CallParticipantLiveCopyWith<$Res> {
|
||||||
|
_$CallParticipantLiveCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final CallParticipantLive _self;
|
||||||
|
final $Res Function(CallParticipantLive) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipantLive
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? participant = null,Object? remoteParticipant = null,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
participant: null == participant ? _self.participant : participant // ignore: cast_nullable_to_non_nullable
|
||||||
|
as CallParticipant,remoteParticipant: null == remoteParticipant ? _self.remoteParticipant : remoteParticipant // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Participant,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
/// Create a copy of CallParticipantLive
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$CallParticipantCopyWith<$Res> get participant {
|
||||||
|
|
||||||
|
return $CallParticipantCopyWith<$Res>(_self.participant, (value) {
|
||||||
|
return _then(_self.copyWith(participant: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
|
||||||
|
|
||||||
|
class _CallParticipantLive extends CallParticipantLive {
|
||||||
|
const _CallParticipantLive({required this.participant, required this.remoteParticipant}): super._();
|
||||||
|
|
||||||
|
|
||||||
|
@override final CallParticipant participant;
|
||||||
|
@override final Participant remoteParticipant;
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipantLive
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$CallParticipantLiveCopyWith<_CallParticipantLive> get copyWith => __$CallParticipantLiveCopyWithImpl<_CallParticipantLive>(this, _$identity);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CallParticipantLive&&(identical(other.participant, participant) || other.participant == participant)&&(identical(other.remoteParticipant, remoteParticipant) || other.remoteParticipant == remoteParticipant));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,participant,remoteParticipant);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CallParticipantLive(participant: $participant, remoteParticipant: $remoteParticipant)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$CallParticipantLiveCopyWith<$Res> implements $CallParticipantLiveCopyWith<$Res> {
|
||||||
|
factory _$CallParticipantLiveCopyWith(_CallParticipantLive value, $Res Function(_CallParticipantLive) _then) = __$CallParticipantLiveCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
CallParticipant participant, Participant remoteParticipant
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $CallParticipantCopyWith<$Res> get participant;
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$CallParticipantLiveCopyWithImpl<$Res>
|
||||||
|
implements _$CallParticipantLiveCopyWith<$Res> {
|
||||||
|
__$CallParticipantLiveCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _CallParticipantLive _self;
|
||||||
|
final $Res Function(_CallParticipantLive) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipantLive
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? participant = null,Object? remoteParticipant = null,}) {
|
||||||
|
return _then(_CallParticipantLive(
|
||||||
|
participant: null == participant ? _self.participant : participant // ignore: cast_nullable_to_non_nullable
|
||||||
|
as CallParticipant,remoteParticipant: null == remoteParticipant ? _self.remoteParticipant : remoteParticipant // ignore: cast_nullable_to_non_nullable
|
||||||
|
as Participant,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Create a copy of CallParticipantLive
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$CallParticipantCopyWith<$Res> get participant {
|
||||||
|
|
||||||
|
return $CallParticipantCopyWith<$Res>(_self.participant, (value) {
|
||||||
|
return _then(_self.copyWith(participant: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
27
lib/pods/call.g.dart
Normal file
27
lib/pods/call.g.dart
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'call.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$callNotifierHash() => r'2082a572b5cfb4bf929dc1ed492c52cd2735452e';
|
||||||
|
|
||||||
|
/// See also [CallNotifier].
|
||||||
|
@ProviderFor(CallNotifier)
|
||||||
|
final callNotifierProvider =
|
||||||
|
AutoDisposeNotifierProvider<CallNotifier, CallState>.internal(
|
||||||
|
CallNotifier.new,
|
||||||
|
name: r'callNotifierProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$callNotifierHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$CallNotifier = AutoDisposeNotifier<CallState>;
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
@@ -1,9 +1,12 @@
|
|||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
import 'package:flutter_riverpod/flutter_riverpod.dart';
|
||||||
import 'package:freezed_annotation/freezed_annotation.dart';
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:island/pods/theme.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
part 'config.freezed.dart';
|
part 'config.freezed.dart';
|
||||||
|
part 'config.g.dart';
|
||||||
|
|
||||||
const kTokenPairStoreKey = 'dyn_user_tk';
|
const kTokenPairStoreKey = 'dyn_user_tk';
|
||||||
|
|
||||||
@@ -14,13 +17,8 @@ const kAppbarTransparentStoreKey = 'app_bar_transparent';
|
|||||||
const kAppBackgroundStoreKey = 'app_has_background';
|
const kAppBackgroundStoreKey = 'app_has_background';
|
||||||
const kAppColorSchemeStoreKey = 'app_color_scheme';
|
const kAppColorSchemeStoreKey = 'app_color_scheme';
|
||||||
const kAppNotifyWithHaptic = 'app_notify_with_haptic';
|
const kAppNotifyWithHaptic = 'app_notify_with_haptic';
|
||||||
const kAppExpandPostLink = 'app_expand_post_link';
|
|
||||||
const kAppExpandChatLink = 'app_expand_chat_link';
|
|
||||||
const kAppRealmCompactView = 'app_realm_compact_view';
|
|
||||||
const kAppCustomFonts = 'app_custom_fonts';
|
const kAppCustomFonts = 'app_custom_fonts';
|
||||||
const kAppMixedFeed = 'app_mixed_feed';
|
|
||||||
const kAppAutoTranslate = 'app_auto_translate';
|
const kAppAutoTranslate = 'app_auto_translate';
|
||||||
const kAppHideBottomNav = 'app_hide_bottom_nav';
|
|
||||||
const kAppSoundEffects = 'app_sound_effects';
|
const kAppSoundEffects = 'app_sound_effects';
|
||||||
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
const kAppAprilFoolFeatures = 'app_april_fool_features';
|
||||||
const kAppWindowSize = 'app_window_size';
|
const kAppWindowSize = 'app_window_size';
|
||||||
@@ -51,75 +49,79 @@ final serverUrlProvider = Provider<String>((ref) {
|
|||||||
});
|
});
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class AppSettings with _$AppSettings {
|
sealed class AppSettings with _$AppSettings {
|
||||||
const factory AppSettings({
|
const factory AppSettings({
|
||||||
required bool realmCompactView,
|
|
||||||
required bool mixedFeed,
|
|
||||||
required bool autoTranslate,
|
required bool autoTranslate,
|
||||||
required bool hideBottomNav,
|
|
||||||
required bool soundEffects,
|
required bool soundEffects,
|
||||||
required bool aprilFoolFeatures,
|
required bool aprilFoolFeatures,
|
||||||
required bool enterToSend,
|
required bool enterToSend,
|
||||||
|
required bool appBarTransparent,
|
||||||
|
required String? customFonts,
|
||||||
|
required int? appColorScheme, // The color stored via the int type
|
||||||
}) = _AppSettings;
|
}) = _AppSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
class AppSettingsNotifier extends StateNotifier<AppSettings> {
|
@riverpod
|
||||||
final SharedPreferences prefs;
|
class AppSettingsNotifier extends _$AppSettingsNotifier {
|
||||||
|
@override
|
||||||
AppSettingsNotifier(this.prefs)
|
AppSettings build() {
|
||||||
: super(
|
final prefs = ref.watch(sharedPreferencesProvider);
|
||||||
AppSettings(
|
return AppSettings(
|
||||||
realmCompactView: prefs.getBool(kAppRealmCompactView) ?? false,
|
autoTranslate: prefs.getBool(kAppAutoTranslate) ?? false,
|
||||||
mixedFeed: prefs.getBool(kAppMixedFeed) ?? true,
|
soundEffects: prefs.getBool(kAppSoundEffects) ?? true,
|
||||||
autoTranslate: prefs.getBool(kAppAutoTranslate) ?? false,
|
aprilFoolFeatures: prefs.getBool(kAppAprilFoolFeatures) ?? true,
|
||||||
hideBottomNav: prefs.getBool(kAppHideBottomNav) ?? false,
|
enterToSend: prefs.getBool(kAppEnterToSend) ?? true,
|
||||||
soundEffects: prefs.getBool(kAppSoundEffects) ?? true,
|
appBarTransparent: prefs.getBool(kAppbarTransparentStoreKey) ?? false,
|
||||||
aprilFoolFeatures: prefs.getBool(kAppAprilFoolFeatures) ?? true,
|
customFonts: prefs.getString(kAppCustomFonts),
|
||||||
enterToSend: prefs.getBool(kAppEnterToSend) ?? true,
|
appColorScheme: prefs.getInt(kAppColorSchemeStoreKey),
|
||||||
),
|
);
|
||||||
);
|
|
||||||
|
|
||||||
void setRealmCompactView(bool value) {
|
|
||||||
prefs.setBool(kAppRealmCompactView, value);
|
|
||||||
state = state.copyWith(realmCompactView: value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setMixedFeed(bool value) {
|
|
||||||
prefs.setBool(kAppMixedFeed, value);
|
|
||||||
state = state.copyWith(mixedFeed: value);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAutoTranslate(bool value) {
|
void setAutoTranslate(bool value) {
|
||||||
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
prefs.setBool(kAppAutoTranslate, value);
|
prefs.setBool(kAppAutoTranslate, value);
|
||||||
state = state.copyWith(autoTranslate: value);
|
state = state.copyWith(autoTranslate: value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setHideBottomNav(bool value) {
|
|
||||||
prefs.setBool(kAppHideBottomNav, value);
|
|
||||||
state = state.copyWith(hideBottomNav: value);
|
|
||||||
}
|
|
||||||
|
|
||||||
void setSoundEffects(bool value) {
|
void setSoundEffects(bool value) {
|
||||||
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
prefs.setBool(kAppSoundEffects, value);
|
prefs.setBool(kAppSoundEffects, value);
|
||||||
state = state.copyWith(soundEffects: value);
|
state = state.copyWith(soundEffects: value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setAprilFoolFeatures(bool value) {
|
void setAprilFoolFeatures(bool value) {
|
||||||
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
prefs.setBool(kAppAprilFoolFeatures, value);
|
prefs.setBool(kAppAprilFoolFeatures, value);
|
||||||
state = state.copyWith(aprilFoolFeatures: value);
|
state = state.copyWith(aprilFoolFeatures: value);
|
||||||
}
|
}
|
||||||
|
|
||||||
void setEnterToSend(bool value) {
|
void setEnterToSend(bool value) {
|
||||||
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
prefs.setBool(kAppEnterToSend, value);
|
prefs.setBool(kAppEnterToSend, value);
|
||||||
state = state.copyWith(enterToSend: value);
|
state = state.copyWith(enterToSend: value);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
final appSettingsProvider =
|
void setAppBarTransparent(bool value) {
|
||||||
StateNotifierProvider<AppSettingsNotifier, AppSettings>((ref) {
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
final prefs = ref.watch(sharedPreferencesProvider);
|
prefs.setBool(kAppbarTransparentStoreKey, value);
|
||||||
return AppSettingsNotifier(prefs);
|
state = state.copyWith(appBarTransparent: value);
|
||||||
});
|
ref.read(themeProvider.notifier).reloadTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setCustomFonts(String? value) {
|
||||||
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
|
prefs.setString(kAppCustomFonts, value ?? '');
|
||||||
|
state = state.copyWith(customFonts: value);
|
||||||
|
ref.read(themeProvider.notifier).reloadTheme();
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAppColorScheme(int? value) {
|
||||||
|
final prefs = ref.read(sharedPreferencesProvider);
|
||||||
|
prefs.setInt(kAppColorSchemeStoreKey, value ?? 0);
|
||||||
|
state = state.copyWith(appColorScheme: value);
|
||||||
|
ref.read(themeProvider.notifier).reloadTheme();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
final updateInfoProvider =
|
final updateInfoProvider =
|
||||||
StateNotifierProvider<UpdateInfoNotifier, (String?, String?)>((ref) {
|
StateNotifierProvider<UpdateInfoNotifier, (String?, String?)>((ref) {
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ T _$identity<T>(T value) => value;
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$AppSettings {
|
mixin _$AppSettings {
|
||||||
|
|
||||||
bool get realmCompactView; bool get mixedFeed; bool get autoTranslate; bool get hideBottomNav; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend;
|
bool get autoTranslate; bool get soundEffects; bool get aprilFoolFeatures; bool get enterToSend; bool get appBarTransparent; String? get customFonts; int? get appColorScheme;
|
||||||
/// Create a copy of AppSettings
|
/// Create a copy of AppSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@@ -26,16 +26,16 @@ $AppSettingsCopyWith<AppSettings> get copyWith => _$AppSettingsCopyWithImpl<AppS
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettings&&(identical(other.realmCompactView, realmCompactView) || other.realmCompactView == realmCompactView)&&(identical(other.mixedFeed, mixedFeed) || other.mixedFeed == mixedFeed)&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.hideBottomNav, hideBottomNav) || other.hideBottomNav == hideBottomNav)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,realmCompactView,mixedFeed,autoTranslate,hideBottomNav,soundEffects,aprilFoolFeatures,enterToSend);
|
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,customFonts,appColorScheme);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppSettings(realmCompactView: $realmCompactView, mixedFeed: $mixedFeed, autoTranslate: $autoTranslate, hideBottomNav: $hideBottomNav, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend)';
|
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, customFonts: $customFonts, appColorScheme: $appColorScheme)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -46,7 +46,7 @@ abstract mixin class $AppSettingsCopyWith<$Res> {
|
|||||||
factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl;
|
factory $AppSettingsCopyWith(AppSettings value, $Res Function(AppSettings) _then) = _$AppSettingsCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
bool realmCompactView, bool mixedFeed, bool autoTranslate, bool hideBottomNav, bool soundEffects, bool aprilFoolFeatures, bool enterToSend
|
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -63,16 +63,16 @@ class _$AppSettingsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of AppSettings
|
/// Create a copy of AppSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? realmCompactView = null,Object? mixedFeed = null,Object? autoTranslate = null,Object? hideBottomNav = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? autoTranslate = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? customFonts = freezed,Object? appColorScheme = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
realmCompactView: null == realmCompactView ? _self.realmCompactView : realmCompactView // ignore: cast_nullable_to_non_nullable
|
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,mixedFeed: null == mixedFeed ? _self.mixedFeed : mixedFeed // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,hideBottomNav: null == hideBottomNav ? _self.hideBottomNav : hideBottomNav // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,appBarTransparent: null == appBarTransparent ? _self.appBarTransparent : appBarTransparent // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,customFonts: freezed == customFonts ? _self.customFonts : customFonts // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,appColorScheme: freezed == appColorScheme ? _self.appColorScheme : appColorScheme // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -83,16 +83,16 @@ as bool,
|
|||||||
|
|
||||||
|
|
||||||
class _AppSettings implements AppSettings {
|
class _AppSettings implements AppSettings {
|
||||||
const _AppSettings({required this.realmCompactView, required this.mixedFeed, required this.autoTranslate, required this.hideBottomNav, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend});
|
const _AppSettings({required this.autoTranslate, required this.soundEffects, required this.aprilFoolFeatures, required this.enterToSend, required this.appBarTransparent, required this.customFonts, required this.appColorScheme});
|
||||||
|
|
||||||
|
|
||||||
@override final bool realmCompactView;
|
|
||||||
@override final bool mixedFeed;
|
|
||||||
@override final bool autoTranslate;
|
@override final bool autoTranslate;
|
||||||
@override final bool hideBottomNav;
|
|
||||||
@override final bool soundEffects;
|
@override final bool soundEffects;
|
||||||
@override final bool aprilFoolFeatures;
|
@override final bool aprilFoolFeatures;
|
||||||
@override final bool enterToSend;
|
@override final bool enterToSend;
|
||||||
|
@override final bool appBarTransparent;
|
||||||
|
@override final String? customFonts;
|
||||||
|
@override final int? appColorScheme;
|
||||||
|
|
||||||
/// Create a copy of AppSettings
|
/// Create a copy of AppSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -104,16 +104,16 @@ _$AppSettingsCopyWith<_AppSettings> get copyWith => __$AppSettingsCopyWithImpl<_
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.realmCompactView, realmCompactView) || other.realmCompactView == realmCompactView)&&(identical(other.mixedFeed, mixedFeed) || other.mixedFeed == mixedFeed)&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.hideBottomNav, hideBottomNav) || other.hideBottomNav == hideBottomNav)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AppSettings&&(identical(other.autoTranslate, autoTranslate) || other.autoTranslate == autoTranslate)&&(identical(other.soundEffects, soundEffects) || other.soundEffects == soundEffects)&&(identical(other.aprilFoolFeatures, aprilFoolFeatures) || other.aprilFoolFeatures == aprilFoolFeatures)&&(identical(other.enterToSend, enterToSend) || other.enterToSend == enterToSend)&&(identical(other.appBarTransparent, appBarTransparent) || other.appBarTransparent == appBarTransparent)&&(identical(other.customFonts, customFonts) || other.customFonts == customFonts)&&(identical(other.appColorScheme, appColorScheme) || other.appColorScheme == appColorScheme));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,realmCompactView,mixedFeed,autoTranslate,hideBottomNav,soundEffects,aprilFoolFeatures,enterToSend);
|
int get hashCode => Object.hash(runtimeType,autoTranslate,soundEffects,aprilFoolFeatures,enterToSend,appBarTransparent,customFonts,appColorScheme);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'AppSettings(realmCompactView: $realmCompactView, mixedFeed: $mixedFeed, autoTranslate: $autoTranslate, hideBottomNav: $hideBottomNav, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend)';
|
return 'AppSettings(autoTranslate: $autoTranslate, soundEffects: $soundEffects, aprilFoolFeatures: $aprilFoolFeatures, enterToSend: $enterToSend, appBarTransparent: $appBarTransparent, customFonts: $customFonts, appColorScheme: $appColorScheme)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -124,7 +124,7 @@ abstract mixin class _$AppSettingsCopyWith<$Res> implements $AppSettingsCopyWith
|
|||||||
factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl;
|
factory _$AppSettingsCopyWith(_AppSettings value, $Res Function(_AppSettings) _then) = __$AppSettingsCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
bool realmCompactView, bool mixedFeed, bool autoTranslate, bool hideBottomNav, bool soundEffects, bool aprilFoolFeatures, bool enterToSend
|
bool autoTranslate, bool soundEffects, bool aprilFoolFeatures, bool enterToSend, bool appBarTransparent, String? customFonts, int? appColorScheme
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -141,16 +141,16 @@ class __$AppSettingsCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of AppSettings
|
/// Create a copy of AppSettings
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? realmCompactView = null,Object? mixedFeed = null,Object? autoTranslate = null,Object? hideBottomNav = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? autoTranslate = null,Object? soundEffects = null,Object? aprilFoolFeatures = null,Object? enterToSend = null,Object? appBarTransparent = null,Object? customFonts = freezed,Object? appColorScheme = freezed,}) {
|
||||||
return _then(_AppSettings(
|
return _then(_AppSettings(
|
||||||
realmCompactView: null == realmCompactView ? _self.realmCompactView : realmCompactView // ignore: cast_nullable_to_non_nullable
|
autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,mixedFeed: null == mixedFeed ? _self.mixedFeed : mixedFeed // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,autoTranslate: null == autoTranslate ? _self.autoTranslate : autoTranslate // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,hideBottomNav: null == hideBottomNav ? _self.hideBottomNav : hideBottomNav // ignore: cast_nullable_to_non_nullable
|
|
||||||
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
as bool,soundEffects: null == soundEffects ? _self.soundEffects : soundEffects // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
as bool,aprilFoolFeatures: null == aprilFoolFeatures ? _self.aprilFoolFeatures : aprilFoolFeatures // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
as bool,enterToSend: null == enterToSend ? _self.enterToSend : enterToSend // ignore: cast_nullable_to_non_nullable
|
||||||
as bool,
|
as bool,appBarTransparent: null == appBarTransparent ? _self.appBarTransparent : appBarTransparent // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool,customFonts: freezed == customFonts ? _self.customFonts : customFonts // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,appColorScheme: freezed == appColorScheme ? _self.appColorScheme : appColorScheme // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
28
lib/pods/config.g.dart
Normal file
28
lib/pods/config.g.dart
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'config.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$appSettingsNotifierHash() =>
|
||||||
|
r'4f727d448ee17a87b5698b8e36ef67521655406c';
|
||||||
|
|
||||||
|
/// See also [AppSettingsNotifier].
|
||||||
|
@ProviderFor(AppSettingsNotifier)
|
||||||
|
final appSettingsNotifierProvider =
|
||||||
|
AutoDisposeNotifierProvider<AppSettingsNotifier, AppSettings>.internal(
|
||||||
|
AppSettingsNotifier.new,
|
||||||
|
name: r'appSettingsNotifierProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$appSettingsNotifierHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
typedef _$AppSettingsNotifier = AutoDisposeNotifier<AppSettings>;
|
||||||
|
// 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
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import 'dart:async';
|
import 'dart:async';
|
||||||
import 'dart:convert';
|
import 'dart:convert';
|
||||||
import 'dart:developer';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
@@ -68,16 +67,9 @@ final apiClientProvider = Provider<Dio>((ref) {
|
|||||||
RequestInterceptorHandler handler,
|
RequestInterceptorHandler handler,
|
||||||
) async {
|
) async {
|
||||||
try {
|
try {
|
||||||
final atk = await getFreshAtk(
|
final token = await getToken(ref.watch(tokenProvider));
|
||||||
ref.watch(tokenPairProvider),
|
if (token != null) {
|
||||||
ref.watch(serverUrlProvider),
|
options.headers['Authorization'] = 'AtField $token';
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (atk != null) {
|
|
||||||
options.headers['Authorization'] = 'Bearer $atk';
|
|
||||||
}
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// ignore
|
// ignore
|
||||||
@@ -95,105 +87,21 @@ final apiClientProvider = Provider<Dio>((ref) {
|
|||||||
return dio;
|
return dio;
|
||||||
});
|
});
|
||||||
|
|
||||||
final tokenPairProvider = Provider<AppTokenPair?>((ref) {
|
final tokenProvider = Provider<AppToken?>((ref) {
|
||||||
final prefs = ref.watch(sharedPreferencesProvider);
|
final prefs = ref.watch(sharedPreferencesProvider);
|
||||||
final tkPairString = prefs.getString(kTokenPairStoreKey);
|
final tokenString = prefs.getString(kTokenPairStoreKey);
|
||||||
if (tkPairString == null) return null;
|
if (tokenString == null) return null;
|
||||||
return AppTokenPair.fromJson(jsonDecode(tkPairString));
|
return AppToken.fromJson(jsonDecode(tokenString));
|
||||||
});
|
});
|
||||||
|
|
||||||
Future<(String, String)?> refreshToken(String baseUrl, String? rtk) async {
|
// Token refresh functionality removed as per backend changes
|
||||||
if (rtk == null) return null;
|
|
||||||
|
|
||||||
final dio = Dio();
|
Future<String?> getToken(AppToken? token) async {
|
||||||
dio.options.baseUrl = baseUrl;
|
return token?.token;
|
||||||
|
|
||||||
final resp = await dio.post(
|
|
||||||
'/auth/token',
|
|
||||||
data: {'grant_type': 'refresh_token', 'refresh_token': rtk},
|
|
||||||
);
|
|
||||||
|
|
||||||
final String atk = resp.data['access_token'];
|
|
||||||
final String nRtk = resp.data['refresh_token'];
|
|
||||||
|
|
||||||
return (atk, nRtk);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Completer<String?>? _refreshCompleter;
|
Future<void> setToken(SharedPreferences prefs, String token) async {
|
||||||
|
final appToken = AppToken(token: token);
|
||||||
Future<String?> getFreshAtk(
|
final tokenString = jsonEncode(appToken);
|
||||||
AppTokenPair? tkPair,
|
prefs.setString(kTokenPairStoreKey, tokenString);
|
||||||
String baseUrl, {
|
|
||||||
Function(String, String)? onRefreshed,
|
|
||||||
}) async {
|
|
||||||
var atk = tkPair?.accessToken;
|
|
||||||
var rtk = tkPair?.refreshToken;
|
|
||||||
|
|
||||||
if (_refreshCompleter != null) {
|
|
||||||
return await _refreshCompleter!.future;
|
|
||||||
} else {
|
|
||||||
_refreshCompleter = Completer<String?>();
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
if (atk != null) {
|
|
||||||
final atkParts = atk.split('.');
|
|
||||||
if (atkParts.length != 3) {
|
|
||||||
throw Exception('invalid format of access token');
|
|
||||||
}
|
|
||||||
|
|
||||||
var rawPayload = atkParts[1].replaceAll('-', '+').replaceAll('_', '/');
|
|
||||||
switch (rawPayload.length % 4) {
|
|
||||||
case 0:
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
rawPayload += '==';
|
|
||||||
break;
|
|
||||||
case 3:
|
|
||||||
rawPayload += '=';
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
throw Exception('illegal format of access token payload');
|
|
||||||
}
|
|
||||||
|
|
||||||
final b64 = utf8.fuse(base64Url);
|
|
||||||
final payload = b64.decode(rawPayload);
|
|
||||||
final exp = jsonDecode(payload)['exp'];
|
|
||||||
if (exp <= DateTime.now().millisecondsSinceEpoch ~/ 1000) {
|
|
||||||
log('[Auth] Access token need refresh, doing it at ${DateTime.now()}');
|
|
||||||
final result = await refreshToken(baseUrl, rtk);
|
|
||||||
if (result == null) {
|
|
||||||
atk = null;
|
|
||||||
} else {
|
|
||||||
onRefreshed?.call(result.$1, result.$2);
|
|
||||||
atk = result.$1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (atk != null) {
|
|
||||||
_refreshCompleter!.complete(atk);
|
|
||||||
return atk;
|
|
||||||
} else {
|
|
||||||
log('[Auth] Access token refresh failed...');
|
|
||||||
_refreshCompleter!.complete(null);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
log('[Auth] Failed to authenticate user... $err');
|
|
||||||
_refreshCompleter!.completeError(err);
|
|
||||||
} finally {
|
|
||||||
_refreshCompleter = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> setTokenPair(
|
|
||||||
SharedPreferences prefs,
|
|
||||||
String atk,
|
|
||||||
String rtk,
|
|
||||||
) async {
|
|
||||||
final tkPair = AppTokenPair(accessToken: atk, refreshToken: rtk);
|
|
||||||
final tkPairString = jsonEncode(tkPair);
|
|
||||||
prefs.setString(kTokenPairStoreKey, tkPairString);
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ class UserInfoNotifier extends StateNotifier<AsyncValue<SnAccount?>> {
|
|||||||
|
|
||||||
Future<String?> getAccessToken() async {
|
Future<String?> getAccessToken() async {
|
||||||
final prefs = _ref.read(sharedPreferencesProvider);
|
final prefs = _ref.read(sharedPreferencesProvider);
|
||||||
return prefs.getString('dyn_user_atk');
|
return prefs.getString(kTokenPairStoreKey);
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetchUser() async {
|
Future<void> fetchUser() async {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ part 'websocket.freezed.dart';
|
|||||||
part 'websocket.g.dart';
|
part 'websocket.g.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class WebSocketState with _$WebSocketState {
|
sealed class WebSocketState with _$WebSocketState {
|
||||||
const factory WebSocketState.connected() = _Connected;
|
const factory WebSocketState.connected() = _Connected;
|
||||||
const factory WebSocketState.connecting() = _Connecting;
|
const factory WebSocketState.connecting() = _Connecting;
|
||||||
const factory WebSocketState.disconnected() = _Disconnected;
|
const factory WebSocketState.disconnected() = _Disconnected;
|
||||||
@@ -22,7 +22,7 @@ abstract class WebSocketState with _$WebSocketState {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class WebSocketPacket with _$WebSocketPacket {
|
sealed class WebSocketPacket with _$WebSocketPacket {
|
||||||
const factory WebSocketPacket({
|
const factory WebSocketPacket({
|
||||||
required String type,
|
required String type,
|
||||||
required Map<String, dynamic>? data,
|
required Map<String, dynamic>? data,
|
||||||
@@ -51,27 +51,21 @@ class WebSocketService {
|
|||||||
|
|
||||||
Future<void> connect(Ref ref) async {
|
Future<void> connect(Ref ref) async {
|
||||||
_ref = ref;
|
_ref = ref;
|
||||||
|
_statusStreamController.sink.add(WebSocketState.connecting());
|
||||||
|
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
final baseUrl = ref.watch(serverUrlProvider);
|
||||||
final atk = await getFreshAtk(
|
final token = await getToken(ref.watch(tokenProvider));
|
||||||
ref.watch(tokenPairProvider),
|
|
||||||
baseUrl,
|
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final url = '$baseUrl/ws'.replaceFirst('http', 'ws');
|
final url = '$baseUrl/ws'.replaceFirst('http', 'ws');
|
||||||
|
|
||||||
log('[WebSocket] Trying connecting to $url');
|
log('[WebSocket] Trying connecting to $url');
|
||||||
try {
|
try {
|
||||||
if (kIsWeb) {
|
if (kIsWeb) {
|
||||||
_channel = WebSocketChannel.connect(Uri.parse('$url?tk=$atk'));
|
_channel = WebSocketChannel.connect(Uri.parse('$url?tk=$token'));
|
||||||
} else {
|
} else {
|
||||||
_channel = IOWebSocketChannel.connect(
|
_channel = IOWebSocketChannel.connect(
|
||||||
Uri.parse(url),
|
Uri.parse(url),
|
||||||
headers: {'Authorization': 'Bearer $atk'},
|
headers: {'Authorization': 'Bearer $token'},
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
await _channel!.ready;
|
await _channel!.ready;
|
||||||
@@ -140,23 +134,10 @@ class WebSocketStateNotifier extends StateNotifier<WebSocketState> {
|
|||||||
state = const WebSocketState.connecting();
|
state = const WebSocketState.connecting();
|
||||||
try {
|
try {
|
||||||
final service = ref.read(websocketProvider);
|
final service = ref.read(websocketProvider);
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
|
||||||
final atk = await getFreshAtk(
|
|
||||||
ref.watch(tokenPairProvider),
|
|
||||||
baseUrl,
|
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (atk == null) {
|
|
||||||
state = const WebSocketState.error('Unauthorized');
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
await service.connect(ref);
|
await service.connect(ref);
|
||||||
state = const WebSocketState.connected();
|
state = const WebSocketState.connected();
|
||||||
service.statusStream.listen((event) {
|
service.statusStream.listen((event) {
|
||||||
state = event;
|
if (mounted) state = event;
|
||||||
});
|
});
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
state = WebSocketState.error('Failed to connect: $err');
|
state = WebSocketState.error('Failed to connect: $err');
|
||||||
|
|||||||
@@ -8,15 +8,15 @@ class AppRouter extends RootStackRouter {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
List<AutoRoute> get routes => [
|
List<AutoRoute> get routes => [
|
||||||
RedirectRoute(path: '/', redirectTo: '/explore'),
|
|
||||||
AutoRoute(
|
AutoRoute(
|
||||||
page: ExploreShellRoute.page,
|
page: ExploreShellRoute.page,
|
||||||
path: '/explore',
|
path: '/',
|
||||||
children: [
|
children: [
|
||||||
AutoRoute(page: ExploreRoute.page, path: ''),
|
AutoRoute(page: ExploreRoute.page, path: ''),
|
||||||
AutoRoute(page: PostComposeRoute.page, path: 'posts/compose'),
|
AutoRoute(page: PostComposeRoute.page, path: 'posts/compose'),
|
||||||
AutoRoute(page: PostDetailRoute.page, path: 'posts/:id'),
|
AutoRoute(page: PostDetailRoute.page, path: 'posts/:id'),
|
||||||
AutoRoute(page: PostEditRoute.page, path: 'posts/:id/edit'),
|
AutoRoute(page: PostEditRoute.page, path: 'posts/:id/edit'),
|
||||||
|
AutoRoute(page: PublisherProfileRoute.page, path: 'publishers/:name'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
AutoRoute(
|
AutoRoute(
|
||||||
@@ -28,12 +28,11 @@ class AppRouter extends RootStackRouter {
|
|||||||
AutoRoute(page: WalletRoute.page, path: 'wallet'),
|
AutoRoute(page: WalletRoute.page, path: 'wallet'),
|
||||||
AutoRoute(page: RelationshipRoute.page, path: 'relationships'),
|
AutoRoute(page: RelationshipRoute.page, path: 'relationships'),
|
||||||
AutoRoute(page: AccountProfileRoute.page, path: ':name'),
|
AutoRoute(page: AccountProfileRoute.page, path: ':name'),
|
||||||
AutoRoute(page: PublisherProfileRoute.page, path: ':name/calendar'),
|
|
||||||
AutoRoute(page: MyselfEventCalendarRoute.page, path: 'me/calendar'),
|
|
||||||
AutoRoute(page: UpdateProfileRoute.page, path: 'me/update'),
|
AutoRoute(page: UpdateProfileRoute.page, path: 'me/update'),
|
||||||
AutoRoute(page: AccountSettingsRoute.page, path: 'settings'),
|
AutoRoute(page: AccountSettingsRoute.page, path: 'settings'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
AutoRoute(page: EventCalanderRoute.page, path: '/account/:name/calendar'),
|
||||||
AutoRoute(page: RealmListRoute.page, path: '/realms'),
|
AutoRoute(page: RealmListRoute.page, path: '/realms'),
|
||||||
AutoRoute(
|
AutoRoute(
|
||||||
page: ChatShellRoute.page,
|
page: ChatShellRoute.page,
|
||||||
@@ -41,6 +40,7 @@ class AppRouter extends RootStackRouter {
|
|||||||
children: [
|
children: [
|
||||||
AutoRoute(page: ChatListRoute.page, path: ''),
|
AutoRoute(page: ChatListRoute.page, path: ''),
|
||||||
AutoRoute(page: ChatRoomRoute.page, path: ':id'),
|
AutoRoute(page: ChatRoomRoute.page, path: ':id'),
|
||||||
|
AutoRoute(page: CallRoute.page, path: ':id/call'),
|
||||||
AutoRoute(page: NewChatRoute.page, path: 'new'),
|
AutoRoute(page: NewChatRoute.page, path: 'new'),
|
||||||
AutoRoute(page: EditChatRoute.page, path: ':id/edit'),
|
AutoRoute(page: EditChatRoute.page, path: ':id/edit'),
|
||||||
AutoRoute(page: ChatDetailRoute.page, path: ':id/detail'),
|
AutoRoute(page: ChatDetailRoute.page, path: ':id/detail'),
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
@@ -11,6 +11,7 @@ import 'package:island/pods/userinfo.dart';
|
|||||||
import 'package:island/route.gr.dart';
|
import 'package:island/route.gr.dart';
|
||||||
import 'package:island/screens/notification.dart';
|
import 'package:island/screens/notification.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
|
import 'package:island/widgets/account/account_name.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/account/leveling_progress.dart';
|
import 'package:island/widgets/account/leveling_progress.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
@@ -74,7 +75,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
if (user.value?.profile.backgroundId != null)
|
if (user.value?.profile.background?.id != null)
|
||||||
ClipRRect(
|
ClipRRect(
|
||||||
borderRadius: BorderRadius.only(
|
borderRadius: BorderRadius.only(
|
||||||
topLeft: Radius.circular(8),
|
topLeft: Radius.circular(8),
|
||||||
@@ -83,7 +84,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
child: AspectRatio(
|
child: AspectRatio(
|
||||||
aspectRatio: 16 / 7,
|
aspectRatio: 16 / 7,
|
||||||
child: CloudImageWidget(
|
child: CloudImageWidget(
|
||||||
fileId: user.value!.profile.backgroundId!,
|
file: user.value?.profile.background,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
@@ -94,7 +95,7 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: ProfilePictureWidget(
|
child: ProfilePictureWidget(
|
||||||
fileId: user.value?.profile.pictureId,
|
file: user.value?.profile.picture,
|
||||||
radius: 24,
|
radius: 24,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
@@ -112,7 +113,13 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.baseline,
|
crossAxisAlignment: CrossAxisAlignment.baseline,
|
||||||
textBaseline: TextBaseline.alphabetic,
|
textBaseline: TextBaseline.alphabetic,
|
||||||
children: [
|
children: [
|
||||||
Text(user.value!.nick).bold().fontSize(16),
|
AccountName(
|
||||||
|
account: user.value!,
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 16,
|
||||||
|
fontWeight: FontWeight.bold,
|
||||||
|
),
|
||||||
|
),
|
||||||
Text('@${user.value!.name}'),
|
Text('@${user.value!.name}'),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -235,6 +242,16 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
context.router.push(SettingsRoute());
|
context.router.push(SettingsRoute());
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
|
ListTile(
|
||||||
|
minTileHeight: 48,
|
||||||
|
leading: const Icon(Symbols.manage_accounts),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
|
title: Text('accountSettings').tr(),
|
||||||
|
onTap: () {
|
||||||
|
context.router.push(AccountSettingsRoute());
|
||||||
|
},
|
||||||
|
),
|
||||||
if (kDebugMode) const Divider(height: 1).padding(vertical: 8),
|
if (kDebugMode) const Divider(height: 1).padding(vertical: 8),
|
||||||
if (kDebugMode)
|
if (kDebugMode)
|
||||||
ListTile(
|
ListTile(
|
||||||
@@ -244,8 +261,8 @@ class AccountScreen extends HookConsumerWidget {
|
|||||||
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
contentPadding: EdgeInsets.symmetric(horizontal: 24),
|
||||||
title: Text('Copy access token'),
|
title: Text('Copy access token'),
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
final tk = ref.watch(tokenPairProvider);
|
final tk = ref.watch(tokenProvider);
|
||||||
Clipboard.setData(ClipboardData(text: tk!.accessToken));
|
Clipboard.setData(ClipboardData(text: tk!.token));
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
if (kDebugMode)
|
if (kDebugMode)
|
||||||
@@ -284,7 +301,7 @@ class _UnauthorizedAccountScreen extends StatelessWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context) {
|
Widget build(BuildContext context) {
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(title: const Text('Account')),
|
appBar: AppBar(title: const Text('account').tr()),
|
||||||
body:
|
body:
|
||||||
ConstrainedBox(
|
ConstrainedBox(
|
||||||
constraints: const BoxConstraints(maxWidth: 360),
|
constraints: const BoxConstraints(maxWidth: 360),
|
||||||
|
|||||||
@@ -7,7 +7,9 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/activity.dart';
|
import 'package:island/models/activity.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/screens/account/profile.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
@@ -17,7 +19,7 @@ part 'event_calendar.g.dart';
|
|||||||
part 'event_calendar.freezed.dart';
|
part 'event_calendar.freezed.dart';
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class EventCalendarQuery with _$EventCalendarQuery {
|
sealed class EventCalendarQuery with _$EventCalendarQuery {
|
||||||
const factory EventCalendarQuery({
|
const factory EventCalendarQuery({
|
||||||
required String? uname,
|
required String? uname,
|
||||||
required int year,
|
required int year,
|
||||||
@@ -39,8 +41,9 @@ Future<List<SnEventCalendarEntry>> accountEventCalendar(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class MyselfEventCalendarScreen extends HookConsumerWidget {
|
class EventCalanderScreen extends HookConsumerWidget {
|
||||||
const MyselfEventCalendarScreen({super.key});
|
final String name;
|
||||||
|
const EventCalanderScreen({super.key, @PathParam("name") required this.name});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -49,150 +52,180 @@ class MyselfEventCalendarScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
final selectedDay = useState(DateTime.now());
|
final selectedDay = useState(DateTime.now());
|
||||||
|
|
||||||
|
final user = ref.watch(accountProvider(name));
|
||||||
final events = ref.watch(
|
final events = ref.watch(
|
||||||
accountEventCalendarProvider(
|
accountEventCalendarProvider(
|
||||||
EventCalendarQuery(
|
EventCalendarQuery(
|
||||||
uname: 'me',
|
uname: name,
|
||||||
year: selectedYear.value,
|
year: selectedYear.value,
|
||||||
month: selectedMonth.value,
|
month: selectedMonth.value,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
final content = Column(
|
||||||
|
children: [
|
||||||
|
TableCalendar(
|
||||||
|
locale: EasyLocalization.of(context)!.locale.toString(),
|
||||||
|
firstDay: DateTime.now().add(Duration(days: -3650)),
|
||||||
|
lastDay: DateTime.now().add(Duration(days: 3650)),
|
||||||
|
focusedDay: DateTime.utc(
|
||||||
|
selectedYear.value,
|
||||||
|
selectedMonth.value,
|
||||||
|
DateTime.now().day,
|
||||||
|
),
|
||||||
|
calendarFormat: CalendarFormat.month,
|
||||||
|
selectedDayPredicate: (day) {
|
||||||
|
return isSameDay(selectedDay.value, day);
|
||||||
|
},
|
||||||
|
onDaySelected: (value, _) {
|
||||||
|
selectedDay.value = value;
|
||||||
|
},
|
||||||
|
onPageChanged: (focusedDay) {
|
||||||
|
selectedMonth.value = focusedDay.month;
|
||||||
|
selectedYear.value = focusedDay.year;
|
||||||
|
},
|
||||||
|
eventLoader: (day) {
|
||||||
|
return events.value
|
||||||
|
?.where((e) => isSameDay(e.date, day))
|
||||||
|
.expand((e) => [...e.statuses, e.checkInResult])
|
||||||
|
.where((e) => e != null)
|
||||||
|
.toList() ??
|
||||||
|
[];
|
||||||
|
},
|
||||||
|
calendarBuilders: CalendarBuilders(
|
||||||
|
dowBuilder: (context, day) {
|
||||||
|
final text = DateFormat.EEEEE().format(day);
|
||||||
|
return Center(child: Text(text));
|
||||||
|
},
|
||||||
|
markerBuilder: (context, day, events) {
|
||||||
|
var checkInResult =
|
||||||
|
events.whereType<SnCheckInResult>().firstOrNull;
|
||||||
|
if (checkInResult != null) {
|
||||||
|
return Positioned(
|
||||||
|
top: 32,
|
||||||
|
child: Text(
|
||||||
|
['大凶', '凶', '中平', '吉', '大吉'][checkInResult.level],
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 9,
|
||||||
|
color:
|
||||||
|
isSameDay(selectedDay.value, day)
|
||||||
|
? Theme.of(context).colorScheme.onPrimaryContainer
|
||||||
|
: isSameDay(DateTime.now(), day)
|
||||||
|
? Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.onSecondaryContainer
|
||||||
|
: Theme.of(context).colorScheme.onSurface,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
const Divider(height: 1).padding(top: 8),
|
||||||
|
AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 300),
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
final event =
|
||||||
|
events.value
|
||||||
|
?.where((e) => isSameDay(e.date, selectedDay.value))
|
||||||
|
.firstOrNull;
|
||||||
|
return Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(DateFormat.EEEE().format(selectedDay.value))
|
||||||
|
.fontSize(16)
|
||||||
|
.bold()
|
||||||
|
.textColor(
|
||||||
|
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
Text(DateFormat.yMd().format(selectedDay.value))
|
||||||
|
.fontSize(12)
|
||||||
|
.textColor(
|
||||||
|
Theme.of(context).colorScheme.onSecondaryContainer,
|
||||||
|
),
|
||||||
|
const Gap(16),
|
||||||
|
if (event?.checkInResult != null)
|
||||||
|
Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'checkInResultLevel${event!.checkInResult!.level}',
|
||||||
|
).tr().fontSize(16).bold(),
|
||||||
|
for (final tip in event.checkInResult!.tips)
|
||||||
|
Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
Symbols.circle,
|
||||||
|
size: 12,
|
||||||
|
fill: 1,
|
||||||
|
).padding(top: 4, right: 4),
|
||||||
|
Expanded(
|
||||||
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text(tip.title).bold(),
|
||||||
|
Text(tip.content),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(top: 8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
if (event?.checkInResult == null &&
|
||||||
|
(event?.statuses.isEmpty ?? true))
|
||||||
|
Text('eventCalanderEmpty').tr(),
|
||||||
|
],
|
||||||
|
).padding(vertical: 24, horizontal: 24);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (name != 'me' && user.hasValue)
|
||||||
|
Container(
|
||||||
|
decoration: BoxDecoration(
|
||||||
|
border: Border.all(
|
||||||
|
width: 1 / MediaQuery.of(context).devicePixelRatio,
|
||||||
|
color: Theme.of(context).dividerColor,
|
||||||
|
),
|
||||||
|
borderRadius: BorderRadius.all(Radius.circular(8)),
|
||||||
|
),
|
||||||
|
margin: EdgeInsets.all(16),
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
elevation: 0,
|
||||||
|
color: Colors.transparent,
|
||||||
|
child: ListTile(
|
||||||
|
leading: ProfilePictureWidget(
|
||||||
|
fileId: user.value!.profile.picture?.id,
|
||||||
|
),
|
||||||
|
title: Text(user.value!.nick).bold(),
|
||||||
|
subtitle: Text('@${user.value!.name}'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
noBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
title: Text('eventCalander').tr(),
|
title: Text('eventCalander').tr(),
|
||||||
),
|
),
|
||||||
body: SingleChildScrollView(
|
body: SingleChildScrollView(
|
||||||
child: Column(
|
child:
|
||||||
children: [
|
MediaQuery.of(context).size.width > 480
|
||||||
TableCalendar(
|
? ConstrainedBox(
|
||||||
locale: EasyLocalization.of(context)!.locale.toString(),
|
constraints: BoxConstraints(maxWidth: 480),
|
||||||
firstDay: DateTime.now().add(Duration(days: -3650)),
|
child: Card(margin: EdgeInsets.all(16), child: content),
|
||||||
lastDay: DateTime.now().add(Duration(days: 3650)),
|
).center()
|
||||||
focusedDay: DateTime.utc(
|
: content,
|
||||||
selectedYear.value,
|
|
||||||
selectedMonth.value,
|
|
||||||
DateTime.now().day,
|
|
||||||
),
|
|
||||||
calendarFormat: CalendarFormat.month,
|
|
||||||
selectedDayPredicate: (day) {
|
|
||||||
return isSameDay(selectedDay.value, day);
|
|
||||||
},
|
|
||||||
onDaySelected: (value, _) {
|
|
||||||
selectedDay.value = value;
|
|
||||||
},
|
|
||||||
onPageChanged: (focusedDay) {
|
|
||||||
selectedMonth.value = focusedDay.month;
|
|
||||||
selectedYear.value = focusedDay.year;
|
|
||||||
},
|
|
||||||
eventLoader: (day) {
|
|
||||||
return events.value
|
|
||||||
?.where((e) => isSameDay(e.date, day))
|
|
||||||
.expand((e) => [...e.statuses, e.checkInResult])
|
|
||||||
.where((e) => e != null)
|
|
||||||
.toList() ??
|
|
||||||
[];
|
|
||||||
},
|
|
||||||
calendarBuilders: CalendarBuilders(
|
|
||||||
dowBuilder: (context, day) {
|
|
||||||
final text = DateFormat.EEEEE().format(day);
|
|
||||||
return Center(child: Text(text));
|
|
||||||
},
|
|
||||||
markerBuilder: (context, day, events) {
|
|
||||||
var checkInResult =
|
|
||||||
events.whereType<SnCheckInResult>().firstOrNull;
|
|
||||||
if (checkInResult != null) {
|
|
||||||
return Positioned(
|
|
||||||
top: 32,
|
|
||||||
child: Text(
|
|
||||||
['大凶', '凶', '中平', '吉', '大吉'][checkInResult.level],
|
|
||||||
style: TextStyle(
|
|
||||||
fontSize: 9,
|
|
||||||
color:
|
|
||||||
isSameDay(selectedDay.value, day)
|
|
||||||
? Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.onPrimaryContainer
|
|
||||||
: isSameDay(DateTime.now(), day)
|
|
||||||
? Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.onSecondaryContainer
|
|
||||||
: Theme.of(context).colorScheme.onSurface,
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
const Divider(height: 1).padding(top: 8),
|
|
||||||
AnimatedSwitcher(
|
|
||||||
duration: const Duration(milliseconds: 300),
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
final event =
|
|
||||||
events.value
|
|
||||||
?.where((e) => isSameDay(e.date, selectedDay.value))
|
|
||||||
.firstOrNull;
|
|
||||||
return Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text(DateFormat.EEEE().format(selectedDay.value))
|
|
||||||
.fontSize(16)
|
|
||||||
.bold()
|
|
||||||
.textColor(
|
|
||||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
|
||||||
),
|
|
||||||
Text(DateFormat.yMd().format(selectedDay.value))
|
|
||||||
.fontSize(12)
|
|
||||||
.textColor(
|
|
||||||
Theme.of(context).colorScheme.onSecondaryContainer,
|
|
||||||
),
|
|
||||||
const Gap(16),
|
|
||||||
if (event?.checkInResult != null)
|
|
||||||
Column(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
|
||||||
children: [
|
|
||||||
Text(
|
|
||||||
'checkInResultLevel${event!.checkInResult!.level}',
|
|
||||||
).tr().fontSize(16).bold(),
|
|
||||||
for (final tip in event.checkInResult!.tips)
|
|
||||||
Row(
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
|
||||||
spacing: 8,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Symbols.circle,
|
|
||||||
size: 12,
|
|
||||||
fill: 1,
|
|
||||||
).padding(top: 4, right: 4),
|
|
||||||
Expanded(
|
|
||||||
child: Column(
|
|
||||||
crossAxisAlignment:
|
|
||||||
CrossAxisAlignment.start,
|
|
||||||
children: [
|
|
||||||
Text(tip.title).bold(),
|
|
||||||
Text(tip.content),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
).padding(top: 8),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
if (event?.checkInResult == null &&
|
|
||||||
(event?.statuses.isEmpty ?? true))
|
|
||||||
Text('eventCalanderEmpty').tr(),
|
|
||||||
],
|
|
||||||
).padding(vertical: 24, horizontal: 24);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because it is too large
Load Diff
48
lib/screens/account/me/settings.g.dart
Normal file
48
lib/screens/account/me/settings.g.dart
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'settings.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$authFactorsHash() => r'4bb65bc0c065c4091c209ee81e57ddef41051ae2';
|
||||||
|
|
||||||
|
/// See also [authFactors].
|
||||||
|
@ProviderFor(authFactors)
|
||||||
|
final authFactorsProvider =
|
||||||
|
AutoDisposeFutureProvider<List<SnAuthFactor>>.internal(
|
||||||
|
authFactors,
|
||||||
|
name: r'authFactorsProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$authFactorsHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
typedef AuthFactorsRef = AutoDisposeFutureProviderRef<List<SnAuthFactor>>;
|
||||||
|
String _$contactMethodsHash() => r'4d7952fc196dce4dc646314565a49c115fd1d292';
|
||||||
|
|
||||||
|
/// See also [contactMethods].
|
||||||
|
@ProviderFor(contactMethods)
|
||||||
|
final contactMethodsProvider =
|
||||||
|
AutoDisposeFutureProvider<List<SnContactMethod>>.internal(
|
||||||
|
contactMethods,
|
||||||
|
name: r'contactMethodsProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$contactMethodsHash,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
);
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
typedef ContactMethodsRef = AutoDisposeFutureProviderRef<List<SnContactMethod>>;
|
||||||
|
// 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:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
@@ -59,19 +60,15 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
final baseUrl = ref.watch(serverUrlProvider);
|
||||||
final atk = await getFreshAtk(
|
final token = await getToken(ref.watch(tokenProvider));
|
||||||
ref.watch(tokenPairProvider),
|
if (token == null) throw ArgumentError('Token is null');
|
||||||
baseUrl,
|
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (atk == null) throw ArgumentError('Access token is null');
|
|
||||||
final cloudFile =
|
final cloudFile =
|
||||||
await putMediaToCloud(
|
await putMediaToCloud(
|
||||||
fileData: result,
|
fileData: UniversalFile(
|
||||||
atk: atk,
|
data: result,
|
||||||
|
type: UniversalFileType.image,
|
||||||
|
),
|
||||||
|
atk: token,
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
filename: result.name,
|
filename: result.name,
|
||||||
mimetype: result.mimeType ?? 'image/jpeg',
|
mimetype: result.mimeType ?? 'image/jpeg',
|
||||||
@@ -166,9 +163,9 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
child: Container(
|
child: Container(
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
||||||
child:
|
child:
|
||||||
user.value!.profile.backgroundId != null
|
user.value!.profile.background?.id != null
|
||||||
? CloudImageWidget(
|
? CloudImageWidget(
|
||||||
fileId: user.value!.profile.backgroundId!,
|
fileId: user.value!.profile.background!.id,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
)
|
)
|
||||||
: const SizedBox.shrink(),
|
: const SizedBox.shrink(),
|
||||||
@@ -182,7 +179,7 @@ class UpdateProfileScreen extends HookConsumerWidget {
|
|||||||
bottom: -32,
|
bottom: -32,
|
||||||
child: GestureDetector(
|
child: GestureDetector(
|
||||||
child: ProfilePictureWidget(
|
child: ProfilePictureWidget(
|
||||||
fileId: user.value!.profile.pictureId,
|
fileId: user.value!.profile.picture?.id,
|
||||||
radius: 40,
|
radius: 40,
|
||||||
),
|
),
|
||||||
onTap: () {
|
onTap: () {
|
||||||
|
|||||||
@@ -4,12 +4,16 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/user.dart';
|
import 'package:island/models/user.dart';
|
||||||
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/pods/userinfo.dart';
|
||||||
|
import 'package:island/services/color.dart';
|
||||||
import 'package:island/widgets/account/badge.dart';
|
import 'package:island/widgets/account/badge.dart';
|
||||||
import 'package:island/widgets/account/leveling_progress.dart';
|
import 'package:island/widgets/account/leveling_progress.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
@@ -17,6 +21,12 @@ part 'profile.g.dart';
|
|||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
Future<SnAccount> account(Ref ref, String uname) async {
|
Future<SnAccount> account(Ref ref, String uname) async {
|
||||||
|
if (uname == 'me') {
|
||||||
|
final userInfo = ref.watch(userInfoProvider);
|
||||||
|
if (userInfo.hasValue && userInfo.value != null) {
|
||||||
|
return userInfo.value!;
|
||||||
|
}
|
||||||
|
}
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
final resp = await apiClient.get("/accounts/$uname");
|
final resp = await apiClient.get("/accounts/$uname");
|
||||||
return SnAccount.fromJson(resp.data);
|
return SnAccount.fromJson(resp.data);
|
||||||
@@ -31,6 +41,21 @@ Future<List<SnAccountBadge>> accountBadges(Ref ref, String uname) async {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<Color?> accountAppbarForcegroundColor(Ref ref, String uname) async {
|
||||||
|
final account = await ref.watch(accountProvider(uname).future);
|
||||||
|
if (account.profile.background == null) return null;
|
||||||
|
final palette = await PaletteGenerator.fromImageProvider(
|
||||||
|
CloudImageWidget.provider(
|
||||||
|
fileId: account.profile.background!.id,
|
||||||
|
serverUrl: ref.watch(serverUrlProvider),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final dominantColor = palette.dominantColor?.color;
|
||||||
|
if (dominantColor == null) return null;
|
||||||
|
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||||
|
}
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class AccountProfileScreen extends HookConsumerWidget {
|
class AccountProfileScreen extends HookConsumerWidget {
|
||||||
final String name;
|
final String name;
|
||||||
@@ -42,11 +67,12 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final account = ref.watch(accountProvider(name));
|
final account = ref.watch(accountProvider(name));
|
||||||
|
final appbarColor = ref.watch(accountAppbarForcegroundColorProvider(name));
|
||||||
|
|
||||||
final iconShadow = Shadow(
|
final appbarShadow = Shadow(
|
||||||
color: Colors.black54,
|
color: appbarColor.value?.invert ?? Colors.black54,
|
||||||
blurRadius: 5.0,
|
blurRadius: 5.0,
|
||||||
offset: const Offset(1.0, 1.0),
|
offset: Offset(1.0, 1.0),
|
||||||
);
|
);
|
||||||
|
|
||||||
return account.when(
|
return account.when(
|
||||||
@@ -55,26 +81,40 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
body: CustomScrollView(
|
body: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverAppBar(
|
SliverAppBar(
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
expandedHeight: 180,
|
expandedHeight: 180,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
leading: PageBackButton(shadows: [iconShadow]),
|
leading: PageBackButton(
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
color: appbarColor.value,
|
||||||
background:
|
shadows: [appbarShadow],
|
||||||
data.profile.backgroundId != null
|
),
|
||||||
? CloudImageWidget(
|
flexibleSpace: Stack(
|
||||||
fileId: data.profile.backgroundId!,
|
children: [
|
||||||
)
|
Positioned.fill(
|
||||||
: Container(
|
child:
|
||||||
color:
|
data.profile.background?.id != null
|
||||||
Theme.of(context).appBarTheme.backgroundColor,
|
? CloudImageWidget(
|
||||||
),
|
file: data.profile.background,
|
||||||
title: Text(
|
)
|
||||||
data.nick,
|
: Container(
|
||||||
style: TextStyle(
|
color:
|
||||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
Theme.of(
|
||||||
shadows: [iconShadow],
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
data.nick,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(context).appBarTheme.foregroundColor,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
@@ -84,7 +124,7 @@ class AccountProfileScreen extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
ProfilePictureWidget(
|
ProfilePictureWidget(
|
||||||
fileId: data.profile.pictureId,
|
file: data.profile.picture,
|
||||||
radius: 32,
|
radius: 32,
|
||||||
),
|
),
|
||||||
const Gap(20),
|
const Gap(20),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part of 'profile.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$accountHash() => r'39003ef3250181b9290e0562329c7801d4841941';
|
String _$accountHash() => r'd2b0579617e6264452d98f47f695a9cdf45b24ec';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
@@ -267,5 +267,133 @@ class _AccountBadgesProviderElement
|
|||||||
String get uname => (origin as AccountBadgesProvider).uname;
|
String get uname => (origin as AccountBadgesProvider).uname;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _$accountAppbarForcegroundColorHash() =>
|
||||||
|
r'f654a7a5594eda1500906e9ad023c22772257a9b';
|
||||||
|
|
||||||
|
/// See also [accountAppbarForcegroundColor].
|
||||||
|
@ProviderFor(accountAppbarForcegroundColor)
|
||||||
|
const accountAppbarForcegroundColorProvider =
|
||||||
|
AccountAppbarForcegroundColorFamily();
|
||||||
|
|
||||||
|
/// See also [accountAppbarForcegroundColor].
|
||||||
|
class AccountAppbarForcegroundColorFamily extends Family<AsyncValue<Color?>> {
|
||||||
|
/// See also [accountAppbarForcegroundColor].
|
||||||
|
const AccountAppbarForcegroundColorFamily();
|
||||||
|
|
||||||
|
/// See also [accountAppbarForcegroundColor].
|
||||||
|
AccountAppbarForcegroundColorProvider call(String uname) {
|
||||||
|
return AccountAppbarForcegroundColorProvider(uname);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AccountAppbarForcegroundColorProvider getProviderOverride(
|
||||||
|
covariant AccountAppbarForcegroundColorProvider 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'accountAppbarForcegroundColorProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [accountAppbarForcegroundColor].
|
||||||
|
class AccountAppbarForcegroundColorProvider
|
||||||
|
extends AutoDisposeFutureProvider<Color?> {
|
||||||
|
/// See also [accountAppbarForcegroundColor].
|
||||||
|
AccountAppbarForcegroundColorProvider(String uname)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => accountAppbarForcegroundColor(
|
||||||
|
ref as AccountAppbarForcegroundColorRef,
|
||||||
|
uname,
|
||||||
|
),
|
||||||
|
from: accountAppbarForcegroundColorProvider,
|
||||||
|
name: r'accountAppbarForcegroundColorProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$accountAppbarForcegroundColorHash,
|
||||||
|
dependencies: AccountAppbarForcegroundColorFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
AccountAppbarForcegroundColorFamily._allTransitiveDependencies,
|
||||||
|
uname: uname,
|
||||||
|
);
|
||||||
|
|
||||||
|
AccountAppbarForcegroundColorProvider._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<Color?> Function(AccountAppbarForcegroundColorRef provider) create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: AccountAppbarForcegroundColorProvider._internal(
|
||||||
|
(ref) => create(ref as AccountAppbarForcegroundColorRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
uname: uname,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<Color?> createElement() {
|
||||||
|
return _AccountAppbarForcegroundColorProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is AccountAppbarForcegroundColorProvider &&
|
||||||
|
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 AccountAppbarForcegroundColorRef on AutoDisposeFutureProviderRef<Color?> {
|
||||||
|
/// The parameter `uname` of this provider.
|
||||||
|
String get uname;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _AccountAppbarForcegroundColorProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<Color?>
|
||||||
|
with AccountAppbarForcegroundColorRef {
|
||||||
|
_AccountAppbarForcegroundColorProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get uname => (origin as AccountAppbarForcegroundColorProvider).uname;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
|||||||
@@ -96,12 +96,11 @@ class RelationshipListTile extends StatelessWidget {
|
|||||||
relationship.status == 0 && relationship.relatedId == currentUserId;
|
relationship.status == 0 && relationship.relatedId == currentUserId;
|
||||||
final isWaiting =
|
final isWaiting =
|
||||||
relationship.status == 0 && relationship.accountId == currentUserId;
|
relationship.status == 0 && relationship.accountId == currentUserId;
|
||||||
final isEstablished =
|
final isEstablished = relationship.status == 1 || relationship.status == 2;
|
||||||
relationship.status >= 100 || relationship.status <= -100;
|
|
||||||
|
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: const EdgeInsets.only(left: 16, right: 12),
|
contentPadding: const EdgeInsets.only(left: 16, right: 12),
|
||||||
leading: ProfilePictureWidget(fileId: account.profile.pictureId),
|
leading: ProfilePictureWidget(fileId: account.profile.picture?.id),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
|
|||||||
@@ -75,6 +75,7 @@ class CreateAccountScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
noBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
title: Text('createAccount').tr(),
|
title: Text('createAccount').tr(),
|
||||||
|
|||||||
@@ -1,9 +1,16 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
import 'dart:io';
|
||||||
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:animations/animations.dart';
|
import 'package:animations/animations.dart';
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
|
import 'package:device_info_plus/device_info_plus.dart';
|
||||||
|
import 'package:dio/dio.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
|
import 'package:flutter_otp_text_field/flutter_otp_text_field.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:gap/gap.dart';
|
import 'package:gap/gap.dart';
|
||||||
import 'package:island/models/auth.dart';
|
import 'package:island/models/auth.dart';
|
||||||
@@ -19,15 +26,17 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
|
|
||||||
|
import 'captcha.dart';
|
||||||
|
|
||||||
final Map<int, (String, String, IconData)> kFactorTypes = {
|
final Map<int, (String, String, IconData)> kFactorTypes = {
|
||||||
0: ('authFactorPassword', 'authFactorPasswordDescription', Symbols.password),
|
0: ('authFactorPassword', 'authFactorPasswordDescription', Symbols.password),
|
||||||
1: ('authFactorEmail', 'authFactorEmailDescription', Symbols.email),
|
1: ('authFactorEmail', 'authFactorEmailDescription', Symbols.email),
|
||||||
2: ('authFactorTOTP', 'authFactorTOTPDescription', Symbols.timer),
|
2: (
|
||||||
3: (
|
|
||||||
'authFactorInAppNotify',
|
'authFactorInAppNotify',
|
||||||
'authFactorInAppNotifyDescription',
|
'authFactorInAppNotifyDescription',
|
||||||
Symbols.notifications_active,
|
Symbols.notifications_active,
|
||||||
),
|
),
|
||||||
|
3: ('authFactorTOTP', 'authFactorTOTPDescription', Symbols.timer),
|
||||||
};
|
};
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
@@ -36,65 +45,102 @@ class LoginScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final isBusy = useState(false);
|
||||||
|
|
||||||
final period = useState(0);
|
final period = useState(0);
|
||||||
final currentTicket = useState<SnAuthChallenge?>(null);
|
final currentTicket = useState<SnAuthChallenge?>(null);
|
||||||
final factors = useState<List<SnAuthFactor>>([]);
|
final factors = useState<List<SnAuthFactor>>([]);
|
||||||
final factorPicked = useState<SnAuthFactor?>(null);
|
final factorPicked = useState<SnAuthFactor?>(null);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
|
noBackground: false,
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
title: Text('login').tr(),
|
title: Text('login').tr(),
|
||||||
),
|
),
|
||||||
body: Theme(
|
body: Theme(
|
||||||
data: Theme.of(context).copyWith(canvasColor: Colors.transparent),
|
data: Theme.of(context).copyWith(canvasColor: Colors.transparent),
|
||||||
child:
|
child: Column(
|
||||||
SingleChildScrollView(
|
children: [
|
||||||
child: PageTransitionSwitcher(
|
if (isBusy.value)
|
||||||
transitionBuilder: (
|
LinearProgressIndicator(
|
||||||
Widget child,
|
minHeight: 4,
|
||||||
Animation<double> primaryAnimation,
|
borderRadius: BorderRadius.zero,
|
||||||
Animation<double> secondaryAnimation,
|
trackGap: 0,
|
||||||
) {
|
stopIndicatorRadius: 0,
|
||||||
return SharedAxisTransition(
|
)
|
||||||
animation: primaryAnimation,
|
else if (currentTicket.value != null)
|
||||||
secondaryAnimation: secondaryAnimation,
|
LinearProgressIndicator(
|
||||||
transitionType: SharedAxisTransitionType.horizontal,
|
minHeight: 4,
|
||||||
child: Container(
|
borderRadius: BorderRadius.zero,
|
||||||
constraints: BoxConstraints(maxWidth: 380),
|
trackGap: 0,
|
||||||
child: child,
|
stopIndicatorRadius: 0,
|
||||||
),
|
value:
|
||||||
);
|
1 -
|
||||||
},
|
(currentTicket.value!.stepRemain /
|
||||||
child: switch (period.value % 3) {
|
currentTicket.value!.stepTotal),
|
||||||
1 => _LoginPickerScreen(
|
)
|
||||||
key: const ValueKey(1),
|
else
|
||||||
ticket: currentTicket.value,
|
const Gap(4),
|
||||||
factors: factors.value,
|
Expanded(
|
||||||
onChallenge:
|
child:
|
||||||
(SnAuthChallenge? p0) => currentTicket.value = p0,
|
SingleChildScrollView(
|
||||||
onPickFactor: (SnAuthFactor p0) => factorPicked.value = p0,
|
child: PageTransitionSwitcher(
|
||||||
onNext: () => period.value++,
|
transitionBuilder: (
|
||||||
),
|
Widget child,
|
||||||
2 => _LoginCheckScreen(
|
Animation<double> primaryAnimation,
|
||||||
key: const ValueKey(2),
|
Animation<double> secondaryAnimation,
|
||||||
challenge: currentTicket.value,
|
) {
|
||||||
factor: factorPicked.value,
|
return SharedAxisTransition(
|
||||||
onChallenge:
|
animation: primaryAnimation,
|
||||||
(SnAuthChallenge? p0) => currentTicket.value = p0,
|
secondaryAnimation: secondaryAnimation,
|
||||||
onNext: () => period.value++,
|
transitionType: SharedAxisTransitionType.horizontal,
|
||||||
),
|
child: Container(
|
||||||
_ => _LoginLookupScreen(
|
constraints: BoxConstraints(maxWidth: 380),
|
||||||
key: const ValueKey(0),
|
child: child,
|
||||||
ticket: currentTicket.value,
|
),
|
||||||
onChallenge:
|
);
|
||||||
(SnAuthChallenge? p0) => currentTicket.value = p0,
|
},
|
||||||
onFactor:
|
child: switch (period.value % 3) {
|
||||||
(List<SnAuthFactor>? p0) => factors.value = p0 ?? [],
|
1 => _LoginPickerScreen(
|
||||||
onNext: () => period.value++,
|
key: const ValueKey(1),
|
||||||
),
|
ticket: currentTicket.value,
|
||||||
},
|
factors: factors.value,
|
||||||
).padding(all: 24),
|
onChallenge:
|
||||||
).center(),
|
(SnAuthChallenge? p0) => currentTicket.value = p0,
|
||||||
|
onPickFactor:
|
||||||
|
(SnAuthFactor p0) => factorPicked.value = p0,
|
||||||
|
onNext: () => period.value++,
|
||||||
|
onBusy: (value) => isBusy.value = value,
|
||||||
|
),
|
||||||
|
2 => _LoginCheckScreen(
|
||||||
|
key: const ValueKey(2),
|
||||||
|
challenge: currentTicket.value,
|
||||||
|
factor: factorPicked.value,
|
||||||
|
onChallenge:
|
||||||
|
(SnAuthChallenge? p0) => currentTicket.value = p0,
|
||||||
|
onNext: () => period.value = 1,
|
||||||
|
onBusy: (value) => isBusy.value = value,
|
||||||
|
),
|
||||||
|
_ => _LoginLookupScreen(
|
||||||
|
key: const ValueKey(0),
|
||||||
|
ticket: currentTicket.value,
|
||||||
|
onChallenge:
|
||||||
|
(SnAuthChallenge? p0) => currentTicket.value = p0,
|
||||||
|
onFactor:
|
||||||
|
(List<SnAuthFactor>? p0) =>
|
||||||
|
factors.value = p0 ?? [],
|
||||||
|
onNext: () => period.value++,
|
||||||
|
onBusy: (value) => isBusy.value = value,
|
||||||
|
),
|
||||||
|
},
|
||||||
|
).padding(all: 24),
|
||||||
|
).center(),
|
||||||
|
),
|
||||||
|
|
||||||
|
const Gap(4),
|
||||||
|
],
|
||||||
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -104,7 +150,8 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
|||||||
final SnAuthChallenge? challenge;
|
final SnAuthChallenge? challenge;
|
||||||
final SnAuthFactor? factor;
|
final SnAuthFactor? factor;
|
||||||
final Function(SnAuthChallenge?) onChallenge;
|
final Function(SnAuthChallenge?) onChallenge;
|
||||||
final Function onNext;
|
final VoidCallback onNext;
|
||||||
|
final Function(bool) onBusy;
|
||||||
|
|
||||||
const _LoginCheckScreen({
|
const _LoginCheckScreen({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -112,6 +159,7 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
|||||||
required this.factor,
|
required this.factor,
|
||||||
required this.onChallenge,
|
required this.onChallenge,
|
||||||
required this.onNext,
|
required this.onNext,
|
||||||
|
required this.onBusy,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -119,11 +167,17 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
|||||||
final isBusy = useState(false);
|
final isBusy = useState(false);
|
||||||
final passwordController = useTextEditingController();
|
final passwordController = useTextEditingController();
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
onBusy.call(isBusy.value);
|
||||||
|
return null;
|
||||||
|
}, [isBusy]);
|
||||||
|
|
||||||
Future<void> performCheckTicket() async {
|
Future<void> performCheckTicket() async {
|
||||||
final pwd = passwordController.value.text;
|
final pwd = passwordController.value.text;
|
||||||
if (pwd.isEmpty) return;
|
if (pwd.isEmpty) return;
|
||||||
isBusy.value = true;
|
isBusy.value = true;
|
||||||
try {
|
try {
|
||||||
|
// Pass challenge
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
final resp = await client.patch(
|
final resp = await client.patch(
|
||||||
'/auth/challenge/${challenge!.id}',
|
'/auth/challenge/${challenge!.id}',
|
||||||
@@ -135,15 +189,18 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
|||||||
onNext();
|
onNext();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get token if challenge is completed
|
||||||
final tokenResp = await client.post(
|
final tokenResp = await client.post(
|
||||||
'/auth/token',
|
'/auth/token',
|
||||||
data: {'grant_type': 'authorization_code', 'code': result.id},
|
data: {'grant_type': 'authorization_code', 'code': result.id},
|
||||||
);
|
);
|
||||||
final atk = tokenResp.data['access_token'];
|
final token = tokenResp.data['token'];
|
||||||
final rtk = tokenResp.data['refresh_token'];
|
setToken(ref.watch(sharedPreferencesProvider), token);
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
ref.invalidate(tokenProvider);
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
if (!context.mounted) return;
|
if (!context.mounted) return;
|
||||||
|
|
||||||
|
// Do post login tasks
|
||||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||||
userNotifier.fetchUser().then((_) {
|
userNotifier.fetchUser().then((_) {
|
||||||
final apiClient = ref.read(apiClientProvider);
|
final apiClient = ref.read(apiClientProvider);
|
||||||
@@ -152,6 +209,28 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
|||||||
wsNotifier.connect();
|
wsNotifier.connect();
|
||||||
if (context.mounted) Navigator.pop(context, true);
|
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(
|
||||||
|
'/accounts/me/sessions/current/label',
|
||||||
|
data: jsonEncode(name),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
return;
|
return;
|
||||||
@@ -160,6 +239,8 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final width = math.min(380, MediaQuery.of(context).size.width);
|
||||||
|
|
||||||
return Column(
|
return Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
@@ -174,24 +255,49 @@ class _LoginCheckScreen extends HookConsumerWidget {
|
|||||||
'loginEnterPassword'.tr(),
|
'loginEnterPassword'.tr(),
|
||||||
style: const TextStyle(fontSize: 28, fontWeight: FontWeight.w900),
|
style: const TextStyle(fontSize: 28, fontWeight: FontWeight.w900),
|
||||||
).padding(left: 4, bottom: 16),
|
).padding(left: 4, bottom: 16),
|
||||||
TextField(
|
if ([0].contains(factor!.type))
|
||||||
autocorrect: false,
|
TextField(
|
||||||
enableSuggestions: false,
|
autocorrect: false,
|
||||||
controller: passwordController,
|
enableSuggestions: false,
|
||||||
obscureText: true,
|
controller: passwordController,
|
||||||
autofillHints: [
|
obscureText: true,
|
||||||
factor!.type == 0
|
autofillHints: [
|
||||||
? AutofillHints.password
|
factor!.type == 0
|
||||||
: AutofillHints.oneTimeCode,
|
? AutofillHints.password
|
||||||
],
|
: AutofillHints.oneTimeCode,
|
||||||
decoration: InputDecoration(
|
],
|
||||||
isDense: true,
|
decoration: InputDecoration(
|
||||||
border: const UnderlineInputBorder(),
|
isDense: true,
|
||||||
labelText: 'password'.tr(),
|
border: const OutlineInputBorder(),
|
||||||
|
labelText: 'password'.tr(),
|
||||||
|
),
|
||||||
|
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
onSubmitted: isBusy.value ? null : (_) => performCheckTicket(),
|
||||||
|
).padding(horizontal: 7)
|
||||||
|
else
|
||||||
|
OtpTextField(
|
||||||
|
showCursor: false,
|
||||||
|
numberOfFields: 6,
|
||||||
|
obscureText: false,
|
||||||
|
showFieldAsBox: true,
|
||||||
|
focusedBorderColor: Theme.of(context).colorScheme.primary,
|
||||||
|
fieldWidth: (width / 6) - 10,
|
||||||
|
onSubmit: (value) {
|
||||||
|
passwordController.text = value;
|
||||||
|
performCheckTicket();
|
||||||
|
},
|
||||||
|
textStyle: Theme.of(context).textTheme.titleLarge!,
|
||||||
),
|
),
|
||||||
onTapOutside: (_) => FocusManager.instance.primaryFocus?.unfocus(),
|
const Gap(12),
|
||||||
onSubmitted: isBusy.value ? null : (_) => performCheckTicket(),
|
Card(
|
||||||
).padding(horizontal: 7),
|
child: ListTile(
|
||||||
|
leading: Icon(
|
||||||
|
kFactorTypes[factor!.type]?.$3 ?? Symbols.question_mark,
|
||||||
|
),
|
||||||
|
title: Text(kFactorTypes[factor!.type]?.$1 ?? 'unknown').tr(),
|
||||||
|
subtitle: Text(kFactorTypes[factor!.type]?.$2 ?? 'unknown').tr(),
|
||||||
|
),
|
||||||
|
),
|
||||||
const Gap(12),
|
const Gap(12),
|
||||||
Row(
|
Row(
|
||||||
mainAxisAlignment: MainAxisAlignment.end,
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
@@ -218,7 +324,8 @@ class _LoginPickerScreen extends HookConsumerWidget {
|
|||||||
final List<SnAuthFactor>? factors;
|
final List<SnAuthFactor>? factors;
|
||||||
final Function(SnAuthChallenge?) onChallenge;
|
final Function(SnAuthChallenge?) onChallenge;
|
||||||
final Function(SnAuthFactor) onPickFactor;
|
final Function(SnAuthFactor) onPickFactor;
|
||||||
final Function onNext;
|
final VoidCallback onNext;
|
||||||
|
final Function(bool) onBusy;
|
||||||
|
|
||||||
const _LoginPickerScreen({
|
const _LoginPickerScreen({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -227,17 +334,25 @@ class _LoginPickerScreen extends HookConsumerWidget {
|
|||||||
required this.onChallenge,
|
required this.onChallenge,
|
||||||
required this.onPickFactor,
|
required this.onPickFactor,
|
||||||
required this.onNext,
|
required this.onNext,
|
||||||
|
required this.onBusy,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final isBusy = useState(false);
|
final isBusy = useState(false);
|
||||||
final factorPicked = useState<String?>(null);
|
final factorPicked = useState<SnAuthFactor?>(null);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
onBusy.call(isBusy.value);
|
||||||
|
return null;
|
||||||
|
}, [isBusy]);
|
||||||
|
|
||||||
final unfocusColor = Theme.of(
|
final unfocusColor = Theme.of(
|
||||||
context,
|
context,
|
||||||
).colorScheme.onSurface.withAlpha((255 * 0.75).round());
|
).colorScheme.onSurface.withAlpha((255 * 0.75).round());
|
||||||
|
|
||||||
|
final hintController = useTextEditingController();
|
||||||
|
|
||||||
void performGetFactorCode() async {
|
void performGetFactorCode() async {
|
||||||
if (factorPicked.value == null) return;
|
if (factorPicked.value == null) return;
|
||||||
|
|
||||||
@@ -245,13 +360,24 @@ class _LoginPickerScreen extends HookConsumerWidget {
|
|||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
// Request one-time-password code
|
|
||||||
await client.post(
|
await client.post(
|
||||||
'/auth/challenge/${ticket!.id}/factors/${factorPicked.value}',
|
'/auth/challenge/${ticket!.id}/factors/${factorPicked.value!.id}',
|
||||||
|
data:
|
||||||
|
hintController.text.isNotEmpty
|
||||||
|
? jsonEncode(hintController.text)
|
||||||
|
: null,
|
||||||
);
|
);
|
||||||
onPickFactor(factors!.where((x) => x.id == factorPicked.value).first);
|
onPickFactor(factors!.where((x) => x == factorPicked.value).first);
|
||||||
onNext();
|
onNext();
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
|
if (err is DioException && err.response?.statusCode == 400) {
|
||||||
|
onPickFactor(factors!.where((x) => x == factorPicked.value).first);
|
||||||
|
onNext();
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(context, err.response!.data.toString());
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
return;
|
return;
|
||||||
} finally {
|
} finally {
|
||||||
@@ -290,10 +416,10 @@ class _LoginPickerScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
title: Text(kFactorTypes[x.type]?.$1 ?? 'unknown').tr(),
|
title: Text(kFactorTypes[x.type]?.$1 ?? 'unknown').tr(),
|
||||||
enabled: !ticket!.blacklistFactors.contains(x.id),
|
enabled: !ticket!.blacklistFactors.contains(x.id),
|
||||||
value: factorPicked.value == x.id,
|
value: factorPicked.value == x,
|
||||||
onChanged: (value) {
|
onChanged: (value) {
|
||||||
if (value == true) {
|
if (value == true) {
|
||||||
factorPicked.value = x.id;
|
factorPicked.value = x;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
@@ -302,6 +428,16 @@ class _LoginPickerScreen extends HookConsumerWidget {
|
|||||||
List.empty(),
|
List.empty(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
if ([1].contains(factorPicked.value?.type))
|
||||||
|
TextField(
|
||||||
|
controller: hintController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
isDense: true,
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
labelText: 'authFactorHint'.tr(),
|
||||||
|
helperText: 'authFactorHintHelper'.tr(),
|
||||||
|
),
|
||||||
|
).padding(top: 12, bottom: 4, horizontal: 4),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
Text(
|
Text(
|
||||||
'loginMultiFactor'.plural(ticket!.stepRemain),
|
'loginMultiFactor'.plural(ticket!.stepRemain),
|
||||||
@@ -332,7 +468,8 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
|||||||
final SnAuthChallenge? ticket;
|
final SnAuthChallenge? ticket;
|
||||||
final Function(SnAuthChallenge?) onChallenge;
|
final Function(SnAuthChallenge?) onChallenge;
|
||||||
final Function(List<SnAuthFactor>?) onFactor;
|
final Function(List<SnAuthFactor>?) onFactor;
|
||||||
final Function onNext;
|
final VoidCallback onNext;
|
||||||
|
final Function(bool) onBusy;
|
||||||
|
|
||||||
const _LoginLookupScreen({
|
const _LoginLookupScreen({
|
||||||
super.key,
|
super.key,
|
||||||
@@ -340,6 +477,7 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
|||||||
required this.onChallenge,
|
required this.onChallenge,
|
||||||
required this.onFactor,
|
required this.onFactor,
|
||||||
required this.onNext,
|
required this.onNext,
|
||||||
|
required this.onBusy,
|
||||||
});
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
@@ -347,21 +485,29 @@ class _LoginLookupScreen extends HookConsumerWidget {
|
|||||||
final isBusy = useState(false);
|
final isBusy = useState(false);
|
||||||
final usernameController = useTextEditingController();
|
final usernameController = useTextEditingController();
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
onBusy.call(isBusy.value);
|
||||||
|
return null;
|
||||||
|
}, [isBusy]);
|
||||||
|
|
||||||
Future<void> requestResetPassword() async {
|
Future<void> requestResetPassword() async {
|
||||||
final uname = usernameController.value.text;
|
final uname = usernameController.value.text;
|
||||||
if (uname.isEmpty) {
|
if (uname.isEmpty) {
|
||||||
showErrorAlert('loginResetPasswordHint'.tr());
|
showErrorAlert('loginResetPasswordHint'.tr());
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
final captchaTk = await Navigator.of(
|
||||||
|
context,
|
||||||
|
).push(MaterialPageRoute(builder: (context) => CaptchaScreen()));
|
||||||
|
if (captchaTk == null) return;
|
||||||
isBusy.value = true;
|
isBusy.value = true;
|
||||||
try {
|
try {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
final lookupResp = await client.get('/users/lookup?probe=$uname');
|
|
||||||
await client.post(
|
await client.post(
|
||||||
'/users/me/password-reset',
|
'/accounts/recovery/password',
|
||||||
data: {'user_id': lookupResp.data['id']},
|
data: {'account': uname, 'captcha_token': captchaTk},
|
||||||
);
|
);
|
||||||
showInfoAlert('done'.tr(), 'signinResetPasswordSent'.tr());
|
showInfoAlert('loginResetPasswordSent'.tr(), 'done'.tr());
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
} finally {
|
} finally {
|
||||||
|
|||||||
@@ -1,3 +1,5 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
@@ -17,6 +19,8 @@ class TabNavigationObserver extends AutoRouterObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void didPush(Route route, Route? previousRoute) {
|
void didPush(Route route, Route? previousRoute) {
|
||||||
|
log('pushed ${previousRoute?.settings.name} -> ${route.settings.name}');
|
||||||
|
if (route is DialogRoute) return;
|
||||||
Future(() {
|
Future(() {
|
||||||
onChange(route.settings.name);
|
onChange(route.settings.name);
|
||||||
});
|
});
|
||||||
@@ -24,6 +28,8 @@ class TabNavigationObserver extends AutoRouterObserver {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
void didPop(Route route, Route? previousRoute) {
|
void didPop(Route route, Route? previousRoute) {
|
||||||
|
log('popped ${route.settings.name} -> ${previousRoute?.settings.name}');
|
||||||
|
if (route is DialogRoute) return;
|
||||||
Future(() {
|
Future(() {
|
||||||
onChange(previousRoute?.settings.name);
|
onChange(previousRoute?.settings.name);
|
||||||
});
|
});
|
||||||
@@ -43,7 +49,6 @@ class TabsNavigationWidget extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final useHorizontalLayout = isWideScreen(context);
|
final useHorizontalLayout = isWideScreen(context);
|
||||||
final useExpandableLayout = isWidestScreen(context);
|
|
||||||
final currentRoute = ref.watch(currentRouteProvider);
|
final currentRoute = ref.watch(currentRouteProvider);
|
||||||
|
|
||||||
final notificationUnreadCount = ref.watch(
|
final notificationUnreadCount = ref.watch(
|
||||||
@@ -80,6 +85,7 @@ class TabsNavigationWidget extends HookConsumerWidget {
|
|||||||
];
|
];
|
||||||
final routeNames = [
|
final routeNames = [
|
||||||
ExploreRoute.name,
|
ExploreRoute.name,
|
||||||
|
ExploreShellRoute.name,
|
||||||
ChatListRoute.name,
|
ChatListRoute.name,
|
||||||
RealmListRoute.name,
|
RealmListRoute.name,
|
||||||
AccountRoute.name,
|
AccountRoute.name,
|
||||||
@@ -110,8 +116,6 @@ class TabsNavigationWidget extends HookConsumerWidget {
|
|||||||
Gap(MediaQuery.of(context).padding.top + 8),
|
Gap(MediaQuery.of(context).padding.top + 8),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: NavigationRail(
|
child: NavigationRail(
|
||||||
minExtendedWidth: 200,
|
|
||||||
extended: useExpandableLayout,
|
|
||||||
selectedIndex: activeIndex,
|
selectedIndex: activeIndex,
|
||||||
onDestinationSelected: (index) {
|
onDestinationSelected: (index) {
|
||||||
router.replace(routes[index]);
|
router.replace(routes[index]);
|
||||||
|
|||||||
297
lib/screens/chat/call.dart
Normal file
297
lib/screens/chat/call.dart
Normal file
@@ -0,0 +1,297 @@
|
|||||||
|
import 'package:auto_route/annotations.dart';
|
||||||
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
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/pods/call.dart';
|
||||||
|
import 'package:island/services/responsive.dart';
|
||||||
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/chat/call_button.dart';
|
||||||
|
import 'package:island/widgets/chat/call_overlay.dart';
|
||||||
|
import 'package:island/widgets/chat/call_participant_tile.dart';
|
||||||
|
import 'package:livekit_client/livekit_client.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
|
@RoutePage()
|
||||||
|
class CallScreen extends HookConsumerWidget {
|
||||||
|
final String roomId;
|
||||||
|
const CallScreen({super.key, @PathParam('id') required this.roomId});
|
||||||
|
|
||||||
|
@override
|
||||||
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final ongoingCall = ref.watch(ongoingCallProvider(roomId));
|
||||||
|
final callState = ref.watch(callNotifierProvider);
|
||||||
|
final callNotifier = ref.read(callNotifierProvider.notifier);
|
||||||
|
|
||||||
|
useEffect(() {
|
||||||
|
callNotifier.joinRoom(roomId);
|
||||||
|
return null;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
final viewMode = useState<String>('grid');
|
||||||
|
|
||||||
|
return AppScaffold(
|
||||||
|
appBar: AppBar(
|
||||||
|
leading: PageBackButton(
|
||||||
|
onWillPop: () {
|
||||||
|
showDialog<void>(
|
||||||
|
context: context,
|
||||||
|
builder: (context) {
|
||||||
|
return AlertDialog(
|
||||||
|
content: const Text(
|
||||||
|
'Do you want to leave the call or leave it in background?',
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
},
|
||||||
|
child: const Text('In Background'),
|
||||||
|
),
|
||||||
|
TextButton(
|
||||||
|
onPressed: () async {
|
||||||
|
Navigator.of(context).pop();
|
||||||
|
await callNotifier.disconnect();
|
||||||
|
callNotifier.dispose();
|
||||||
|
},
|
||||||
|
child: const Text('Leave'),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
title: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
ongoingCall.value?.room.name ?? 'call'.tr(),
|
||||||
|
style: const TextStyle(fontSize: 16),
|
||||||
|
),
|
||||||
|
Text(
|
||||||
|
callState.isConnected
|
||||||
|
? formatDuration(callState.duration)
|
||||||
|
: 'Connecting',
|
||||||
|
style: const TextStyle(fontSize: 14),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.end,
|
||||||
|
children: [
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.grid_view),
|
||||||
|
tooltip: 'Grid View',
|
||||||
|
onPressed: () => viewMode.value = 'grid',
|
||||||
|
color:
|
||||||
|
viewMode.value == 'grid'
|
||||||
|
? Theme.of(context).colorScheme.primary
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: Icon(Icons.view_agenda),
|
||||||
|
tooltip: 'Stage View',
|
||||||
|
onPressed: () => viewMode.value = 'stage',
|
||||||
|
color:
|
||||||
|
viewMode.value == 'stage'
|
||||||
|
? Theme.of(context).colorScheme.primary
|
||||||
|
: null,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
body:
|
||||||
|
callState.error != null
|
||||||
|
? Center(
|
||||||
|
child: Text(
|
||||||
|
callState.error!,
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: const TextStyle(color: Colors.red),
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Builder(
|
||||||
|
builder: (context) {
|
||||||
|
if (!callState.isConnected) {
|
||||||
|
return const Center(
|
||||||
|
child: CircularProgressIndicator(),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (callNotifier.participants.isEmpty) {
|
||||||
|
return const Center(
|
||||||
|
child: Text('No participants in call'),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final participants = callNotifier.participants;
|
||||||
|
final allAudioOnly = participants.every(
|
||||||
|
(p) =>
|
||||||
|
!(p.hasVideo &&
|
||||||
|
p.remoteParticipant.trackPublications.values
|
||||||
|
.any(
|
||||||
|
(pub) =>
|
||||||
|
pub.track != null &&
|
||||||
|
pub.kind == TrackType.VIDEO,
|
||||||
|
)),
|
||||||
|
);
|
||||||
|
if (allAudioOnly) {
|
||||||
|
// Audio-only: show avatars in a compact row
|
||||||
|
return Center(
|
||||||
|
child: SingleChildScrollView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
child: Wrap(
|
||||||
|
crossAxisAlignment: WrapCrossAlignment.center,
|
||||||
|
alignment: WrapAlignment.center,
|
||||||
|
spacing: 8,
|
||||||
|
runSpacing: 8,
|
||||||
|
children: [
|
||||||
|
for (final live in participants)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
|
child: SpeakingRippleAvatar(
|
||||||
|
isSpeaking: live.isSpeaking,
|
||||||
|
audioLevel:
|
||||||
|
live.remoteParticipant.audioLevel,
|
||||||
|
pictureId:
|
||||||
|
live
|
||||||
|
.participant
|
||||||
|
.profile
|
||||||
|
?.account
|
||||||
|
.profile
|
||||||
|
.picture
|
||||||
|
?.id,
|
||||||
|
size: 72,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
if (viewMode.value == 'stage') {
|
||||||
|
// Stage view: show main speaker(s) large, others in row
|
||||||
|
final mainSpeakers =
|
||||||
|
participants
|
||||||
|
.where(
|
||||||
|
(p) => p
|
||||||
|
.remoteParticipant
|
||||||
|
.trackPublications
|
||||||
|
.values
|
||||||
|
.any(
|
||||||
|
(pub) =>
|
||||||
|
pub.track != null &&
|
||||||
|
pub.kind == TrackType.VIDEO,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
if (mainSpeakers.isEmpty && participants.isNotEmpty) {
|
||||||
|
mainSpeakers.add(participants.first);
|
||||||
|
}
|
||||||
|
final others =
|
||||||
|
participants
|
||||||
|
.where((p) => !mainSpeakers.contains(p))
|
||||||
|
.toList();
|
||||||
|
return Column(
|
||||||
|
children: [
|
||||||
|
Expanded(
|
||||||
|
child: Row(
|
||||||
|
mainAxisAlignment: MainAxisAlignment.center,
|
||||||
|
children: [
|
||||||
|
for (final speaker in mainSpeakers)
|
||||||
|
Expanded(
|
||||||
|
child:
|
||||||
|
AspectRatio(
|
||||||
|
aspectRatio: 16 / 9,
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius:
|
||||||
|
BorderRadius.circular(8),
|
||||||
|
child: Column(
|
||||||
|
children: [
|
||||||
|
CallParticipantTile(
|
||||||
|
live: speaker,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).center(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 12),
|
||||||
|
),
|
||||||
|
if (others.isNotEmpty)
|
||||||
|
SizedBox(
|
||||||
|
height: 100,
|
||||||
|
child: ListView(
|
||||||
|
scrollDirection: Axis.horizontal,
|
||||||
|
children: [
|
||||||
|
for (final other in others)
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 8,
|
||||||
|
),
|
||||||
|
child: CallParticipantTile(
|
||||||
|
live: other,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
// Default: grid view
|
||||||
|
return GridView.builder(
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 12,
|
||||||
|
vertical: 8,
|
||||||
|
),
|
||||||
|
gridDelegate:
|
||||||
|
SliverGridDelegateWithFixedCrossAxisCount(
|
||||||
|
crossAxisCount:
|
||||||
|
isWidestScreen(context)
|
||||||
|
? 4
|
||||||
|
: isWiderScreen(context)
|
||||||
|
? 3
|
||||||
|
: 2,
|
||||||
|
childAspectRatio: 16 / 9,
|
||||||
|
crossAxisSpacing: 8,
|
||||||
|
mainAxisSpacing: 8,
|
||||||
|
),
|
||||||
|
itemCount: participants.length,
|
||||||
|
itemBuilder: (context, idx) {
|
||||||
|
final live = participants[idx];
|
||||||
|
return AspectRatio(
|
||||||
|
aspectRatio: 16 / 9,
|
||||||
|
child: Card(
|
||||||
|
margin: EdgeInsets.zero,
|
||||||
|
child: ClipRRect(
|
||||||
|
borderRadius: BorderRadius.circular(8),
|
||||||
|
child: Column(
|
||||||
|
children: [CallParticipantTile(live: live)],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
).center();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
CallControlsBar(),
|
||||||
|
Gap(MediaQuery.of(context).padding.bottom + 16),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,6 +11,7 @@ import 'package:image_picker/image_picker.dart';
|
|||||||
import 'package:island/models/chat.dart';
|
import 'package:island/models/chat.dart';
|
||||||
import 'package:island/models/file.dart';
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/models/realm.dart';
|
import 'package:island/models/realm.dart';
|
||||||
|
import 'package:island/pods/call.dart';
|
||||||
import 'package:island/pods/chat_summary.dart';
|
import 'package:island/pods/chat_summary.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
@@ -21,7 +22,9 @@ import 'package:island/services/responsive.dart';
|
|||||||
import 'package:island/widgets/account/account_picker.dart';
|
import 'package:island/widgets/account/account_picker.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/chat/call_overlay.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
import 'package:island/widgets/realms/selection_dropdown.dart';
|
import 'package:island/widgets/realms/selection_dropdown.dart';
|
||||||
import 'package:island/widgets/response.dart';
|
import 'package:island/widgets/response.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
@@ -107,7 +110,7 @@ class ChatRoomListTile extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
loading: () => const SizedBox.shrink(),
|
loading: () => const SizedBox.shrink(),
|
||||||
error:
|
error:
|
||||||
(_, __) =>
|
(_, _) =>
|
||||||
isDirect && room.description == null
|
isDirect && room.description == null
|
||||||
? Text(
|
? Text(
|
||||||
room.members!.map((e) => '@${e.account.name}').join(', '),
|
room.members!.map((e) => '@${e.account.name}').join(', '),
|
||||||
@@ -125,19 +128,19 @@ class ChatRoomListTile extends HookConsumerWidget {
|
|||||||
isLabelVisible: summary.when(
|
isLabelVisible: summary.when(
|
||||||
data: (data) => (data?.unreadCount ?? 0) > 0,
|
data: (data) => (data?.unreadCount ?? 0) > 0,
|
||||||
loading: () => false,
|
loading: () => false,
|
||||||
error: (_, __) => false,
|
error: (_, _) => false,
|
||||||
),
|
),
|
||||||
child:
|
child:
|
||||||
(isDirect && room.pictureId == null)
|
(isDirect && room.picture?.id == null)
|
||||||
? SplitAvatarWidget(
|
? SplitAvatarWidget(
|
||||||
filesId:
|
filesId:
|
||||||
room.members!
|
room.members!
|
||||||
.map((e) => e.account.profile.pictureId)
|
.map((e) => e.account.profile.picture?.id)
|
||||||
.toList(),
|
.toList(),
|
||||||
)
|
)
|
||||||
: room.pictureId == null
|
: room.picture?.id == null
|
||||||
? CircleAvatar(child: Text(room.name![0].toUpperCase()))
|
? CircleAvatar(child: Text(room.name![0].toUpperCase()))
|
||||||
: ProfilePictureWidget(fileId: room.pictureId),
|
: ProfilePictureWidget(fileId: room.picture?.id),
|
||||||
),
|
),
|
||||||
title: Text(
|
title: Text(
|
||||||
(isDirect && room.name == null)
|
(isDirect && room.name == null)
|
||||||
@@ -145,14 +148,14 @@ class ChatRoomListTile extends HookConsumerWidget {
|
|||||||
: room.name ?? '',
|
: room.name ?? '',
|
||||||
),
|
),
|
||||||
subtitle: buildSubtitle(),
|
subtitle: buildSubtitle(),
|
||||||
|
trailing: trailing, // Add this line
|
||||||
onTap: () async {
|
onTap: () async {
|
||||||
// Clear unread count if there are unread messages
|
// Clear unread count if there are unread messages
|
||||||
final summary = await ref.read(chatSummaryProvider.future);
|
ref.read(chatSummaryProvider.future).then((summary) {
|
||||||
if ((summary[room.id]?.unreadCount ?? 0) > 0) {
|
if ((summary[room.id]?.unreadCount ?? 0) > 0) {
|
||||||
await ref
|
ref.read(chatSummaryProvider.notifier).clearUnreadCount(room.id);
|
||||||
.read(chatSummaryProvider.notifier)
|
}
|
||||||
.clearUnreadCount(room.id);
|
});
|
||||||
}
|
|
||||||
onTap?.call();
|
onTap?.call();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
@@ -213,6 +216,8 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
0,
|
0,
|
||||||
); // 0 for All, 1 for Direct Messages, 2 for Group Chats
|
); // 0 for All, 1 for Direct Messages, 2 for Group Chats
|
||||||
|
|
||||||
|
final callState = ref.watch(callNotifierProvider);
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
tabController.addListener(() {
|
tabController.addListener(() {
|
||||||
selectedTab.value = tabController.index;
|
selectedTab.value = tabController.index;
|
||||||
@@ -241,9 +246,33 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
bottom: TabBar(
|
bottom: TabBar(
|
||||||
controller: tabController,
|
controller: tabController,
|
||||||
tabs: [
|
tabs: [
|
||||||
Tab(text: 'chatTabAll'.tr()),
|
Tab(
|
||||||
Tab(text: 'chatTabDirect'.tr()),
|
child: Text(
|
||||||
Tab(text: 'chatTabGroup'.tr()),
|
'chatTabAll'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'chatTabDirect'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
Tab(
|
||||||
|
child: Text(
|
||||||
|
'chatTabGroup'.tr(),
|
||||||
|
textAlign: TextAlign.center,
|
||||||
|
style: TextStyle(
|
||||||
|
color: Theme.of(context).appBarTheme.foregroundColor!,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
@@ -252,13 +281,13 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
label: Text(
|
label: Text(
|
||||||
chatInvites.when(
|
chatInvites.when(
|
||||||
data: (invites) => invites.length.toString(),
|
data: (invites) => invites.length.toString(),
|
||||||
error: (_, __) => '0',
|
error: (_, _) => '0',
|
||||||
loading: () => '0',
|
loading: () => '0',
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
isLabelVisible: chatInvites.when(
|
isLabelVisible: chatInvites.when(
|
||||||
data: (invites) => invites.isNotEmpty,
|
data: (invites) => invites.isNotEmpty,
|
||||||
error: (_, __) => false,
|
error: (_, _) => false,
|
||||||
loading: () => false,
|
loading: () => false,
|
||||||
),
|
),
|
||||||
child: const Icon(Symbols.email),
|
child: const Icon(Symbols.email),
|
||||||
@@ -310,57 +339,99 @@ class ChatListScreen extends HookConsumerWidget {
|
|||||||
},
|
},
|
||||||
child: const Icon(Symbols.add),
|
child: const Icon(Symbols.add),
|
||||||
),
|
),
|
||||||
body: chats.when(
|
body: Stack(
|
||||||
data:
|
children: [
|
||||||
(items) => RefreshIndicator(
|
Column(
|
||||||
onRefresh:
|
children: [
|
||||||
() => Future.sync(() {
|
Consumer(
|
||||||
ref.invalidate(chatroomsJoinedProvider);
|
builder: (context, ref, _) {
|
||||||
}),
|
final summaryState = ref.watch(chatSummaryProvider);
|
||||||
child: ListView.builder(
|
return summaryState.maybeWhen(
|
||||||
padding: EdgeInsets.zero,
|
loading:
|
||||||
itemCount:
|
() => const LinearProgressIndicator(
|
||||||
items
|
minHeight: 2,
|
||||||
.where(
|
borderRadius: BorderRadius.zero,
|
||||||
(item) =>
|
),
|
||||||
selectedTab.value == 0 ||
|
orElse: () => const SizedBox.shrink(),
|
||||||
(selectedTab.value == 1 && item.type == 1) ||
|
|
||||||
(selectedTab.value == 2 && item.type != 1),
|
|
||||||
)
|
|
||||||
.length,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final filteredItems =
|
|
||||||
items
|
|
||||||
.where(
|
|
||||||
(item) =>
|
|
||||||
selectedTab.value == 0 ||
|
|
||||||
(selectedTab.value == 1 && item.type == 1) ||
|
|
||||||
(selectedTab.value == 2 && item.type != 1),
|
|
||||||
)
|
|
||||||
.toList();
|
|
||||||
final item = filteredItems[index];
|
|
||||||
return ChatRoomListTile(
|
|
||||||
room: item,
|
|
||||||
isDirect: item.type == 1,
|
|
||||||
onTap: () {
|
|
||||||
if (context.router.topRoute.name == ChatRoomRoute.name) {
|
|
||||||
context.router.replace(ChatRoomRoute(id: item.id));
|
|
||||||
} else {
|
|
||||||
context.router.push(ChatRoomRoute(id: item.id));
|
|
||||||
}
|
|
||||||
},
|
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
),
|
Expanded(
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
child: chats.when(
|
||||||
error:
|
data:
|
||||||
(error, stack) => ResponseErrorWidget(
|
(items) => RefreshIndicator(
|
||||||
error: error,
|
onRefresh:
|
||||||
onRetry: () {
|
() => Future.sync(() {
|
||||||
ref.invalidate(chatroomsJoinedProvider);
|
ref.invalidate(chatroomsJoinedProvider);
|
||||||
},
|
}),
|
||||||
),
|
child: ListView.builder(
|
||||||
|
padding:
|
||||||
|
callState.isConnected
|
||||||
|
? EdgeInsets.only(bottom: 96)
|
||||||
|
: EdgeInsets.zero,
|
||||||
|
itemCount:
|
||||||
|
items
|
||||||
|
.where(
|
||||||
|
(item) =>
|
||||||
|
selectedTab.value == 0 ||
|
||||||
|
(selectedTab.value == 1 &&
|
||||||
|
item.type == 1) ||
|
||||||
|
(selectedTab.value == 2 &&
|
||||||
|
item.type != 1),
|
||||||
|
)
|
||||||
|
.length,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
final filteredItems =
|
||||||
|
items
|
||||||
|
.where(
|
||||||
|
(item) =>
|
||||||
|
selectedTab.value == 0 ||
|
||||||
|
(selectedTab.value == 1 &&
|
||||||
|
item.type == 1) ||
|
||||||
|
(selectedTab.value == 2 &&
|
||||||
|
item.type != 1),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
final item = filteredItems[index];
|
||||||
|
return ChatRoomListTile(
|
||||||
|
room: item,
|
||||||
|
isDirect: item.type == 1,
|
||||||
|
onTap: () {
|
||||||
|
if (context.router.topRoute.name ==
|
||||||
|
ChatRoomRoute.name) {
|
||||||
|
context.router.replace(
|
||||||
|
ChatRoomRoute(id: item.id),
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
context.router.push(
|
||||||
|
ChatRoomRoute(id: item.id),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
loading:
|
||||||
|
() => const Center(child: CircularProgressIndicator()),
|
||||||
|
error:
|
||||||
|
(error, stack) => ResponseErrorWidget(
|
||||||
|
error: error,
|
||||||
|
onRetry: () {
|
||||||
|
ref.invalidate(chatroomsJoinedProvider);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
child: const CallOverlayBar().padding(horizontal: 16, vertical: 12),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -457,19 +528,15 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
final baseUrl = ref.watch(serverUrlProvider);
|
||||||
final atk = await getFreshAtk(
|
final token = await getToken(ref.watch(tokenProvider));
|
||||||
ref.watch(tokenPairProvider),
|
if (token == null) throw ArgumentError('Token is null');
|
||||||
baseUrl,
|
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (atk == null) throw ArgumentError('Access token is null');
|
|
||||||
final cloudFile =
|
final cloudFile =
|
||||||
await putMediaToCloud(
|
await putMediaToCloud(
|
||||||
fileData: result,
|
fileData: UniversalFile(
|
||||||
atk: atk,
|
data: result,
|
||||||
|
type: UniversalFileType.image,
|
||||||
|
),
|
||||||
|
atk: token,
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
filename: result.name,
|
filename: result.name,
|
||||||
mimetype: result.mimeType ?? 'image/jpeg',
|
mimetype: result.mimeType ?? 'image/jpeg',
|
||||||
@@ -530,7 +597,7 @@ class EditChatScreen extends HookConsumerWidget {
|
|||||||
realms: joinedRealms.when(
|
realms: joinedRealms.when(
|
||||||
data: (realms) => realms,
|
data: (realms) => realms,
|
||||||
loading: () => [],
|
loading: () => [],
|
||||||
error: (_, __) => [],
|
error: (_, _) => [],
|
||||||
),
|
),
|
||||||
onChanged: (SnRealm? value) {
|
onChanged: (SnRealm? value) {
|
||||||
currentRealm.value = value;
|
currentRealm.value = value;
|
||||||
@@ -652,109 +719,77 @@ class _ChatInvitesSheet extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return Container(
|
return SheetScaffold(
|
||||||
constraints: BoxConstraints(
|
titleText: 'invites'.tr(),
|
||||||
maxHeight: MediaQuery.of(context).size.height * 0.8,
|
actions: [
|
||||||
),
|
IconButton(
|
||||||
child: Column(
|
icon: const Icon(Symbols.refresh),
|
||||||
mainAxisSize: MainAxisSize.min,
|
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
||||||
children: [
|
onPressed: () {
|
||||||
Padding(
|
ref.invalidate(realmInvitesProvider);
|
||||||
padding: EdgeInsets.only(top: 16, left: 20, right: 16, bottom: 12),
|
},
|
||||||
child: Row(
|
),
|
||||||
children: [
|
],
|
||||||
Text(
|
child: invites.when(
|
||||||
'invites'.tr(),
|
data:
|
||||||
style: Theme.of(context).textTheme.headlineSmall?.copyWith(
|
(items) =>
|
||||||
fontWeight: FontWeight.w600,
|
items.isEmpty
|
||||||
letterSpacing: -0.5,
|
? Center(
|
||||||
),
|
child:
|
||||||
),
|
Text(
|
||||||
const Spacer(),
|
'invitesEmpty',
|
||||||
IconButton(
|
textAlign: TextAlign.center,
|
||||||
icon: const Icon(Symbols.refresh),
|
).tr(),
|
||||||
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
)
|
||||||
onPressed: () {
|
: ListView.builder(
|
||||||
ref.invalidate(chatroomInvitesProvider);
|
shrinkWrap: true,
|
||||||
},
|
itemCount: items.length,
|
||||||
),
|
itemBuilder: (context, index) {
|
||||||
IconButton(
|
final invite = items[index];
|
||||||
icon: const Icon(Symbols.close),
|
return ChatRoomListTile(
|
||||||
onPressed: () => Navigator.pop(context),
|
room: invite.chatRoom!,
|
||||||
style: IconButton.styleFrom(minimumSize: const Size(36, 36)),
|
isDirect: invite.chatRoom!.type == 1,
|
||||||
),
|
subtitle: Row(
|
||||||
],
|
spacing: 6,
|
||||||
),
|
children: [
|
||||||
),
|
Flexible(
|
||||||
const Divider(height: 1),
|
child:
|
||||||
Expanded(
|
Text(
|
||||||
child: invites.when(
|
invite.role >= 100
|
||||||
data:
|
? 'permissionOwner'
|
||||||
(items) =>
|
: invite.role >= 50
|
||||||
items.isEmpty
|
? 'permissionModerator'
|
||||||
? Center(
|
: 'permissionMember',
|
||||||
child:
|
).tr(),
|
||||||
Text(
|
),
|
||||||
'invitesEmpty',
|
if (invite.chatRoom!.type == 1)
|
||||||
textAlign: TextAlign.center,
|
Badge(
|
||||||
).tr(),
|
label: Text('directMessage').tr(),
|
||||||
)
|
backgroundColor:
|
||||||
: ListView.builder(
|
Theme.of(context).colorScheme.primary,
|
||||||
shrinkWrap: true,
|
textColor:
|
||||||
itemCount: items.length,
|
Theme.of(context).colorScheme.onPrimary,
|
||||||
itemBuilder: (context, index) {
|
|
||||||
final invite = items[index];
|
|
||||||
return ChatRoomListTile(
|
|
||||||
room: invite.chatRoom!,
|
|
||||||
isDirect: invite.chatRoom!.type == 1,
|
|
||||||
subtitle: Row(
|
|
||||||
spacing: 6,
|
|
||||||
children: [
|
|
||||||
Flexible(
|
|
||||||
child:
|
|
||||||
Text(
|
|
||||||
invite.role >= 100
|
|
||||||
? 'permissionOwner'
|
|
||||||
: invite.role >= 50
|
|
||||||
? 'permissionModerator'
|
|
||||||
: 'permissionMember',
|
|
||||||
).tr(),
|
|
||||||
),
|
|
||||||
if (invite.chatRoom!.type == 1)
|
|
||||||
Badge(
|
|
||||||
label: Text('directMessage').tr(),
|
|
||||||
backgroundColor:
|
|
||||||
Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.primary,
|
|
||||||
textColor:
|
|
||||||
Theme.of(
|
|
||||||
context,
|
|
||||||
).colorScheme.onPrimary,
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
trailing: Row(
|
],
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.check),
|
|
||||||
onPressed: () => acceptInvite(invite),
|
|
||||||
),
|
|
||||||
IconButton(
|
|
||||||
icon: const Icon(Symbols.close),
|
|
||||||
onPressed: () => declineInvite(invite),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
trailing: Row(
|
||||||
error: (error, stack) => Center(child: Text('Error: $error')),
|
mainAxisSize: MainAxisSize.min,
|
||||||
),
|
children: [
|
||||||
),
|
IconButton(
|
||||||
],
|
icon: const Icon(Symbols.check),
|
||||||
|
onPressed: () => acceptInvite(invite),
|
||||||
|
),
|
||||||
|
IconButton(
|
||||||
|
icon: const Icon(Symbols.close),
|
||||||
|
onPressed: () => declineInvite(invite),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
|
error: (error, stack) => Center(child: Text('Error: $error')),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ import 'dart:convert';
|
|||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
@@ -18,21 +19,23 @@ import 'package:island/pods/database.dart';
|
|||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
import 'package:island/pods/websocket.dart';
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/route.gr.dart';
|
import 'package:island/route.gr.dart';
|
||||||
import 'package:island/screens/posts/compose.dart';
|
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
|
import 'package:island/widgets/chat/call_overlay.dart';
|
||||||
import 'package:island/widgets/chat/message_item.dart';
|
import 'package:island/widgets/chat/message_item.dart';
|
||||||
|
import 'package:island/widgets/content/attachment_preview.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/response.dart';
|
import 'package:island/widgets/response.dart';
|
||||||
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
import 'package:material_symbols_icons/material_symbols_icons.dart';
|
||||||
|
import 'package:pasteboard/pasteboard.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:super_sliver_list/super_sliver_list.dart';
|
import 'package:super_sliver_list/super_sliver_list.dart';
|
||||||
import 'package:uuid/uuid.dart';
|
import 'package:uuid/uuid.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:super_clipboard/super_clipboard.dart';
|
|
||||||
import 'chat.dart';
|
import 'chat.dart';
|
||||||
|
import 'package:island/widgets/chat/call_button.dart';
|
||||||
|
|
||||||
part 'room.g.dart';
|
part 'room.g.dart';
|
||||||
|
|
||||||
@@ -115,19 +118,12 @@ class MessagesNotifier extends _$MessagesNotifier {
|
|||||||
messageRepositoryProvider(_roomId).future,
|
messageRepositoryProvider(_roomId).future,
|
||||||
);
|
);
|
||||||
final baseUrl = ref.read(serverUrlProvider);
|
final baseUrl = ref.read(serverUrlProvider);
|
||||||
final atk = await getFreshAtk(
|
final token = await getToken(ref.watch(tokenProvider));
|
||||||
ref.watch(tokenPairProvider),
|
if (token == null) throw ArgumentError('Access token is null');
|
||||||
baseUrl,
|
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (atk == null) throw ArgumentError('Access token is null');
|
|
||||||
|
|
||||||
final currentMessages = state.value ?? [];
|
final currentMessages = state.value ?? [];
|
||||||
await repository.sendMessage(
|
await repository.sendMessage(
|
||||||
atk,
|
token,
|
||||||
baseUrl,
|
baseUrl,
|
||||||
_roomId,
|
_roomId,
|
||||||
content,
|
content,
|
||||||
@@ -325,6 +321,46 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Members who are typing
|
||||||
|
final typingStatuses = useState<List<SnChatMember>>([]);
|
||||||
|
final typingDebouncer = useState<Timer?>(null);
|
||||||
|
|
||||||
|
void sendTypingStatus() {
|
||||||
|
// Don't send if we're already in a cooldown period
|
||||||
|
if (typingDebouncer.value != null) return;
|
||||||
|
|
||||||
|
// Send typing status immediately
|
||||||
|
final wsState = ref.read(websocketStateProvider.notifier);
|
||||||
|
wsState.sendMessage(
|
||||||
|
jsonEncode(
|
||||||
|
WebSocketPacket(type: 'messages.typing', data: {'chat_room_id': id}),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
|
||||||
|
typingDebouncer.value = Timer(const Duration(milliseconds: 850), () {
|
||||||
|
typingDebouncer.value = null;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add timer to remove typing status after inactivity
|
||||||
|
useEffect(() {
|
||||||
|
final removeTypingTimer = Timer.periodic(const Duration(seconds: 5), (_) {
|
||||||
|
if (typingStatuses.value.isNotEmpty) {
|
||||||
|
// Remove typing statuses older than 5 seconds
|
||||||
|
final now = DateTime.now();
|
||||||
|
typingStatuses.value =
|
||||||
|
typingStatuses.value.where((member) {
|
||||||
|
final lastTyped =
|
||||||
|
member.lastTyped ??
|
||||||
|
DateTime.now().subtract(const Duration(milliseconds: 1350));
|
||||||
|
return now.difference(lastTyped).inSeconds < 5;
|
||||||
|
}).toList();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return () => removeTypingTimer.cancel();
|
||||||
|
}, []);
|
||||||
|
|
||||||
var isLoading = false;
|
var isLoading = false;
|
||||||
|
|
||||||
// Add scroll listener for pagination
|
// Add scroll listener for pagination
|
||||||
@@ -347,10 +383,38 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
void onMessage(WebSocketPacket pkt) {
|
void onMessage(WebSocketPacket pkt) {
|
||||||
if (!pkt.type.startsWith('messages')) return;
|
if (!pkt.type.startsWith('messages')) return;
|
||||||
if (['messages.read'].contains(pkt.type)) return;
|
if (['messages.read'].contains(pkt.type)) return;
|
||||||
|
|
||||||
|
if (pkt.type == 'messages.typing' && pkt.data?['sender'] != null) {
|
||||||
|
if (pkt.data?['sender_id'] == chatIdentity.value?.id) return;
|
||||||
|
|
||||||
|
final sender = SnChatMember.fromJson(
|
||||||
|
pkt.data?['sender'],
|
||||||
|
).copyWith(lastTyped: DateTime.now());
|
||||||
|
|
||||||
|
// Check if the sender is already in the typing list
|
||||||
|
final existingIndex = typingStatuses.value.indexWhere(
|
||||||
|
(member) => member.id == sender.id,
|
||||||
|
);
|
||||||
|
if (existingIndex >= 0) {
|
||||||
|
// Update the existing entry with new timestamp
|
||||||
|
final updatedList = [...typingStatuses.value];
|
||||||
|
updatedList[existingIndex] = sender;
|
||||||
|
typingStatuses.value = updatedList;
|
||||||
|
} else {
|
||||||
|
// Add new typing status
|
||||||
|
typingStatuses.value = [...typingStatuses.value, sender];
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
final message = SnChatMessage.fromJson(pkt.data!);
|
final message = SnChatMessage.fromJson(pkt.data!);
|
||||||
if (message.chatRoomId != chatRoom.value?.id) return;
|
if (message.chatRoomId != chatRoom.value?.id) return;
|
||||||
switch (pkt.type) {
|
switch (pkt.type) {
|
||||||
case 'messages.new':
|
case 'messages.new':
|
||||||
|
if (message.type.startsWith('call')) {
|
||||||
|
// Handle the ongoing call.
|
||||||
|
ref.invalidate(ongoingCallProvider(message.chatRoomId));
|
||||||
|
}
|
||||||
messagesNotifier.receiveMessage(message);
|
messagesNotifier.receiveMessage(message);
|
||||||
// Send read receipt for new message
|
// Send read receipt for new message
|
||||||
sendReadReceipt();
|
sendReadReceipt();
|
||||||
@@ -416,8 +480,22 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Add listener to message controller for typing status
|
||||||
|
useEffect(() {
|
||||||
|
void onTextChange() {
|
||||||
|
if (messageController.text.isNotEmpty) {
|
||||||
|
sendTypingStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
messageController.addListener(onTextChange);
|
||||||
|
return () => messageController.removeListener(onTextChange);
|
||||||
|
}, [messageController]);
|
||||||
|
|
||||||
final compactHeader = isWideScreen(context);
|
final compactHeader = isWideScreen(context);
|
||||||
|
|
||||||
|
final listController = useMemoized(() => ListController(), []);
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: !compactHeader ? const Center(child: PageBackButton()) : null,
|
leading: !compactHeader ? const Center(child: PageBackButton()) : null,
|
||||||
@@ -435,19 +513,23 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
height: 26,
|
height: 26,
|
||||||
width: 26,
|
width: 26,
|
||||||
child:
|
child:
|
||||||
(room!.type == 1 && room.pictureId == null)
|
(room!.type == 1 && room.picture?.id == null)
|
||||||
? SplitAvatarWidget(
|
? SplitAvatarWidget(
|
||||||
filesId:
|
filesId:
|
||||||
room.members!
|
room.members!
|
||||||
.map(
|
.map(
|
||||||
(e) =>
|
(e) =>
|
||||||
e.account.profile.pictureId,
|
e
|
||||||
|
.account
|
||||||
|
.profile
|
||||||
|
.picture
|
||||||
|
?.id,
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
)
|
)
|
||||||
: room.pictureId != null
|
: room.picture?.id != null
|
||||||
? ProfilePictureWidget(
|
? ProfilePictureWidget(
|
||||||
fileId: room.pictureId,
|
fileId: room.picture?.id,
|
||||||
fallbackIcon: Symbols.chat,
|
fallbackIcon: Symbols.chat,
|
||||||
)
|
)
|
||||||
: CircleAvatar(
|
: CircleAvatar(
|
||||||
@@ -475,19 +557,23 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
height: 26,
|
height: 26,
|
||||||
width: 26,
|
width: 26,
|
||||||
child:
|
child:
|
||||||
(room!.type == 1 && room.pictureId == null)
|
(room!.type == 1 && room.picture?.id == null)
|
||||||
? SplitAvatarWidget(
|
? SplitAvatarWidget(
|
||||||
filesId:
|
filesId:
|
||||||
room.members!
|
room.members!
|
||||||
.map(
|
.map(
|
||||||
(e) =>
|
(e) =>
|
||||||
e.account.profile.pictureId,
|
e
|
||||||
|
.account
|
||||||
|
.profile
|
||||||
|
.picture
|
||||||
|
?.id,
|
||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
)
|
)
|
||||||
: room.pictureId != null
|
: room.picture?.id != null
|
||||||
? ProfilePictureWidget(
|
? ProfilePictureWidget(
|
||||||
fileId: room.pictureId,
|
fileId: room.picture?.id,
|
||||||
fallbackIcon: Symbols.chat,
|
fallbackIcon: Symbols.chat,
|
||||||
)
|
)
|
||||||
: CircleAvatar(
|
: CircleAvatar(
|
||||||
@@ -508,18 +594,13 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
loading: () => const Text('Loading...'),
|
loading: () => const Text('Loading...'),
|
||||||
error:
|
error:
|
||||||
(err, __) => ResponseErrorWidget(
|
(err, _) => ResponseErrorWidget(
|
||||||
error: err,
|
error: err,
|
||||||
onRetry: () => messagesNotifier.loadInitial(),
|
onRetry: () => messagesNotifier.loadInitial(),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
IconButton(
|
AudioCallButton(roomId: id),
|
||||||
icon: const Icon(Symbols.video_call),
|
|
||||||
onPressed: () {
|
|
||||||
showInfoAlert('Oops', 'Not implemented yet...');
|
|
||||||
},
|
|
||||||
),
|
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.more_vert),
|
icon: const Icon(Icons.more_vert),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
@@ -529,152 +610,265 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
const Gap(8),
|
const Gap(8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: Column(
|
body: Stack(
|
||||||
children: [
|
children: [
|
||||||
Expanded(
|
Column(
|
||||||
child: messages.when(
|
children: [
|
||||||
data:
|
Expanded(
|
||||||
(messageList) =>
|
child: messages.when(
|
||||||
messageList.isEmpty
|
data:
|
||||||
? Center(child: Text('No messages yet'.tr()))
|
(messageList) =>
|
||||||
: SuperListView.builder(
|
messageList.isEmpty
|
||||||
padding: EdgeInsets.symmetric(vertical: 16),
|
? Center(child: Text('No messages yet'.tr()))
|
||||||
controller: scrollController,
|
: SuperListView.builder(
|
||||||
reverse: true, // Show newest messages at the bottom
|
listController: listController,
|
||||||
itemCount: messageList.length,
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
itemBuilder: (context, index) {
|
controller: scrollController,
|
||||||
final message = messageList[index];
|
reverse:
|
||||||
final nextMessage =
|
true, // Show newest messages at the bottom
|
||||||
index < messageList.length - 1
|
itemCount: messageList.length,
|
||||||
? messageList[index + 1]
|
findChildIndexCallback: (key) {
|
||||||
: null;
|
final valueKey = key as ValueKey;
|
||||||
final isLastInGroup =
|
final messageId = valueKey.value as String;
|
||||||
nextMessage == null ||
|
return messageList.indexWhere(
|
||||||
nextMessage.senderId != message.senderId ||
|
(m) => m.id == messageId,
|
||||||
nextMessage.createdAt
|
);
|
||||||
.difference(message.createdAt)
|
},
|
||||||
.inMinutes
|
itemBuilder: (context, index) {
|
||||||
.abs() >
|
final message = messageList[index];
|
||||||
3;
|
final nextMessage =
|
||||||
|
index < messageList.length - 1
|
||||||
|
? messageList[index + 1]
|
||||||
|
: null;
|
||||||
|
final isLastInGroup =
|
||||||
|
nextMessage == null ||
|
||||||
|
nextMessage.senderId !=
|
||||||
|
message.senderId ||
|
||||||
|
nextMessage.createdAt
|
||||||
|
.difference(message.createdAt)
|
||||||
|
.inMinutes
|
||||||
|
.abs() >
|
||||||
|
3;
|
||||||
|
|
||||||
return chatIdentity.when(
|
return chatIdentity.when(
|
||||||
skipError: true,
|
skipError: true,
|
||||||
data:
|
data:
|
||||||
(identity) => MessageItem(
|
(identity) => MessageItem(
|
||||||
message: message,
|
message: message,
|
||||||
isCurrentUser:
|
isCurrentUser:
|
||||||
identity?.id == message.senderId,
|
identity?.id == message.senderId,
|
||||||
onAction: (action) {
|
onAction: (action) {
|
||||||
switch (action) {
|
switch (action) {
|
||||||
case MessageItemAction.delete:
|
case MessageItemAction.delete:
|
||||||
messagesNotifier.deleteMessage(
|
messagesNotifier.deleteMessage(
|
||||||
message.id,
|
message.id,
|
||||||
|
);
|
||||||
|
case MessageItemAction.edit:
|
||||||
|
messageEditingTo.value =
|
||||||
|
message.toRemoteMessage();
|
||||||
|
messageController.text =
|
||||||
|
messageEditingTo
|
||||||
|
.value
|
||||||
|
?.content ??
|
||||||
|
'';
|
||||||
|
attachments.value =
|
||||||
|
messageEditingTo
|
||||||
|
.value!
|
||||||
|
.attachments
|
||||||
|
.map(
|
||||||
|
(e) =>
|
||||||
|
UniversalFile.fromAttachment(
|
||||||
|
e,
|
||||||
|
),
|
||||||
|
)
|
||||||
|
.toList();
|
||||||
|
case MessageItemAction.forward:
|
||||||
|
messageForwardingTo.value =
|
||||||
|
message.toRemoteMessage();
|
||||||
|
case MessageItemAction.reply:
|
||||||
|
messageReplyingTo.value =
|
||||||
|
message.toRemoteMessage();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
onJump: (messageId) {
|
||||||
|
final messageIndex = messageList
|
||||||
|
.indexWhere(
|
||||||
|
(m) => m.id == messageId,
|
||||||
|
);
|
||||||
|
listController.jumpToItem(
|
||||||
|
index: messageIndex,
|
||||||
|
scrollController:
|
||||||
|
scrollController,
|
||||||
|
alignment: 0.5,
|
||||||
);
|
);
|
||||||
case MessageItemAction.edit:
|
},
|
||||||
messageEditingTo.value =
|
progress:
|
||||||
message.toRemoteMessage();
|
attachmentProgress.value[message
|
||||||
messageController.text =
|
.id],
|
||||||
messageEditingTo
|
showAvatar: isLastInGroup,
|
||||||
.value
|
),
|
||||||
?.content ??
|
loading:
|
||||||
'';
|
() => MessageItem(
|
||||||
attachments.value =
|
message: message,
|
||||||
messageEditingTo
|
isCurrentUser: false,
|
||||||
.value!
|
onAction: null,
|
||||||
.attachments
|
progress: null,
|
||||||
.map(
|
showAvatar: false,
|
||||||
(e) =>
|
onJump: (_) {},
|
||||||
UniversalFile.fromAttachment(
|
),
|
||||||
e,
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
),
|
);
|
||||||
)
|
},
|
||||||
.toList();
|
),
|
||||||
case MessageItemAction.forward:
|
loading:
|
||||||
messageForwardingTo.value =
|
() => const Center(child: CircularProgressIndicator()),
|
||||||
message.toRemoteMessage();
|
error:
|
||||||
case MessageItemAction.reply:
|
(error, _) => ResponseErrorWidget(
|
||||||
messageReplyingTo.value =
|
error: error,
|
||||||
message.toRemoteMessage();
|
onRetry: () => messagesNotifier.loadInitial(),
|
||||||
}
|
),
|
||||||
},
|
|
||||||
progress:
|
|
||||||
attachmentProgress.value[message.id],
|
|
||||||
showAvatar: isLastInGroup,
|
|
||||||
),
|
|
||||||
loading:
|
|
||||||
() => MessageItem(
|
|
||||||
message: message,
|
|
||||||
isCurrentUser: false,
|
|
||||||
onAction: null,
|
|
||||||
progress: null,
|
|
||||||
showAvatar: false,
|
|
||||||
),
|
|
||||||
error: (_, __) => const SizedBox.shrink(),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
|
||||||
error:
|
|
||||||
(error, _) => ResponseErrorWidget(
|
|
||||||
error: error,
|
|
||||||
onRetry: () => messagesNotifier.loadInitial(),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
chatRoom.when(
|
|
||||||
data:
|
|
||||||
(room) => _ChatInput(
|
|
||||||
messageController: messageController,
|
|
||||||
chatRoom: room!,
|
|
||||||
onSend: sendMessage,
|
|
||||||
onClear: () {
|
|
||||||
if (messageEditingTo.value != null) {
|
|
||||||
attachments.value.clear();
|
|
||||||
messageController.clear();
|
|
||||||
}
|
|
||||||
messageEditingTo.value = null;
|
|
||||||
messageReplyingTo.value = null;
|
|
||||||
messageForwardingTo.value = null;
|
|
||||||
},
|
|
||||||
messageEditingTo: messageEditingTo.value,
|
|
||||||
messageReplyingTo: messageReplyingTo.value,
|
|
||||||
messageForwardingTo: messageForwardingTo.value,
|
|
||||||
onPickFile: (bool isPhoto) {
|
|
||||||
if (isPhoto) {
|
|
||||||
pickPhotoMedia();
|
|
||||||
} else {
|
|
||||||
pickVideoMedia();
|
|
||||||
}
|
|
||||||
},
|
|
||||||
attachments: attachments.value,
|
|
||||||
onUploadAttachment: (_) {
|
|
||||||
// not going to do anything, only upload when send the message
|
|
||||||
},
|
|
||||||
onDeleteAttachment: (index) async {
|
|
||||||
final attachment = attachments.value[index];
|
|
||||||
if (attachment.isOnCloud) {
|
|
||||||
final client = ref.watch(apiClientProvider);
|
|
||||||
await client.delete('/files/${attachment.data.id}');
|
|
||||||
}
|
|
||||||
final clone = List.of(attachments.value);
|
|
||||||
clone.removeAt(index);
|
|
||||||
attachments.value = clone;
|
|
||||||
},
|
|
||||||
onMoveAttachment: (idx, delta) {
|
|
||||||
if (idx + delta < 0 ||
|
|
||||||
idx + delta >= attachments.value.length) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
final clone = List.of(attachments.value);
|
|
||||||
clone.insert(idx + delta, clone.removeAt(idx));
|
|
||||||
attachments.value = clone;
|
|
||||||
},
|
|
||||||
onAttachmentsChanged: (newAttachments) {
|
|
||||||
attachments.value = newAttachments;
|
|
||||||
},
|
|
||||||
),
|
),
|
||||||
error: (_, __) => const SizedBox.shrink(),
|
),
|
||||||
loading: () => const SizedBox.shrink(),
|
chatRoom.when(
|
||||||
|
data:
|
||||||
|
(room) => Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
AnimatedSwitcher(
|
||||||
|
duration: const Duration(milliseconds: 150),
|
||||||
|
switchInCurve: Curves.fastEaseInToSlowEaseOut,
|
||||||
|
switchOutCurve: Curves.fastEaseInToSlowEaseOut,
|
||||||
|
transitionBuilder: (
|
||||||
|
Widget child,
|
||||||
|
Animation<double> animation,
|
||||||
|
) {
|
||||||
|
return SlideTransition(
|
||||||
|
position: Tween<Offset>(
|
||||||
|
begin: const Offset(0, -0.3),
|
||||||
|
end: Offset.zero,
|
||||||
|
).animate(
|
||||||
|
CurvedAnimation(
|
||||||
|
parent: animation,
|
||||||
|
curve: Curves.easeOutCubic,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: SizeTransition(
|
||||||
|
sizeFactor: animation,
|
||||||
|
axisAlignment: -1.0,
|
||||||
|
child: FadeTransition(
|
||||||
|
opacity: animation,
|
||||||
|
child: child,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child:
|
||||||
|
typingStatuses.value.isNotEmpty
|
||||||
|
? Container(
|
||||||
|
key: const ValueKey('typing-indicator'),
|
||||||
|
width: double.infinity,
|
||||||
|
padding: const EdgeInsets.symmetric(
|
||||||
|
horizontal: 16,
|
||||||
|
vertical: 4,
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(
|
||||||
|
Symbols.more_horiz,
|
||||||
|
size: 16,
|
||||||
|
).padding(horizontal: 8),
|
||||||
|
const Gap(8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'typingHint'.plural(
|
||||||
|
typingStatuses.value.length,
|
||||||
|
args: [
|
||||||
|
typingStatuses.value
|
||||||
|
.map(
|
||||||
|
(x) =>
|
||||||
|
x.nick ??
|
||||||
|
x.account.nick,
|
||||||
|
)
|
||||||
|
.join(', '),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
style:
|
||||||
|
Theme.of(
|
||||||
|
context,
|
||||||
|
).textTheme.bodySmall,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
)
|
||||||
|
: const SizedBox.shrink(
|
||||||
|
key: ValueKey('typing-indicator-none'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
_ChatInput(
|
||||||
|
messageController: messageController,
|
||||||
|
chatRoom: room!,
|
||||||
|
onSend: sendMessage,
|
||||||
|
onClear: () {
|
||||||
|
if (messageEditingTo.value != null) {
|
||||||
|
attachments.value.clear();
|
||||||
|
messageController.clear();
|
||||||
|
}
|
||||||
|
messageEditingTo.value = null;
|
||||||
|
messageReplyingTo.value = null;
|
||||||
|
messageForwardingTo.value = null;
|
||||||
|
},
|
||||||
|
messageEditingTo: messageEditingTo.value,
|
||||||
|
messageReplyingTo: messageReplyingTo.value,
|
||||||
|
messageForwardingTo: messageForwardingTo.value,
|
||||||
|
onPickFile: (bool isPhoto) {
|
||||||
|
if (isPhoto) {
|
||||||
|
pickPhotoMedia();
|
||||||
|
} else {
|
||||||
|
pickVideoMedia();
|
||||||
|
}
|
||||||
|
},
|
||||||
|
attachments: attachments.value,
|
||||||
|
onUploadAttachment: (_) {
|
||||||
|
// not going to do anything, only upload when send the message
|
||||||
|
},
|
||||||
|
onDeleteAttachment: (index) async {
|
||||||
|
final attachment = attachments.value[index];
|
||||||
|
if (attachment.isOnCloud) {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
await client.delete(
|
||||||
|
'/files/${attachment.data.id}',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
final clone = List.of(attachments.value);
|
||||||
|
clone.removeAt(index);
|
||||||
|
attachments.value = clone;
|
||||||
|
},
|
||||||
|
onMoveAttachment: (idx, delta) {
|
||||||
|
if (idx + delta < 0 ||
|
||||||
|
idx + delta >= attachments.value.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final clone = List.of(attachments.value);
|
||||||
|
clone.insert(idx + delta, clone.removeAt(idx));
|
||||||
|
attachments.value = clone;
|
||||||
|
},
|
||||||
|
onAttachmentsChanged: (newAttachments) {
|
||||||
|
attachments.value = newAttachments;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
|
loading: () => const SizedBox.shrink(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
Positioned(
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
top: 0,
|
||||||
|
child: CallOverlayBar().padding(horizontal: 8, top: 12),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -682,7 +876,7 @@ class ChatRoomScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class _ChatInput extends ConsumerWidget {
|
class _ChatInput extends HookConsumerWidget {
|
||||||
final TextEditingController messageController;
|
final TextEditingController messageController;
|
||||||
final SnChatRoom chatRoom;
|
final SnChatRoom chatRoom;
|
||||||
final VoidCallback onSend;
|
final VoidCallback onSend;
|
||||||
@@ -713,62 +907,58 @@ class _ChatInput extends ConsumerWidget {
|
|||||||
required this.onAttachmentsChanged,
|
required this.onAttachmentsChanged,
|
||||||
});
|
});
|
||||||
|
|
||||||
void _handleKeyPress(BuildContext context, WidgetRef ref, RawKeyEvent event) {
|
|
||||||
if (event is! RawKeyDownEvent) return;
|
|
||||||
|
|
||||||
final isPaste = event.logicalKey == LogicalKeyboardKey.keyV;
|
|
||||||
final isModifierPressed = event.isMetaPressed || event.isControlPressed;
|
|
||||||
|
|
||||||
if (isPaste && isModifierPressed) {
|
|
||||||
_handlePaste();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
final enterToSend = ref.read(appSettingsProvider).enterToSend;
|
|
||||||
final isEnter = event.logicalKey == LogicalKeyboardKey.enter;
|
|
||||||
|
|
||||||
if (isEnter) {
|
|
||||||
if (enterToSend && !isModifierPressed) {
|
|
||||||
onSend();
|
|
||||||
} else if (!enterToSend && isModifierPressed) {
|
|
||||||
onSend();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> _handlePaste() async {
|
|
||||||
final clipboard = SystemClipboard.instance;
|
|
||||||
if (clipboard == null) return;
|
|
||||||
|
|
||||||
final reader = await clipboard.read();
|
|
||||||
if (reader.canProvide(Formats.png)) {
|
|
||||||
reader.getFile(Formats.png, (file) async {
|
|
||||||
final stream = file.getStream();
|
|
||||||
final bytes = await stream.toList();
|
|
||||||
final imageBytes = bytes.expand((e) => e).toList();
|
|
||||||
|
|
||||||
// Create a temporary file to store the image
|
|
||||||
final tempDir = Directory.systemTemp;
|
|
||||||
final tempFile = File(
|
|
||||||
'${tempDir.path}/pasted_image_${DateTime.now().millisecondsSinceEpoch}.png',
|
|
||||||
);
|
|
||||||
await tempFile.writeAsBytes(imageBytes);
|
|
||||||
|
|
||||||
// Add the file to attachments
|
|
||||||
onAttachmentsChanged([
|
|
||||||
...attachments,
|
|
||||||
UniversalFile(
|
|
||||||
data: XFile(tempFile.path),
|
|
||||||
type: UniversalFileType.image,
|
|
||||||
),
|
|
||||||
]);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final enterToSend = ref.watch(appSettingsProvider).enterToSend;
|
final inputFocusNode = useFocusNode();
|
||||||
|
|
||||||
|
final enterToSend = ref.watch(appSettingsNotifierProvider).enterToSend;
|
||||||
|
|
||||||
|
final isMobile = !kIsWeb && (Platform.isAndroid || Platform.isIOS);
|
||||||
|
|
||||||
|
void send() {
|
||||||
|
inputFocusNode.requestFocus();
|
||||||
|
onSend.call();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> handlePaste() async {
|
||||||
|
final clipboard = await Pasteboard.image;
|
||||||
|
if (clipboard == null) return;
|
||||||
|
|
||||||
|
onAttachmentsChanged([
|
||||||
|
...attachments,
|
||||||
|
UniversalFile(
|
||||||
|
data: XFile.fromData(clipboard, mimeType: "image/jpeg"),
|
||||||
|
type: UniversalFileType.image,
|
||||||
|
),
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void handleKeyPress(
|
||||||
|
BuildContext context,
|
||||||
|
WidgetRef ref,
|
||||||
|
RawKeyEvent event,
|
||||||
|
) {
|
||||||
|
if (event is! RawKeyDownEvent) return;
|
||||||
|
|
||||||
|
final isPaste = event.logicalKey == LogicalKeyboardKey.keyV;
|
||||||
|
final isModifierPressed = event.isMetaPressed || event.isControlPressed;
|
||||||
|
|
||||||
|
if (isPaste && isModifierPressed) {
|
||||||
|
handlePaste();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
final enterToSend = ref.read(appSettingsNotifierProvider).enterToSend;
|
||||||
|
final isEnter = event.logicalKey == LogicalKeyboardKey.enter;
|
||||||
|
|
||||||
|
if (isEnter) {
|
||||||
|
if (enterToSend && !isModifierPressed) {
|
||||||
|
send();
|
||||||
|
} else if (!enterToSend && isModifierPressed) {
|
||||||
|
send();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return Material(
|
return Material(
|
||||||
elevation: 8,
|
elevation: 8,
|
||||||
@@ -790,7 +980,7 @@ class _ChatInput extends ConsumerWidget {
|
|||||||
onMove: (delta) => onMoveAttachment(idx, delta),
|
onMove: (delta) => onMoveAttachment(idx, delta),
|
||||||
);
|
);
|
||||||
},
|
},
|
||||||
separatorBuilder: (_, __) => const Gap(8),
|
separatorBuilder: (_, _) => const Gap(8),
|
||||||
),
|
),
|
||||||
).padding(top: 12),
|
).padding(top: 12),
|
||||||
if (messageReplyingTo != null ||
|
if (messageReplyingTo != null ||
|
||||||
@@ -871,11 +1061,23 @@ class _ChatInput extends ConsumerWidget {
|
|||||||
Expanded(
|
Expanded(
|
||||||
child: RawKeyboardListener(
|
child: RawKeyboardListener(
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
onKey: (event) => _handleKeyPress(context, ref, event),
|
onKey: (event) => handleKeyPress(context, ref, event),
|
||||||
child: TextField(
|
child: TextField(
|
||||||
|
focusNode: inputFocusNode,
|
||||||
controller: messageController,
|
controller: messageController,
|
||||||
|
onSubmitted:
|
||||||
|
(enterToSend && isMobile)
|
||||||
|
? (_) {
|
||||||
|
send();
|
||||||
|
}
|
||||||
|
: null,
|
||||||
|
keyboardType:
|
||||||
|
(enterToSend && isMobile)
|
||||||
|
? TextInputType.text
|
||||||
|
: TextInputType.multiline,
|
||||||
|
textInputAction: TextInputAction.send,
|
||||||
inputFormatters: [
|
inputFormatters: [
|
||||||
if (enterToSend)
|
if (enterToSend && !isMobile)
|
||||||
TextInputFormatter.withFunction((oldValue, newValue) {
|
TextInputFormatter.withFunction((oldValue, newValue) {
|
||||||
if (newValue.text.endsWith('\n')) {
|
if (newValue.text.endsWith('\n')) {
|
||||||
return oldValue;
|
return oldValue;
|
||||||
@@ -910,7 +1112,7 @@ class _ChatInput extends ConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Icons.send),
|
icon: const Icon(Icons.send),
|
||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
onPressed: onSend,
|
onPressed: send,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
).padding(bottom: MediaQuery.of(context).padding.bottom),
|
).padding(bottom: MediaQuery.of(context).padding.bottom),
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ part of 'room.dart';
|
|||||||
// RiverpodGenerator
|
// RiverpodGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$messagesNotifierHash() => r'71a9fc1c6d024f6203f06225384c19335b9b6f2c';
|
String _$messagesNotifierHash() => r'afc4d43f4948ec571118cef0321838a6cefc89c0';
|
||||||
|
|
||||||
/// Copied from Dart SDK
|
/// Copied from Dart SDK
|
||||||
class _SystemHash {
|
class _SystemHash {
|
||||||
|
|||||||
@@ -14,10 +14,14 @@ import 'package:island/widgets/account/account_picker.dart';
|
|||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:island/widgets/content/sheet.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
part 'room_detail.freezed.dart';
|
part 'room_detail.freezed.dart';
|
||||||
|
part 'room_detail.g.dart';
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class ChatDetailScreen extends HookConsumerWidget {
|
class ChatDetailScreen extends HookConsumerWidget {
|
||||||
@@ -27,6 +31,206 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final roomState = ref.watch(chatroomProvider(id));
|
final roomState = ref.watch(chatroomProvider(id));
|
||||||
|
final roomIdentity = ref.watch(chatroomIdentityProvider(id));
|
||||||
|
|
||||||
|
const kNotifyLevelText = [
|
||||||
|
'chatNotifyLevelAll',
|
||||||
|
'chatNotifyLevelMention',
|
||||||
|
'chatNotifyLevelNone',
|
||||||
|
];
|
||||||
|
|
||||||
|
void setNotifyLevel(int level) async {
|
||||||
|
try {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
await client.patch(
|
||||||
|
'/chat/$id/members/me/notify',
|
||||||
|
data: {'notify_level': level},
|
||||||
|
);
|
||||||
|
ref.invalidate(chatroomIdentityProvider(id));
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(
|
||||||
|
context,
|
||||||
|
'chatNotifyLevelUpdated'.tr(args: [kNotifyLevelText[level].tr()]),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setChatBreak(DateTime until) async {
|
||||||
|
try {
|
||||||
|
final client = ref.watch(apiClientProvider);
|
||||||
|
await client.patch(
|
||||||
|
'/chat/$id/members/me/notify',
|
||||||
|
data: {'break_until': until.toUtc().toIso8601String()},
|
||||||
|
);
|
||||||
|
ref.invalidate(chatroomProvider(id));
|
||||||
|
} catch (err) {
|
||||||
|
showErrorAlert(err);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showNotifyLevelBottomSheet(SnChatMember identity) {
|
||||||
|
showModalBottomSheet(
|
||||||
|
isScrollControlled: true,
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => SheetScaffold(
|
||||||
|
height: 320,
|
||||||
|
titleText: 'chatNotifyLevel'.tr(),
|
||||||
|
child: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
title: const Text('chatNotifyLevelAll').tr(),
|
||||||
|
subtitle: const Text('chatNotifyLevelDescription').tr(),
|
||||||
|
leading: const Icon(Icons.notifications_active),
|
||||||
|
selected: identity.notify == 0,
|
||||||
|
onTap: () {
|
||||||
|
setNotifyLevel(0);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('chatNotifyLevelMention').tr(),
|
||||||
|
subtitle: const Text('chatNotifyLevelDescription').tr(),
|
||||||
|
leading: const Icon(Icons.alternate_email),
|
||||||
|
selected: identity.notify == 1,
|
||||||
|
onTap: () {
|
||||||
|
setNotifyLevel(1);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('chatNotifyLevelNone').tr(),
|
||||||
|
subtitle: const Text('chatNotifyLevelDescription').tr(),
|
||||||
|
leading: const Icon(Icons.notifications_off),
|
||||||
|
selected: identity.notify == 2,
|
||||||
|
onTap: () {
|
||||||
|
setNotifyLevel(2);
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
void showChatBreakDialog() {
|
||||||
|
final now = DateTime.now();
|
||||||
|
final durationController = TextEditingController();
|
||||||
|
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: const Text('chatBreak').tr(),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
const Text('chatBreakDescription').tr(),
|
||||||
|
const Gap(16),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('Clear').tr(),
|
||||||
|
subtitle: const Text('chatBreakClear').tr(),
|
||||||
|
leading: const Icon(Icons.notifications_active),
|
||||||
|
onTap: () {
|
||||||
|
setChatBreak(now);
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(context, 'chatBreakCleared'.tr());
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('5m'),
|
||||||
|
subtitle: const Text('chatBreakHour').tr(args: ['5m']),
|
||||||
|
leading: const Icon(Symbols.circle),
|
||||||
|
onTap: () {
|
||||||
|
setChatBreak(now.add(const Duration(minutes: 5)));
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(context, 'chatBreakSet'.tr(args: ['5m']));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('10m'),
|
||||||
|
subtitle: const Text('chatBreakHour').tr(args: ['10m']),
|
||||||
|
leading: const Icon(Symbols.circle),
|
||||||
|
onTap: () {
|
||||||
|
setChatBreak(now.add(const Duration(minutes: 10)));
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(context, 'chatBreakSet'.tr(args: ['10m']));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('15m'),
|
||||||
|
subtitle: const Text('chatBreakHour').tr(args: ['15m']),
|
||||||
|
leading: const Icon(Symbols.timer_3),
|
||||||
|
onTap: () {
|
||||||
|
setChatBreak(now.add(const Duration(minutes: 15)));
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(context, 'chatBreakSet'.tr(args: ['15m']));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
title: const Text('30m'),
|
||||||
|
subtitle: const Text('chatBreakHour').tr(args: ['30m']),
|
||||||
|
leading: const Icon(Symbols.timer),
|
||||||
|
onTap: () {
|
||||||
|
setChatBreak(now.add(const Duration(minutes: 30)));
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(context, 'chatBreakSet'.tr(args: ['30m']));
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const Gap(8),
|
||||||
|
TextField(
|
||||||
|
controller: durationController,
|
||||||
|
decoration: InputDecoration(
|
||||||
|
labelText: 'Custom (minutes)'.tr(),
|
||||||
|
hintText: 'Enter minutes'.tr(),
|
||||||
|
border: const OutlineInputBorder(),
|
||||||
|
suffixIcon: IconButton(
|
||||||
|
icon: const Icon(Icons.check),
|
||||||
|
onPressed: () {
|
||||||
|
final minutes = int.tryParse(durationController.text);
|
||||||
|
if (minutes != null && minutes > 0) {
|
||||||
|
setChatBreak(now.add(Duration(minutes: minutes)));
|
||||||
|
Navigator.pop(context);
|
||||||
|
if (context.mounted) {
|
||||||
|
showSnackBar(
|
||||||
|
context,
|
||||||
|
'chatBreakSet'.tr(args: ['${minutes}m']),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
keyboardType: TextInputType.number,
|
||||||
|
onTapOutside:
|
||||||
|
(_) => FocusManager.instance.primaryFocus?.unfocus(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.pop(context),
|
||||||
|
child: const Text('cancel').tr(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
const iconShadow = Shadow(
|
const iconShadow = Shadow(
|
||||||
color: Colors.black54,
|
color: Colors.black54,
|
||||||
@@ -48,9 +252,9 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
background:
|
background:
|
||||||
(currentRoom!.type == 1 &&
|
(currentRoom!.type == 1 &&
|
||||||
currentRoom.backgroundId != null)
|
currentRoom.background?.id != null)
|
||||||
? CloudImageWidget(
|
? CloudImageWidget(
|
||||||
fileId: currentRoom.backgroundId!,
|
fileId: currentRoom.background!.id,
|
||||||
)
|
)
|
||||||
: (currentRoom.type == 1 &&
|
: (currentRoom.type == 1 &&
|
||||||
currentRoom.members!.length == 1 &&
|
currentRoom.members!.length == 1 &&
|
||||||
@@ -59,7 +263,8 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
.first
|
.first
|
||||||
.account
|
.account
|
||||||
.profile
|
.profile
|
||||||
.backgroundId !=
|
.background
|
||||||
|
?.id !=
|
||||||
null)
|
null)
|
||||||
? CloudImageWidget(
|
? CloudImageWidget(
|
||||||
fileId:
|
fileId:
|
||||||
@@ -68,11 +273,12 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
.first
|
.first
|
||||||
.account
|
.account
|
||||||
.profile
|
.profile
|
||||||
.backgroundId!,
|
.background!
|
||||||
|
.id,
|
||||||
)
|
)
|
||||||
: currentRoom.backgroundId != null
|
: currentRoom.background?.id != null
|
||||||
? CloudImageWidget(
|
? CloudImageWidget(
|
||||||
fileId: currentRoom.backgroundId!,
|
fileId: currentRoom.background!.id,
|
||||||
fit: BoxFit.cover,
|
fit: BoxFit.cover,
|
||||||
)
|
)
|
||||||
: Container(
|
: Container(
|
||||||
@@ -108,17 +314,59 @@ class ChatDetailScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
SliverToBoxAdapter(
|
SliverToBoxAdapter(
|
||||||
child: Padding(
|
child: Column(
|
||||||
padding: const EdgeInsets.all(16.0),
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
child: Column(
|
children: [
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
Text(
|
||||||
children: [
|
currentRoom.description ?? 'descriptionNone'.tr(),
|
||||||
Text(
|
style: const TextStyle(fontSize: 16),
|
||||||
currentRoom.description ?? 'descriptionNone'.tr(),
|
).padding(all: 24),
|
||||||
style: const TextStyle(fontSize: 16),
|
const Divider(height: 1),
|
||||||
),
|
roomIdentity.when(
|
||||||
],
|
data:
|
||||||
),
|
(identity) => Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
leading: const Icon(Symbols.notifications),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
title: const Text('chatNotifyLevel').tr(),
|
||||||
|
subtitle: Text(
|
||||||
|
kNotifyLevelText[identity!.notify].tr(),
|
||||||
|
),
|
||||||
|
onTap:
|
||||||
|
() =>
|
||||||
|
showNotifyLevelBottomSheet(identity),
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
contentPadding: EdgeInsets.symmetric(
|
||||||
|
horizontal: 24,
|
||||||
|
),
|
||||||
|
leading: const Icon(Icons.timer),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
title: const Text('chatBreak').tr(),
|
||||||
|
subtitle:
|
||||||
|
identity.breakUntil != null &&
|
||||||
|
identity.breakUntil!.isAfter(
|
||||||
|
DateTime.now(),
|
||||||
|
)
|
||||||
|
? Text(
|
||||||
|
DateFormat(
|
||||||
|
'yyyy-MM-dd HH:mm',
|
||||||
|
).format(identity.breakUntil!),
|
||||||
|
)
|
||||||
|
: const Text('chatBreakNone').tr(),
|
||||||
|
onTap: () => showChatBreakDialog(),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
|
loading: () => const SizedBox.shrink(),
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
@@ -229,7 +477,7 @@ class _ChatRoomActionMenu extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class ChatRoomMemberState with _$ChatRoomMemberState {
|
sealed class ChatRoomMemberState with _$ChatRoomMemberState {
|
||||||
const factory ChatRoomMemberState({
|
const factory ChatRoomMemberState({
|
||||||
required List<SnChatMember> members,
|
required List<SnChatMember> members,
|
||||||
required bool isLoading,
|
required bool isLoading,
|
||||||
@@ -285,12 +533,51 @@ class ChatMemberNotifier extends StateNotifier<ChatRoomMemberState> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class ChatMemberListNotifier extends _$ChatMemberListNotifier
|
||||||
|
with CursorPagingNotifierMixin<SnChatMember> {
|
||||||
|
@override
|
||||||
|
Future<CursorPagingData<SnChatMember>> build(String roomId) {
|
||||||
|
return fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<CursorPagingData<SnChatMember>> fetch({String? cursor}) async {
|
||||||
|
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||||
|
final take = 20;
|
||||||
|
|
||||||
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
|
final response = await apiClient.get(
|
||||||
|
'/chat/$roomId/members',
|
||||||
|
queryParameters: {'offset': offset, 'take': take},
|
||||||
|
);
|
||||||
|
|
||||||
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
|
final List<dynamic> data = response.data;
|
||||||
|
final members = data.map((e) => SnChatMember.fromJson(e)).toList();
|
||||||
|
|
||||||
|
// Calculate next cursor based on total count
|
||||||
|
final nextOffset = offset + members.length;
|
||||||
|
final String? nextCursor =
|
||||||
|
nextOffset < total ? nextOffset.toString() : null;
|
||||||
|
|
||||||
|
return CursorPagingData(
|
||||||
|
items: members,
|
||||||
|
nextCursor: nextCursor,
|
||||||
|
hasMore: members.length < total,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
class _ChatMemberListSheet extends HookConsumerWidget {
|
class _ChatMemberListSheet extends HookConsumerWidget {
|
||||||
final String roomId;
|
final String roomId;
|
||||||
const _ChatMemberListSheet({required this.roomId});
|
const _ChatMemberListSheet({required this.roomId});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final memberListProvider = chatMemberListNotifierProvider(roomId);
|
||||||
|
|
||||||
|
// For backward compatibility and to show total count in the header
|
||||||
final memberState = ref.watch(chatMemberStateProvider(roomId));
|
final memberState = ref.watch(chatMemberStateProvider(roomId));
|
||||||
final memberNotifier = ref.read(chatMemberStateProvider(roomId).notifier);
|
final memberNotifier = ref.read(chatMemberStateProvider(roomId).notifier);
|
||||||
|
|
||||||
@@ -316,8 +603,10 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
'/chat/invites/$roomId',
|
'/chat/invites/$roomId',
|
||||||
data: {'related_user_id': result.id, 'role': 0},
|
data: {'related_user_id': result.id, 'role': 0},
|
||||||
);
|
);
|
||||||
|
// Refresh both providers
|
||||||
memberNotifier.reset();
|
memberNotifier.reset();
|
||||||
await memberNotifier.loadMore();
|
await memberNotifier.loadMore();
|
||||||
|
ref.invalidate(memberListProvider);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
}
|
}
|
||||||
@@ -349,8 +638,10 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.refresh),
|
icon: const Icon(Symbols.refresh),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
// Refresh both providers
|
||||||
memberNotifier.reset();
|
memberNotifier.reset();
|
||||||
memberNotifier.loadMore();
|
memberNotifier.loadMore();
|
||||||
|
ref.invalidate(memberListProvider);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -363,108 +654,103 @@ class _ChatMemberListSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child: PagingHelperView(
|
||||||
memberState.error != null
|
provider: memberListProvider,
|
||||||
? Center(child: Text(memberState.error!))
|
futureRefreshable: memberListProvider.future,
|
||||||
: ListView.builder(
|
notifierRefreshable: memberListProvider.notifier,
|
||||||
itemCount: memberState.members.length + 1,
|
contentBuilder: (data, widgetCount, endItemView) {
|
||||||
itemBuilder: (context, index) {
|
return ListView.builder(
|
||||||
if (index == memberState.members.length) {
|
itemCount: widgetCount,
|
||||||
if (memberState.isLoading) {
|
itemBuilder: (context, index) {
|
||||||
return const Center(
|
if (index == data.items.length) {
|
||||||
child: Padding(
|
return endItemView;
|
||||||
padding: EdgeInsets.all(16.0),
|
}
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (memberState.members.length < memberState.total) {
|
|
||||||
memberNotifier.loadMore(
|
|
||||||
offset: memberState.members.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
final member = memberState.members[index];
|
final member = data.items[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
fileId: member.account.profile.pictureId,
|
fileId: member.account.profile.picture?.id,
|
||||||
),
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: Text(member.account.nick)),
|
Flexible(child: Text(member.account.nick)),
|
||||||
if (member.joinedAt == null)
|
if (member.joinedAt == null)
|
||||||
const Icon(Symbols.pending_actions, size: 20),
|
const Icon(Symbols.pending_actions, size: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Row(
|
subtitle: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
member.role >= 100
|
member.role >= 100
|
||||||
? 'permissionOwner'
|
? 'permissionOwner'
|
||||||
: member.role >= 50
|
: member.role >= 50
|
||||||
? 'permissionModerator'
|
? 'permissionModerator'
|
||||||
: 'permissionMember',
|
: 'permissionMember',
|
||||||
).tr(),
|
).tr(),
|
||||||
Text('·').bold().padding(horizontal: 6),
|
Text('·').bold().padding(horizontal: 6),
|
||||||
Expanded(child: Text("@${member.account.name}")),
|
Expanded(child: Text("@${member.account.name}")),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if ((roomIdentity.value?.role ?? 0) >= 50)
|
if ((roomIdentity.value?.role ?? 0) >= 50)
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.edit),
|
icon: const Icon(Symbols.edit),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
(context) => _ChatMemberRoleSheet(
|
(context) => _ChatMemberRoleSheet(
|
||||||
roomId: roomId,
|
roomId: roomId,
|
||||||
member: member,
|
member: member,
|
||||||
),
|
),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
memberNotifier.reset();
|
// Refresh both providers
|
||||||
memberNotifier.loadMore();
|
memberNotifier.reset();
|
||||||
}
|
memberNotifier.loadMore();
|
||||||
});
|
ref.invalidate(memberListProvider);
|
||||||
},
|
}
|
||||||
),
|
});
|
||||||
if ((roomIdentity.value?.role ?? 0) >= 50)
|
},
|
||||||
IconButton(
|
),
|
||||||
icon: const Icon(Symbols.delete),
|
if ((roomIdentity.value?.role ?? 0) >= 50)
|
||||||
onPressed: () {
|
IconButton(
|
||||||
showConfirmAlert(
|
icon: const Icon(Symbols.delete),
|
||||||
'removeChatMemberHint'.tr(),
|
onPressed: () {
|
||||||
'removeChatMember'.tr(),
|
showConfirmAlert(
|
||||||
).then((confirm) async {
|
'removeChatMemberHint'.tr(),
|
||||||
if (confirm != true) return;
|
'removeChatMember'.tr(),
|
||||||
try {
|
).then((confirm) async {
|
||||||
final apiClient = ref.watch(
|
if (confirm != true) return;
|
||||||
apiClientProvider,
|
try {
|
||||||
);
|
final apiClient = ref.watch(
|
||||||
await apiClient.delete(
|
apiClientProvider,
|
||||||
'/chat/$roomId/members/${member.accountId}',
|
);
|
||||||
);
|
await apiClient.delete(
|
||||||
memberNotifier.reset();
|
'/chat/$roomId/members/${member.accountId}',
|
||||||
memberNotifier.loadMore();
|
);
|
||||||
} catch (err) {
|
// Refresh both providers
|
||||||
showErrorAlert(err);
|
memberNotifier.reset();
|
||||||
}
|
memberNotifier.loadMore();
|
||||||
});
|
ref.invalidate(memberListProvider);
|
||||||
},
|
} catch (err) {
|
||||||
),
|
showErrorAlert(err);
|
||||||
],
|
}
|
||||||
),
|
});
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
180
lib/screens/chat/room_detail.g.dart
Normal file
180
lib/screens/chat/room_detail.g.dart
Normal file
@@ -0,0 +1,180 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'room_detail.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// RiverpodGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
String _$chatMemberListNotifierHash() =>
|
||||||
|
r'f2191a631ba00ae3de39ccac10e4cdd065ffee17';
|
||||||
|
|
||||||
|
/// 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));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract class _$ChatMemberListNotifier
|
||||||
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnChatMember>> {
|
||||||
|
late final String roomId;
|
||||||
|
|
||||||
|
FutureOr<CursorPagingData<SnChatMember>> build(String roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [ChatMemberListNotifier].
|
||||||
|
@ProviderFor(ChatMemberListNotifier)
|
||||||
|
const chatMemberListNotifierProvider = ChatMemberListNotifierFamily();
|
||||||
|
|
||||||
|
/// See also [ChatMemberListNotifier].
|
||||||
|
class ChatMemberListNotifierFamily
|
||||||
|
extends Family<AsyncValue<CursorPagingData<SnChatMember>>> {
|
||||||
|
/// See also [ChatMemberListNotifier].
|
||||||
|
const ChatMemberListNotifierFamily();
|
||||||
|
|
||||||
|
/// See also [ChatMemberListNotifier].
|
||||||
|
ChatMemberListNotifierProvider call(String roomId) {
|
||||||
|
return ChatMemberListNotifierProvider(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
ChatMemberListNotifierProvider getProviderOverride(
|
||||||
|
covariant ChatMemberListNotifierProvider 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'chatMemberListNotifierProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [ChatMemberListNotifier].
|
||||||
|
class ChatMemberListNotifierProvider
|
||||||
|
extends
|
||||||
|
AutoDisposeAsyncNotifierProviderImpl<
|
||||||
|
ChatMemberListNotifier,
|
||||||
|
CursorPagingData<SnChatMember>
|
||||||
|
> {
|
||||||
|
/// See also [ChatMemberListNotifier].
|
||||||
|
ChatMemberListNotifierProvider(String roomId)
|
||||||
|
: this._internal(
|
||||||
|
() => ChatMemberListNotifier()..roomId = roomId,
|
||||||
|
from: chatMemberListNotifierProvider,
|
||||||
|
name: r'chatMemberListNotifierProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$chatMemberListNotifierHash,
|
||||||
|
dependencies: ChatMemberListNotifierFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
ChatMemberListNotifierFamily._allTransitiveDependencies,
|
||||||
|
roomId: roomId,
|
||||||
|
);
|
||||||
|
|
||||||
|
ChatMemberListNotifierProvider._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
|
||||||
|
FutureOr<CursorPagingData<SnChatMember>> runNotifierBuild(
|
||||||
|
covariant ChatMemberListNotifier notifier,
|
||||||
|
) {
|
||||||
|
return notifier.build(roomId);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(ChatMemberListNotifier Function() create) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: ChatMemberListNotifierProvider._internal(
|
||||||
|
() => create()..roomId = roomId,
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
roomId: roomId,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeAsyncNotifierProviderElement<
|
||||||
|
ChatMemberListNotifier,
|
||||||
|
CursorPagingData<SnChatMember>
|
||||||
|
>
|
||||||
|
createElement() {
|
||||||
|
return _ChatMemberListNotifierProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is ChatMemberListNotifierProvider && 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 ChatMemberListNotifierRef
|
||||||
|
on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnChatMember>> {
|
||||||
|
/// The parameter `roomId` of this provider.
|
||||||
|
String get roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _ChatMemberListNotifierProviderElement
|
||||||
|
extends
|
||||||
|
AutoDisposeAsyncNotifierProviderElement<
|
||||||
|
ChatMemberListNotifier,
|
||||||
|
CursorPagingData<SnChatMember>
|
||||||
|
>
|
||||||
|
with ChatMemberListNotifierRef {
|
||||||
|
_ChatMemberListNotifierProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get roomId => (origin as ChatMemberListNotifierProvider).roomId;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 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
|
||||||
@@ -101,7 +101,7 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
minTileHeight: 48,
|
minTileHeight: 48,
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
radius: 16,
|
radius: 16,
|
||||||
fileId: item.pictureId,
|
fileId: item.picture?.id,
|
||||||
),
|
),
|
||||||
title: Text(item.nick),
|
title: Text(item.nick),
|
||||||
subtitle: Text('@${item.name}'),
|
subtitle: Text('@${item.name}'),
|
||||||
@@ -115,7 +115,7 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
)
|
)
|
||||||
.toList(),
|
.toList(),
|
||||||
loading: () => [],
|
loading: () => [],
|
||||||
error: (_, __) => [],
|
error: (_, _) => [],
|
||||||
);
|
);
|
||||||
|
|
||||||
final publisherStats = ref.watch(
|
final publisherStats = ref.watch(
|
||||||
@@ -150,7 +150,7 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
...publishersMenu.map(
|
...publishersMenu.map(
|
||||||
(e) => ProfilePictureWidget(
|
(e) => ProfilePictureWidget(
|
||||||
radius: 16,
|
radius: 16,
|
||||||
fileId: e.value?.pictureId,
|
fileId: e.value?.picture?.id,
|
||||||
).center().padding(right: 8),
|
).center().padding(right: 8),
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
@@ -204,7 +204,7 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
...(publishers.value?.map(
|
...(publishers.value?.map(
|
||||||
(publisher) => ListTile(
|
(publisher) => ListTile(
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
fileId: publisher.pictureId,
|
fileId: publisher.picture?.id,
|
||||||
),
|
),
|
||||||
title: Text(publisher.nick),
|
title: Text(publisher.nick),
|
||||||
subtitle: Text('@${publisher.name}'),
|
subtitle: Text('@${publisher.name}'),
|
||||||
@@ -293,7 +293,7 @@ class CreatorHubScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
loading: () => const Center(child: CircularProgressIndicator()),
|
loading: () => const Center(child: CircularProgressIndicator()),
|
||||||
error: (_, __) => const SizedBox.shrink(),
|
error: (_, _) => const SizedBox.shrink(),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -7,6 +7,7 @@ import 'package:flutter/material.dart';
|
|||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
|
import 'package:island/models/file.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/models/realm.dart';
|
import 'package:island/models/realm.dart';
|
||||||
import 'package:island/pods/config.dart';
|
import 'package:island/pods/config.dart';
|
||||||
@@ -95,19 +96,15 @@ class EditPublisherScreen extends HookConsumerWidget {
|
|||||||
submitting.value = true;
|
submitting.value = true;
|
||||||
try {
|
try {
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
final baseUrl = ref.watch(serverUrlProvider);
|
||||||
final atk = await getFreshAtk(
|
final token = await getToken(ref.watch(tokenProvider));
|
||||||
ref.watch(tokenPairProvider),
|
if (token == null) throw ArgumentError('Token is null');
|
||||||
baseUrl,
|
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (atk == null) throw ArgumentError('Access token is null');
|
|
||||||
final cloudFile =
|
final cloudFile =
|
||||||
await putMediaToCloud(
|
await putMediaToCloud(
|
||||||
fileData: result,
|
fileData: UniversalFile(
|
||||||
atk: atk,
|
data: result,
|
||||||
|
type: UniversalFileType.image,
|
||||||
|
),
|
||||||
|
atk: token,
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
filename: result.name,
|
filename: result.name,
|
||||||
mimetype: result.mimeType ?? 'image/jpeg',
|
mimetype: result.mimeType ?? 'image/jpeg',
|
||||||
@@ -145,8 +142,8 @@ class EditPublisherScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
if (publisher.value != null) {
|
if (publisher.value != null) {
|
||||||
picture.value = publisher.value!.pictureId;
|
picture.value = publisher.value!.picture?.id;
|
||||||
background.value = publisher.value!.backgroundId;
|
background.value = publisher.value!.background?.id;
|
||||||
nameController.text = publisher.value!.name;
|
nameController.text = publisher.value!.name;
|
||||||
nickController.text = publisher.value!.nick;
|
nickController.text = publisher.value!.nick;
|
||||||
bioController.text = publisher.value!.bio;
|
bioController.text = publisher.value!.bio;
|
||||||
@@ -200,7 +197,7 @@ class EditPublisherScreen extends HookConsumerWidget {
|
|||||||
realms: joinedRealms.when(
|
realms: joinedRealms.when(
|
||||||
data: (realms) => realms,
|
data: (realms) => realms,
|
||||||
loading: () => [],
|
loading: () => [],
|
||||||
error: (_, __) => [],
|
error: (_, _) => [],
|
||||||
),
|
),
|
||||||
onChanged: (SnRealm? value) {
|
onChanged: (SnRealm? value) {
|
||||||
currentRealm.value = value;
|
currentRealm.value = value;
|
||||||
@@ -286,14 +283,14 @@ class EditPublisherScreen extends HookConsumerWidget {
|
|||||||
nameController.text = user.value!.name;
|
nameController.text = user.value!.name;
|
||||||
nickController.text = user.value!.nick;
|
nickController.text = user.value!.nick;
|
||||||
bioController.text = user.value!.profile.bio;
|
bioController.text = user.value!.profile.bio;
|
||||||
picture.value = user.value!.profile.pictureId;
|
picture.value = user.value!.profile.picture?.id;
|
||||||
background.value = user.value!.profile.backgroundId;
|
background.value = user.value!.profile.background?.id;
|
||||||
} else {
|
} else {
|
||||||
nameController.text = currentRealm.value!.slug;
|
nameController.text = currentRealm.value!.slug;
|
||||||
nickController.text = currentRealm.value!.name;
|
nickController.text = currentRealm.value!.name;
|
||||||
bioController.text = currentRealm.value!.description;
|
bioController.text = currentRealm.value!.description;
|
||||||
picture.value = currentRealm.value!.pictureId;
|
picture.value = currentRealm.value!.picture?.id;
|
||||||
background.value = currentRealm.value!.backgroundId;
|
background.value = currentRealm.value!.background?.id;
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
label:
|
label:
|
||||||
|
|||||||
@@ -298,7 +298,7 @@ class _StickerPackActionMenu extends HookConsumerWidget {
|
|||||||
if (confirm) {
|
if (confirm) {
|
||||||
final client = ref.watch(apiClientProvider);
|
final client = ref.watch(apiClientProvider);
|
||||||
client.delete('/stickers/$packId');
|
client.delete('/stickers/$packId');
|
||||||
ref.invalidate(stickerPacksProvider);
|
ref.invalidate(stickerPacksNotifierProvider);
|
||||||
if (context.mounted) context.router.maybePop(true);
|
if (context.mounted) context.router.maybePop(true);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -310,7 +310,7 @@ class _StickerPackActionMenu extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
abstract class StickerWithPackQuery with _$StickerWithPackQuery {
|
sealed class StickerWithPackQuery with _$StickerWithPackQuery {
|
||||||
const factory StickerWithPackQuery({
|
const factory StickerWithPackQuery({
|
||||||
required String packId,
|
required String packId,
|
||||||
required String id,
|
required String id,
|
||||||
|
|||||||
@@ -13,7 +13,7 @@ import 'package:island/widgets/app_scaffold.dart';
|
|||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:very_good_infinite_list/very_good_infinite_list.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
|
|
||||||
part 'stickers.g.dart';
|
part 'stickers.g.dart';
|
||||||
|
|
||||||
@@ -24,9 +24,6 @@ class StickersScreen extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final stickersState = ref.watch(stickerPacksProvider);
|
|
||||||
final stickersNotifier = ref.watch(stickerPacksProvider.notifier);
|
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
title: const Text('stickers').tr(),
|
title: const Text('stickers').tr(),
|
||||||
@@ -37,7 +34,7 @@ class StickersScreen extends HookConsumerWidget {
|
|||||||
value,
|
value,
|
||||||
) {
|
) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
stickersNotifier.refresh();
|
ref.invalidate(stickerPacksNotifierProvider(pubName));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
@@ -46,104 +43,90 @@ class StickersScreen extends HookConsumerWidget {
|
|||||||
const Gap(8),
|
const Gap(8),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
body: stickersState.when(
|
body: SliverStickerPacksList(pubName: pubName),
|
||||||
data:
|
|
||||||
(stickers) => RefreshIndicator(
|
|
||||||
onRefresh: stickersNotifier.refresh,
|
|
||||||
child: InfiniteList(
|
|
||||||
padding: EdgeInsets.zero,
|
|
||||||
itemCount: stickers.length,
|
|
||||||
hasReachedMax: stickersNotifier.isReachedMax,
|
|
||||||
isLoading: stickersNotifier.isLoading,
|
|
||||||
onFetchData: stickersNotifier.fetchMore,
|
|
||||||
itemBuilder: (context, index) {
|
|
||||||
return ListTile(
|
|
||||||
title: Text(stickers[index].name),
|
|
||||||
subtitle: Text(stickers[index].description),
|
|
||||||
trailing: const Icon(Symbols.chevron_right),
|
|
||||||
onTap: () {
|
|
||||||
context.router.push(
|
|
||||||
StickerPackDetailRoute(
|
|
||||||
pubName: pubName,
|
|
||||||
id: stickers[index].id,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
loading: () => const CircularProgressIndicator(),
|
|
||||||
error: (error, stack) => Text('Error: $error'),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final stickerPacksProvider = StateNotifierProvider<
|
class SliverStickerPacksList extends HookConsumerWidget {
|
||||||
StickerPacksNotifier,
|
final String pubName;
|
||||||
AsyncValue<List<SnStickerPack>>
|
const SliverStickerPacksList({super.key, required this.pubName});
|
||||||
>((ref) {
|
|
||||||
return StickerPacksNotifier(ref.watch(apiClientProvider));
|
|
||||||
});
|
|
||||||
|
|
||||||
class StickerPacksNotifier
|
@override
|
||||||
extends StateNotifier<AsyncValue<List<SnStickerPack>>> {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final Dio _apiClient;
|
return PagingHelperView(
|
||||||
StickerPacksNotifier(this._apiClient) : super(const AsyncValue.loading()) {
|
provider: stickerPacksNotifierProvider(pubName),
|
||||||
fetchStickers();
|
futureRefreshable: stickerPacksNotifierProvider(pubName).future,
|
||||||
|
notifierRefreshable: stickerPacksNotifierProvider(pubName).notifier,
|
||||||
|
contentBuilder:
|
||||||
|
(data, widgetCount, endItemView) => ListView.builder(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
|
itemCount: widgetCount,
|
||||||
|
itemBuilder: (context, index) {
|
||||||
|
if (index == widgetCount - 1) {
|
||||||
|
return endItemView;
|
||||||
|
}
|
||||||
|
|
||||||
|
final sticker = data.items[index];
|
||||||
|
return ListTile(
|
||||||
|
title: Text(sticker.name),
|
||||||
|
subtitle: Text(sticker.description),
|
||||||
|
trailing: const Icon(Symbols.chevron_right),
|
||||||
|
onTap: () {
|
||||||
|
context.router.push(
|
||||||
|
StickerPackDetailRoute(pubName: pubName, id: sticker.id),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class StickerPacksNotifier extends _$StickerPacksNotifier
|
||||||
|
with CursorPagingNotifierMixin<SnStickerPack> {
|
||||||
|
static const int _pageSize = 20;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<CursorPagingData<SnStickerPack>> build(String pubName) {
|
||||||
|
return fetch(cursor: null);
|
||||||
}
|
}
|
||||||
|
|
||||||
int offset = 0;
|
@override
|
||||||
int take = 20;
|
Future<CursorPagingData<SnStickerPack>> fetch({
|
||||||
int total = 0;
|
required String? cursor,
|
||||||
|
}) async {
|
||||||
bool isLoading = false;
|
final client = ref.read(apiClientProvider);
|
||||||
bool get isReachedMax =>
|
final offset = cursor == null ? 0 : int.parse(cursor);
|
||||||
state.valueOrNull != null && state.valueOrNull!.length >= total;
|
|
||||||
|
|
||||||
Future<void> fetchStickers() async {
|
|
||||||
if (isLoading) return;
|
|
||||||
isLoading = true;
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final response = await _apiClient.get(
|
final response = await client.get(
|
||||||
'/stickers?offset=$offset&take=$take',
|
'/stickers',
|
||||||
|
queryParameters: {
|
||||||
|
'offset': offset,
|
||||||
|
'take': _pageSize,
|
||||||
|
'pubName': pubName,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
if (response.statusCode == 200) {
|
|
||||||
total = int.parse(response.headers.value('X-Total') ?? '0');
|
|
||||||
final newStickers =
|
|
||||||
response.data
|
|
||||||
.map((e) => SnStickerPack.fromJson(e))
|
|
||||||
.cast<SnStickerPack>()
|
|
||||||
.toList();
|
|
||||||
|
|
||||||
state = AsyncValue.data(
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
state.valueOrNull != null
|
final List<dynamic> data = response.data;
|
||||||
? [...state.value!, ...newStickers]
|
final stickers = data.map((e) => SnStickerPack.fromJson(e)).toList();
|
||||||
: newStickers,
|
|
||||||
);
|
final hasMore = offset + stickers.length < total;
|
||||||
offset += take;
|
final nextCursor = hasMore ? (offset + stickers.length).toString() : null;
|
||||||
} else {
|
|
||||||
state = AsyncValue.error('Failed to load stickers', StackTrace.current);
|
return CursorPagingData(
|
||||||
}
|
items: stickers,
|
||||||
} catch (err, stackTrace) {
|
hasMore: hasMore,
|
||||||
state = AsyncValue.error(err, stackTrace);
|
nextCursor: nextCursor,
|
||||||
} finally {
|
);
|
||||||
isLoading = false;
|
} catch (err) {
|
||||||
|
rethrow;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> fetchMore() async {
|
|
||||||
if (state.valueOrNull == null || state.valueOrNull!.length >= total) return;
|
|
||||||
await fetchStickers();
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> refresh() async {
|
|
||||||
offset = 0;
|
|
||||||
state = const AsyncValue.loading();
|
|
||||||
await fetchStickers();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@riverpod
|
@riverpod
|
||||||
|
|||||||
@@ -147,5 +147,154 @@ class _StickerPackProviderElement
|
|||||||
String? get packId => (origin as StickerPackProvider).packId;
|
String? get packId => (origin as StickerPackProvider).packId;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _$stickerPacksNotifierHash() =>
|
||||||
|
r'dc0cc4ec27fdd6d5da28f982ff10c852f8107a18';
|
||||||
|
|
||||||
|
abstract class _$StickerPacksNotifier
|
||||||
|
extends BuildlessAutoDisposeAsyncNotifier<CursorPagingData<SnStickerPack>> {
|
||||||
|
late final String pubName;
|
||||||
|
|
||||||
|
FutureOr<CursorPagingData<SnStickerPack>> build(String pubName);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [StickerPacksNotifier].
|
||||||
|
@ProviderFor(StickerPacksNotifier)
|
||||||
|
const stickerPacksNotifierProvider = StickerPacksNotifierFamily();
|
||||||
|
|
||||||
|
/// See also [StickerPacksNotifier].
|
||||||
|
class StickerPacksNotifierFamily
|
||||||
|
extends Family<AsyncValue<CursorPagingData<SnStickerPack>>> {
|
||||||
|
/// See also [StickerPacksNotifier].
|
||||||
|
const StickerPacksNotifierFamily();
|
||||||
|
|
||||||
|
/// See also [StickerPacksNotifier].
|
||||||
|
StickerPacksNotifierProvider call(String pubName) {
|
||||||
|
return StickerPacksNotifierProvider(pubName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
StickerPacksNotifierProvider getProviderOverride(
|
||||||
|
covariant StickerPacksNotifierProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.pubName);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'stickerPacksNotifierProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [StickerPacksNotifier].
|
||||||
|
class StickerPacksNotifierProvider
|
||||||
|
extends
|
||||||
|
AutoDisposeAsyncNotifierProviderImpl<
|
||||||
|
StickerPacksNotifier,
|
||||||
|
CursorPagingData<SnStickerPack>
|
||||||
|
> {
|
||||||
|
/// See also [StickerPacksNotifier].
|
||||||
|
StickerPacksNotifierProvider(String pubName)
|
||||||
|
: this._internal(
|
||||||
|
() => StickerPacksNotifier()..pubName = pubName,
|
||||||
|
from: stickerPacksNotifierProvider,
|
||||||
|
name: r'stickerPacksNotifierProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$stickerPacksNotifierHash,
|
||||||
|
dependencies: StickerPacksNotifierFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
StickerPacksNotifierFamily._allTransitiveDependencies,
|
||||||
|
pubName: pubName,
|
||||||
|
);
|
||||||
|
|
||||||
|
StickerPacksNotifierProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.pubName,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String pubName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
FutureOr<CursorPagingData<SnStickerPack>> runNotifierBuild(
|
||||||
|
covariant StickerPacksNotifier notifier,
|
||||||
|
) {
|
||||||
|
return notifier.build(pubName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(StickerPacksNotifier Function() create) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: StickerPacksNotifierProvider._internal(
|
||||||
|
() => create()..pubName = pubName,
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
pubName: pubName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeAsyncNotifierProviderElement<
|
||||||
|
StickerPacksNotifier,
|
||||||
|
CursorPagingData<SnStickerPack>
|
||||||
|
>
|
||||||
|
createElement() {
|
||||||
|
return _StickerPacksNotifierProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is StickerPacksNotifierProvider && other.pubName == pubName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, pubName.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin StickerPacksNotifierRef
|
||||||
|
on AutoDisposeAsyncNotifierProviderRef<CursorPagingData<SnStickerPack>> {
|
||||||
|
/// The parameter `pubName` of this provider.
|
||||||
|
String get pubName;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _StickerPacksNotifierProviderElement
|
||||||
|
extends
|
||||||
|
AutoDisposeAsyncNotifierProviderElement<
|
||||||
|
StickerPacksNotifier,
|
||||||
|
CursorPagingData<SnStickerPack>
|
||||||
|
>
|
||||||
|
with StickerPacksNotifierRef {
|
||||||
|
_StickerPacksNotifierProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get pubName => (origin as StickerPacksNotifierProvider).pubName;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
|||||||
@@ -7,7 +7,6 @@ import 'package:island/models/activity.dart';
|
|||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/route.gr.dart';
|
import 'package:island/route.gr.dart';
|
||||||
import 'package:island/services/responsive.dart';
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/widgets/check_in.dart';
|
import 'package:island/widgets/check_in.dart';
|
||||||
@@ -17,6 +16,7 @@ import 'package:material_symbols_icons/symbols.dart';
|
|||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
part 'explore.g.dart';
|
part 'explore.g.dart';
|
||||||
|
|
||||||
@@ -131,10 +131,16 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
|
|
||||||
switch (item.type) {
|
switch (item.type) {
|
||||||
case 'posts.new':
|
case 'posts.new':
|
||||||
|
case 'posts.new.replies':
|
||||||
|
final isReply = item.type == 'posts.new.replies';
|
||||||
itemWidget = PostItem(
|
itemWidget = PostItem(
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
isWideScreen(context) ? Colors.transparent : null,
|
isWideScreen(context) ? Colors.transparent : null,
|
||||||
item: SnPost.fromJson(item.data),
|
item: SnPost.fromJson(item.data),
|
||||||
|
padding:
|
||||||
|
isReply
|
||||||
|
? EdgeInsets.only(left: 16, right: 16, bottom: 16)
|
||||||
|
: null,
|
||||||
onRefresh: (_) {
|
onRefresh: (_) {
|
||||||
activitiesNotifier.forceRefresh();
|
activitiesNotifier.forceRefresh();
|
||||||
},
|
},
|
||||||
@@ -145,12 +151,21 @@ class _ActivityListView extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
break;
|
if (isReply) {
|
||||||
case 'accounts.check-in':
|
itemWidget = Column(
|
||||||
itemWidget = CheckInActivityWidget(item: item);
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
break;
|
children: [
|
||||||
case 'accounts.status':
|
Row(
|
||||||
itemWidget = StatusActivityWidget(item: item);
|
children: [
|
||||||
|
const Icon(Symbols.reply),
|
||||||
|
const Gap(8),
|
||||||
|
Text('Replying your post'),
|
||||||
|
],
|
||||||
|
).padding(horizontal: 20, vertical: 8),
|
||||||
|
itemWidget,
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
itemWidget = const Placeholder();
|
itemWidget = const Placeholder();
|
||||||
@@ -174,12 +189,14 @@ class ActivityListNotifier extends _$ActivityListNotifier
|
|||||||
@override
|
@override
|
||||||
Future<CursorPagingData<SnActivity>> fetch({required String? cursor}) async {
|
Future<CursorPagingData<SnActivity>> fetch({required String? cursor}) async {
|
||||||
final client = ref.read(apiClientProvider);
|
final client = ref.read(apiClientProvider);
|
||||||
final offset = cursor == null ? 0 : int.parse(cursor);
|
|
||||||
final take = 20;
|
final take = 20;
|
||||||
|
|
||||||
final response = await client.get(
|
final response = await client.get(
|
||||||
'/activities',
|
'/activities',
|
||||||
queryParameters: {'offset': offset, 'take': take},
|
queryParameters: {
|
||||||
|
if (cursor != null) 'reading_cursor': cursor,
|
||||||
|
'take': take,
|
||||||
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
final List<SnActivity> items =
|
final List<SnActivity> items =
|
||||||
@@ -187,9 +204,9 @@ class ActivityListNotifier extends _$ActivityListNotifier
|
|||||||
.map((e) => SnActivity.fromJson(e as Map<String, dynamic>))
|
.map((e) => SnActivity.fromJson(e as Map<String, dynamic>))
|
||||||
.toList();
|
.toList();
|
||||||
|
|
||||||
final total = int.tryParse(response.headers['x-total']?.first ?? '') ?? 0;
|
final hasMore = (items.firstOrNull?.type ?? 'empty') != 'empty';
|
||||||
final hasMore = offset + items.length < total;
|
final nextCursor =
|
||||||
final nextCursor = hasMore ? (offset + items.length).toString() : null;
|
items.map((x) => x.createdAt).lastOrNull?.toIso8601String().toString();
|
||||||
|
|
||||||
return CursorPagingData(
|
return CursorPagingData(
|
||||||
items: items,
|
items: items,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'explore.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$activityListNotifierHash() =>
|
String _$activityListNotifierHash() =>
|
||||||
r'8a67d302e828408c7c4cf724d84c2c5958f2dc7e';
|
r'2ca8fe14686d7f4fb09ab26f2978eb2de7184565';
|
||||||
|
|
||||||
/// See also [ActivityListNotifier].
|
/// See also [ActivityListNotifier].
|
||||||
@ProviderFor(ActivityListNotifier)
|
@ProviderFor(ActivityListNotifier)
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
import 'dart:async';
|
||||||
import 'dart:math' as math;
|
import 'dart:math' as math;
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
@@ -7,6 +8,7 @@ import 'package:flutter/services.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/user.dart';
|
import 'package:island/models/user.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/markdown.dart';
|
import 'package:island/widgets/content/markdown.dart';
|
||||||
@@ -21,8 +23,18 @@ part 'notification.g.dart';
|
|||||||
@riverpod
|
@riverpod
|
||||||
class NotificationUnreadCountNotifier
|
class NotificationUnreadCountNotifier
|
||||||
extends _$NotificationUnreadCountNotifier {
|
extends _$NotificationUnreadCountNotifier {
|
||||||
|
StreamSubscription<WebSocketPacket>? _subscription;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Future<int> build() async {
|
Future<int> build() async {
|
||||||
|
// Subscribe to websocket events when this provider is built
|
||||||
|
_subscribeToWebSocket();
|
||||||
|
|
||||||
|
// Dispose the subscription when this provider is disposed
|
||||||
|
ref.onDispose(() {
|
||||||
|
_subscription?.cancel();
|
||||||
|
});
|
||||||
|
|
||||||
try {
|
try {
|
||||||
final client = ref.read(apiClientProvider);
|
final client = ref.read(apiClientProvider);
|
||||||
final response = await client.get('/notifications/count');
|
final response = await client.get('/notifications/count');
|
||||||
@@ -32,9 +44,23 @@ class NotificationUnreadCountNotifier
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void _subscribeToWebSocket() {
|
||||||
|
final webSocketService = ref.read(websocketProvider);
|
||||||
|
_subscription = webSocketService.dataStream.listen((packet) {
|
||||||
|
if (packet.type == 'notifications.new') {
|
||||||
|
_incrementCounter();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> _incrementCounter() async {
|
||||||
|
final current = await future;
|
||||||
|
state = AsyncData(current + 1);
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> decrement(int count) async {
|
Future<void> decrement(int count) async {
|
||||||
final current = await future;
|
final current = await future;
|
||||||
state = AsyncData(math.min(current - count, 0));
|
state = AsyncData(math.max(current - count, 0));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -94,6 +120,7 @@ class NotificationScreen extends HookConsumerWidget {
|
|||||||
notifierRefreshable: notificationListNotifierProvider.notifier,
|
notifierRefreshable: notificationListNotifierProvider.notifier,
|
||||||
contentBuilder:
|
contentBuilder:
|
||||||
(data, widgetCount, endItemView) => ListView.builder(
|
(data, widgetCount, endItemView) => ListView.builder(
|
||||||
|
padding: EdgeInsets.zero,
|
||||||
itemCount: widgetCount,
|
itemCount: widgetCount,
|
||||||
itemBuilder: (context, index) {
|
itemBuilder: (context, index) {
|
||||||
if (index == widgetCount - 1) {
|
if (index == widgetCount - 1) {
|
||||||
@@ -142,7 +169,7 @@ class NotificationScreen extends HookConsumerWidget {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
trailing:
|
trailing:
|
||||||
notification.viewedAt == null
|
notification.viewedAt != null
|
||||||
? null
|
? null
|
||||||
: Container(
|
: Container(
|
||||||
width: 12,
|
width: 12,
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ part of 'notification.dart';
|
|||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
String _$notificationUnreadCountNotifierHash() =>
|
String _$notificationUnreadCountNotifierHash() =>
|
||||||
r'074143cf208a3afe1495be405198532a23ef77c8';
|
r'372a2cc259d7d838cd4f33a9129f7396ef31dbb9';
|
||||||
|
|
||||||
/// See also [NotificationUnreadCountNotifier].
|
/// See also [NotificationUnreadCountNotifier].
|
||||||
@ProviderFor(NotificationUnreadCountNotifier)
|
@ProviderFor(NotificationUnreadCountNotifier)
|
||||||
|
|||||||
@@ -1,6 +1,3 @@
|
|||||||
import 'dart:io';
|
|
||||||
import 'dart:typed_data';
|
|
||||||
|
|
||||||
import 'package:auto_route/auto_route.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:collection/collection.dart';
|
import 'package:collection/collection.dart';
|
||||||
import 'package:dio/dio.dart';
|
import 'package:dio/dio.dart';
|
||||||
@@ -18,13 +15,15 @@ import 'package:island/pods/network.dart';
|
|||||||
import 'package:island/screens/creators/publishers.dart';
|
import 'package:island/screens/creators/publishers.dart';
|
||||||
import 'package:island/screens/posts/detail.dart';
|
import 'package:island/screens/posts/detail.dart';
|
||||||
import 'package:island/services/file.dart';
|
import 'package:island/services/file.dart';
|
||||||
|
import 'package:island/services/responsive.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
|
import 'package:island/widgets/content/attachment_preview.dart';
|
||||||
import 'package:island/widgets/post/publishers_modal.dart';
|
import 'package:island/widgets/post/publishers_modal.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
|
import 'package:pasteboard/pasteboard.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
import 'package:super_clipboard/super_clipboard.dart';
|
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class PostEditScreen extends HookConsumerWidget {
|
class PostEditScreen extends HookConsumerWidget {
|
||||||
@@ -53,7 +52,14 @@ class PostEditScreen extends HookConsumerWidget {
|
|||||||
@RoutePage()
|
@RoutePage()
|
||||||
class PostComposeScreen extends HookConsumerWidget {
|
class PostComposeScreen extends HookConsumerWidget {
|
||||||
final SnPost? originalPost;
|
final SnPost? originalPost;
|
||||||
const PostComposeScreen({super.key, this.originalPost});
|
final SnPost? repliedPost;
|
||||||
|
final SnPost? forwardedPost;
|
||||||
|
const PostComposeScreen({
|
||||||
|
super.key,
|
||||||
|
this.originalPost,
|
||||||
|
this.repliedPost,
|
||||||
|
this.forwardedPost,
|
||||||
|
});
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
@@ -90,9 +96,14 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
text: originalPost?.description,
|
text: originalPost?.description,
|
||||||
);
|
);
|
||||||
final contentController = useTextEditingController(
|
final contentController = useTextEditingController(
|
||||||
text: originalPost?.content,
|
text:
|
||||||
|
originalPost?.content ??
|
||||||
|
(forwardedPost != null ? '> ${forwardedPost!.content}\n\n' : null),
|
||||||
);
|
);
|
||||||
|
|
||||||
|
// Add visibility state with default value from original post or 0 (public)
|
||||||
|
final visibility = useState<int>(originalPost?.visibility ?? 0);
|
||||||
|
|
||||||
final submitting = useState(false);
|
final submitting = useState(false);
|
||||||
|
|
||||||
Future<void> pickPhotoMedia() async {
|
Future<void> pickPhotoMedia() async {
|
||||||
@@ -125,21 +136,14 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
final attachment = attachments.value[index];
|
final attachment = attachments.value[index];
|
||||||
if (attachment is SnCloudFile) return;
|
if (attachment is SnCloudFile) return;
|
||||||
final baseUrl = ref.watch(serverUrlProvider);
|
final baseUrl = ref.watch(serverUrlProvider);
|
||||||
final atk = await getFreshAtk(
|
final token = await getToken(ref.watch(tokenProvider));
|
||||||
ref.watch(tokenPairProvider),
|
if (token == null) throw ArgumentError('Token is null');
|
||||||
baseUrl,
|
|
||||||
onRefreshed: (atk, rtk) {
|
|
||||||
setTokenPair(ref.watch(sharedPreferencesProvider), atk, rtk);
|
|
||||||
ref.invalidate(tokenPairProvider);
|
|
||||||
},
|
|
||||||
);
|
|
||||||
if (atk == null) throw ArgumentError('Access token is null');
|
|
||||||
try {
|
try {
|
||||||
attachmentProgress.value = {...attachmentProgress.value, index: 0};
|
attachmentProgress.value = {...attachmentProgress.value, index: 0};
|
||||||
final cloudFile =
|
final cloudFile =
|
||||||
await putMediaToCloud(
|
await putMediaToCloud(
|
||||||
fileData: attachment.data,
|
fileData: attachment,
|
||||||
atk: atk,
|
atk: token,
|
||||||
baseUrl: baseUrl,
|
baseUrl: baseUrl,
|
||||||
filename: attachment.data.name ?? 'Post media',
|
filename: attachment.data.name ?? 'Post media',
|
||||||
mimetype:
|
mimetype:
|
||||||
@@ -195,12 +199,18 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
await client.request(
|
await client.request(
|
||||||
originalPost == null ? '/posts' : '/posts/${originalPost!.id}',
|
originalPost == null ? '/posts' : '/posts/${originalPost!.id}',
|
||||||
data: {
|
data: {
|
||||||
|
'title': titleController.text,
|
||||||
|
'description': descriptionController.text,
|
||||||
'content': contentController.text,
|
'content': contentController.text,
|
||||||
|
'visibility':
|
||||||
|
visibility.value, // Add visibility field to API request
|
||||||
'attachments':
|
'attachments':
|
||||||
attachments.value
|
attachments.value
|
||||||
.where((e) => e.isOnCloud)
|
.where((e) => e.isOnCloud)
|
||||||
.map((e) => e.data.id)
|
.map((e) => e.data.id)
|
||||||
.toList(),
|
.toList(),
|
||||||
|
if (repliedPost != null) 'replied_post_id': repliedPost!.id,
|
||||||
|
if (forwardedPost != null) 'forwarded_post_id': forwardedPost!.id,
|
||||||
},
|
},
|
||||||
options: Options(
|
options: Options(
|
||||||
headers: {'X-Pub': currentPublisher.value?.name},
|
headers: {'X-Pub': currentPublisher.value?.name},
|
||||||
@@ -217,51 +227,149 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<void> _handlePaste() async {
|
Future<void> handlePaste() async {
|
||||||
final clipboard = SystemClipboard.instance;
|
final clipboard = await Pasteboard.image;
|
||||||
if (clipboard == null) return;
|
if (clipboard == null) return;
|
||||||
|
|
||||||
final reader = await clipboard.read();
|
attachments.value = [
|
||||||
if (reader.canProvide(Formats.png)) {
|
...attachments.value,
|
||||||
reader.getFile(Formats.png, (file) async {
|
UniversalFile(
|
||||||
final stream = file.getStream();
|
data: XFile.fromData(clipboard, mimeType: "image/jpeg"),
|
||||||
final bytes = await stream.toList();
|
type: UniversalFileType.image,
|
||||||
final imageBytes = bytes.expand((e) => e).toList();
|
),
|
||||||
|
];
|
||||||
// Create a temporary file to store the image
|
|
||||||
final tempDir = Directory.systemTemp;
|
|
||||||
final tempFile = File(
|
|
||||||
'${tempDir.path}/pasted_image_${DateTime.now().millisecondsSinceEpoch}.png',
|
|
||||||
);
|
|
||||||
await tempFile.writeAsBytes(imageBytes);
|
|
||||||
|
|
||||||
// Add the file to attachments
|
|
||||||
attachments.value = [
|
|
||||||
...attachments.value,
|
|
||||||
UniversalFile(
|
|
||||||
data: XFile(tempFile.path),
|
|
||||||
type: UniversalFileType.image,
|
|
||||||
),
|
|
||||||
];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void _handleKeyPress(RawKeyEvent event) {
|
void handleKeyPress(RawKeyEvent event) {
|
||||||
if (event is! RawKeyDownEvent) return;
|
if (event is! RawKeyDownEvent) return;
|
||||||
|
|
||||||
final isPaste = event.logicalKey == LogicalKeyboardKey.keyV;
|
final isPaste = event.logicalKey == LogicalKeyboardKey.keyV;
|
||||||
final isModifierPressed = event.isMetaPressed || event.isControlPressed;
|
final isModifierPressed = event.isMetaPressed || event.isControlPressed;
|
||||||
|
|
||||||
if (isPaste && isModifierPressed) {
|
if (isPaste && isModifierPressed) {
|
||||||
_handlePaste();
|
handlePaste();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void showVisibilityModal() {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: Text('postVisibility'.tr()),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Symbols.public),
|
||||||
|
title: Text('postVisibilityPublic'.tr()),
|
||||||
|
onTap: () {
|
||||||
|
visibility.value = 0;
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
selected: visibility.value == 0,
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Symbols.group),
|
||||||
|
title: Text('postVisibilityFriends'.tr()),
|
||||||
|
onTap: () {
|
||||||
|
visibility.value = 1;
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
selected: visibility.value == 1,
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Symbols.link_off),
|
||||||
|
title: Text('postVisibilityUnlisted'.tr()),
|
||||||
|
onTap: () {
|
||||||
|
visibility.value = 2;
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
selected: visibility.value == 2,
|
||||||
|
),
|
||||||
|
ListTile(
|
||||||
|
leading: Icon(Symbols.lock),
|
||||||
|
title: Text('postVisibilityPrivate'.tr()),
|
||||||
|
onTap: () {
|
||||||
|
visibility.value = 3;
|
||||||
|
Navigator.pop(context);
|
||||||
|
},
|
||||||
|
selected: visibility.value == 3,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to get the appropriate icon for each visibility status
|
||||||
|
IconData getVisibilityIcon(int visibilityValue) {
|
||||||
|
switch (visibilityValue) {
|
||||||
|
case 1: // Friends
|
||||||
|
return Symbols.group;
|
||||||
|
case 2: // Unlisted
|
||||||
|
return Symbols.link_off;
|
||||||
|
case 3: // Private
|
||||||
|
return Symbols.lock;
|
||||||
|
default: // Public (0) or unknown
|
||||||
|
return Symbols.public;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper method to get the translation key for each visibility status
|
||||||
|
String getVisibilityText(int visibilityValue) {
|
||||||
|
switch (visibilityValue) {
|
||||||
|
case 1: // Friends
|
||||||
|
return 'postVisibilityFriends';
|
||||||
|
case 2: // Unlisted
|
||||||
|
return 'postVisibilityUnlisted';
|
||||||
|
case 3: // Private
|
||||||
|
return 'postVisibilityPrivate';
|
||||||
|
default: // Public (0) or unknown
|
||||||
|
return 'postVisibilityPublic';
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return AppScaffold(
|
return AppScaffold(
|
||||||
appBar: AppBar(
|
appBar: AppBar(
|
||||||
leading: const PageBackButton(),
|
leading: const PageBackButton(),
|
||||||
|
title:
|
||||||
|
isWideScreen(context)
|
||||||
|
? Text(originalPost != null ? 'editPost'.tr() : 'newPost'.tr())
|
||||||
|
: null,
|
||||||
actions: [
|
actions: [
|
||||||
|
if (isWideScreen(context))
|
||||||
|
Tooltip(
|
||||||
|
message: 'keyboard_shortcuts'.tr(),
|
||||||
|
child: IconButton(
|
||||||
|
icon: const Icon(Symbols.keyboard),
|
||||||
|
onPressed: () {
|
||||||
|
showDialog(
|
||||||
|
context: context,
|
||||||
|
builder:
|
||||||
|
(context) => AlertDialog(
|
||||||
|
title: Text('keyboard_shortcuts'.tr()),
|
||||||
|
content: Column(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
children: [
|
||||||
|
Text('Ctrl/Cmd + Enter: ${'submit'.tr()}'),
|
||||||
|
Text('Ctrl/Cmd + V: ${'paste'.tr()}'),
|
||||||
|
Text('Ctrl/Cmd + I: ${'add_image'.tr()}'),
|
||||||
|
Text('Ctrl/Cmd + Shift + V: ${'add_video'.tr()}'),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
actions: [
|
||||||
|
TextButton(
|
||||||
|
onPressed: () => Navigator.of(context).pop(),
|
||||||
|
child: Text('close'.tr()),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
onPressed: submitting.value ? null : performAction,
|
onPressed: submitting.value ? null : performAction,
|
||||||
icon:
|
icon:
|
||||||
@@ -284,6 +392,48 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
body: Column(
|
body: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
if (repliedPost != null)
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceVariant.withOpacity(0.5),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.reply, size: 16),
|
||||||
|
const Gap(8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'${'reply'.tr()}: ${repliedPost!.publisher.nick}',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
if (forwardedPost != null)
|
||||||
|
Container(
|
||||||
|
padding: const EdgeInsets.symmetric(horizontal: 16, vertical: 8),
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.surfaceVariant.withOpacity(0.5),
|
||||||
|
child: Row(
|
||||||
|
children: [
|
||||||
|
const Icon(Symbols.forward, size: 16),
|
||||||
|
const Gap(8),
|
||||||
|
Expanded(
|
||||||
|
child: Text(
|
||||||
|
'${'forward'.tr()}: ${forwardedPost!.publisher.nick}',
|
||||||
|
style: Theme.of(context).textTheme.bodySmall,
|
||||||
|
maxLines: 1,
|
||||||
|
overflow: TextOverflow.ellipsis,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Row(
|
child: Row(
|
||||||
spacing: 12,
|
spacing: 12,
|
||||||
@@ -291,7 +441,7 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
children: [
|
children: [
|
||||||
GestureDetector(
|
GestureDetector(
|
||||||
child: ProfilePictureWidget(
|
child: ProfilePictureWidget(
|
||||||
fileId: currentPublisher.value?.pictureId,
|
fileId: currentPublisher.value?.picture?.id,
|
||||||
radius: 20,
|
radius: 20,
|
||||||
fallbackIcon:
|
fallbackIcon:
|
||||||
currentPublisher.value == null
|
currentPublisher.value == null
|
||||||
@@ -312,11 +462,56 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
child: SingleChildScrollView(
|
child: SingleChildScrollView(
|
||||||
padding: EdgeInsets.symmetric(vertical: 16),
|
padding: EdgeInsets.symmetric(vertical: 16),
|
||||||
child: Column(
|
child: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
children: [
|
children: [
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
OutlinedButton(
|
||||||
|
onPressed: () {
|
||||||
|
showVisibilityModal();
|
||||||
|
},
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(20),
|
||||||
|
),
|
||||||
|
side: BorderSide(
|
||||||
|
color: Theme.of(
|
||||||
|
context,
|
||||||
|
).colorScheme.primary.withOpacity(0.5),
|
||||||
|
),
|
||||||
|
padding: EdgeInsets.symmetric(horizontal: 16),
|
||||||
|
visualDensity: const VisualDensity(
|
||||||
|
vertical: -2,
|
||||||
|
horizontal: -4,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
child: Row(
|
||||||
|
mainAxisSize: MainAxisSize.min,
|
||||||
|
children: [
|
||||||
|
Icon(
|
||||||
|
getVisibilityIcon(visibility.value),
|
||||||
|
size: 16,
|
||||||
|
color:
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
const SizedBox(width: 6),
|
||||||
|
Text(
|
||||||
|
getVisibilityText(visibility.value).tr(),
|
||||||
|
style: TextStyle(
|
||||||
|
fontSize: 14,
|
||||||
|
color:
|
||||||
|
Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
).padding(bottom: 6),
|
||||||
TextField(
|
TextField(
|
||||||
controller: titleController,
|
controller: titleController,
|
||||||
decoration: InputDecoration.collapsed(
|
decoration: InputDecoration.collapsed(
|
||||||
hintText: 'Title',
|
hintText: 'postTitle'.tr(),
|
||||||
),
|
),
|
||||||
style: TextStyle(fontSize: 16),
|
style: TextStyle(fontSize: 16),
|
||||||
onTapOutside:
|
onTapOutside:
|
||||||
@@ -326,7 +521,7 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
TextField(
|
TextField(
|
||||||
controller: descriptionController,
|
controller: descriptionController,
|
||||||
decoration: InputDecoration.collapsed(
|
decoration: InputDecoration.collapsed(
|
||||||
hintText: 'Description',
|
hintText: 'postDescription'.tr(),
|
||||||
),
|
),
|
||||||
style: TextStyle(fontSize: 16),
|
style: TextStyle(fontSize: 16),
|
||||||
onTapOutside:
|
onTapOutside:
|
||||||
@@ -336,7 +531,7 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
const Gap(8),
|
const Gap(8),
|
||||||
RawKeyboardListener(
|
RawKeyboardListener(
|
||||||
focusNode: FocusNode(),
|
focusNode: FocusNode(),
|
||||||
onKey: _handleKeyPress,
|
onKey: handleKeyPress,
|
||||||
child: TextField(
|
child: TextField(
|
||||||
controller: contentController,
|
controller: contentController,
|
||||||
style: TextStyle(fontSize: 14),
|
style: TextStyle(fontSize: 14),
|
||||||
@@ -345,6 +540,7 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
hintText: 'postPlaceholder'.tr(),
|
hintText: 'postPlaceholder'.tr(),
|
||||||
isDense: true,
|
isDense: true,
|
||||||
),
|
),
|
||||||
|
maxLines: null,
|
||||||
onTapOutside:
|
onTapOutside:
|
||||||
(_) =>
|
(_) =>
|
||||||
FocusManager.instance.primaryFocus
|
FocusManager.instance.primaryFocus
|
||||||
@@ -352,34 +548,81 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
),
|
),
|
||||||
const Gap(8),
|
const Gap(8),
|
||||||
Column(
|
LayoutBuilder(
|
||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
builder: (context, constraints) {
|
||||||
spacing: 8,
|
final isWide = isWideScreen(context);
|
||||||
children: [
|
return isWide
|
||||||
for (
|
? Wrap(
|
||||||
var idx = 0;
|
spacing: 8,
|
||||||
idx < attachments.value.length;
|
runSpacing: 8,
|
||||||
idx++
|
children: [
|
||||||
)
|
for (
|
||||||
AttachmentPreview(
|
var idx = 0;
|
||||||
item: attachments.value[idx],
|
idx < attachments.value.length;
|
||||||
progress: attachmentProgress.value[idx],
|
idx++
|
||||||
onRequestUpload: () => uploadAttachment(idx),
|
)
|
||||||
onDelete: () => deleteAttachment(idx),
|
SizedBox(
|
||||||
onMove: (delta) {
|
width: constraints.maxWidth / 2 - 4,
|
||||||
if (idx + delta < 0 ||
|
child: AttachmentPreview(
|
||||||
idx + delta >= attachments.value.length) {
|
item: attachments.value[idx],
|
||||||
return;
|
progress:
|
||||||
}
|
attachmentProgress.value[idx],
|
||||||
final clone = List.of(attachments.value);
|
onRequestUpload:
|
||||||
clone.insert(
|
() => uploadAttachment(idx),
|
||||||
idx + delta,
|
onDelete: () => deleteAttachment(idx),
|
||||||
clone.removeAt(idx),
|
onMove: (delta) {
|
||||||
);
|
if (idx + delta < 0 ||
|
||||||
attachments.value = clone;
|
idx + delta >=
|
||||||
},
|
attachments.value.length) {
|
||||||
),
|
return;
|
||||||
],
|
}
|
||||||
|
final clone = List.of(
|
||||||
|
attachments.value,
|
||||||
|
);
|
||||||
|
clone.insert(
|
||||||
|
idx + delta,
|
||||||
|
clone.removeAt(idx),
|
||||||
|
);
|
||||||
|
attachments.value = clone;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
|
)
|
||||||
|
: Column(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
|
spacing: 8,
|
||||||
|
children: [
|
||||||
|
for (
|
||||||
|
var idx = 0;
|
||||||
|
idx < attachments.value.length;
|
||||||
|
idx++
|
||||||
|
)
|
||||||
|
AttachmentPreview(
|
||||||
|
item: attachments.value[idx],
|
||||||
|
progress: attachmentProgress.value[idx],
|
||||||
|
onRequestUpload:
|
||||||
|
() => uploadAttachment(idx),
|
||||||
|
onDelete: () => deleteAttachment(idx),
|
||||||
|
onMove: (delta) {
|
||||||
|
if (idx + delta < 0 ||
|
||||||
|
idx + delta >=
|
||||||
|
attachments.value.length) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
final clone = List.of(
|
||||||
|
attachments.value,
|
||||||
|
);
|
||||||
|
clone.insert(
|
||||||
|
idx + delta,
|
||||||
|
clone.removeAt(idx),
|
||||||
|
);
|
||||||
|
attachments.value = clone;
|
||||||
|
},
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@@ -414,204 +657,3 @@ class PostComposeScreen extends HookConsumerWidget {
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class AttachmentPreview extends StatelessWidget {
|
|
||||||
final UniversalFile item;
|
|
||||||
final double? progress;
|
|
||||||
final Function(int)? onMove;
|
|
||||||
final Function? onDelete;
|
|
||||||
final Function? onRequestUpload;
|
|
||||||
const AttachmentPreview({
|
|
||||||
super.key,
|
|
||||||
required this.item,
|
|
||||||
this.progress,
|
|
||||||
this.onRequestUpload,
|
|
||||||
this.onMove,
|
|
||||||
this.onDelete,
|
|
||||||
});
|
|
||||||
|
|
||||||
@override
|
|
||||||
Widget build(BuildContext context) {
|
|
||||||
return AspectRatio(
|
|
||||||
aspectRatio:
|
|
||||||
(item.isOnCloud ? (item.data.fileMeta?['ratio'] ?? 1) : 1).toDouble(),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: Stack(
|
|
||||||
fit: StackFit.expand,
|
|
||||||
children: [
|
|
||||||
Container(
|
|
||||||
color: Theme.of(context).colorScheme.surfaceContainerHigh,
|
|
||||||
child: Builder(
|
|
||||||
builder: (context) {
|
|
||||||
if (item.isOnCloud) {
|
|
||||||
return CloudFileWidget(item: item.data);
|
|
||||||
} else if (item.data is XFile) {
|
|
||||||
if (item.type == UniversalFileType.image) {
|
|
||||||
return Image.file(File(item.data.path));
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: Text(
|
|
||||||
'Preview is not supported for ${item.type}',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
} else if (item is List<int> || item is Uint8List) {
|
|
||||||
if (item.type == UniversalFileType.image) {
|
|
||||||
return Image.memory(item.data);
|
|
||||||
} else {
|
|
||||||
return Center(
|
|
||||||
child: Text(
|
|
||||||
'Preview is not supported for ${item.type}',
|
|
||||||
textAlign: TextAlign.center,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Placeholder();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (progress != null)
|
|
||||||
Positioned.fill(
|
|
||||||
child: Container(
|
|
||||||
color: Colors.black.withOpacity(0.3),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 40, vertical: 16),
|
|
||||||
child: Column(
|
|
||||||
mainAxisAlignment: MainAxisAlignment.center,
|
|
||||||
crossAxisAlignment: CrossAxisAlignment.center,
|
|
||||||
children: [
|
|
||||||
if (progress != null)
|
|
||||||
Text(
|
|
||||||
'${progress!.toStringAsFixed(2)}%',
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
)
|
|
||||||
else
|
|
||||||
Text(
|
|
||||||
'uploading'.tr(),
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
Gap(6),
|
|
||||||
Center(child: LinearProgressIndicator(value: progress)),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
Positioned(
|
|
||||||
left: 8,
|
|
||||||
top: 8,
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: Container(
|
|
||||||
color: Colors.black.withOpacity(0.5),
|
|
||||||
child: Material(
|
|
||||||
color: Colors.transparent,
|
|
||||||
child: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
if (onDelete != null)
|
|
||||||
InkWell(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: const Icon(
|
|
||||||
Symbols.delete,
|
|
||||||
size: 14,
|
|
||||||
color: Colors.white,
|
|
||||||
).padding(horizontal: 8, vertical: 6),
|
|
||||||
onTap: () {
|
|
||||||
onDelete?.call();
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (onDelete != null && onMove != null)
|
|
||||||
SizedBox(
|
|
||||||
height: 26,
|
|
||||||
child: const VerticalDivider(
|
|
||||||
width: 0.3,
|
|
||||||
color: Colors.white,
|
|
||||||
thickness: 0.3,
|
|
||||||
),
|
|
||||||
).padding(horizontal: 2),
|
|
||||||
if (onMove != null)
|
|
||||||
InkWell(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: const Icon(
|
|
||||||
Symbols.keyboard_arrow_up,
|
|
||||||
size: 14,
|
|
||||||
color: Colors.white,
|
|
||||||
).padding(horizontal: 8, vertical: 6),
|
|
||||||
onTap: () {
|
|
||||||
onMove?.call(-1);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
if (onMove != null)
|
|
||||||
InkWell(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: const Icon(
|
|
||||||
Symbols.keyboard_arrow_down,
|
|
||||||
size: 14,
|
|
||||||
color: Colors.white,
|
|
||||||
).padding(horizontal: 8, vertical: 6),
|
|
||||||
onTap: () {
|
|
||||||
onMove?.call(1);
|
|
||||||
},
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
if (onRequestUpload != null)
|
|
||||||
Positioned(
|
|
||||||
top: 8,
|
|
||||||
right: 8,
|
|
||||||
child: InkWell(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
onTap: () => onRequestUpload?.call(),
|
|
||||||
child: ClipRRect(
|
|
||||||
borderRadius: BorderRadius.circular(8),
|
|
||||||
child: Container(
|
|
||||||
color: Colors.black.withOpacity(0.5),
|
|
||||||
padding: EdgeInsets.symmetric(horizontal: 8, vertical: 4),
|
|
||||||
child:
|
|
||||||
(item.isOnCloud)
|
|
||||||
? Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Symbols.cloud,
|
|
||||||
size: 16,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
Text(
|
|
||||||
'On-cloud',
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
)
|
|
||||||
: Row(
|
|
||||||
mainAxisSize: MainAxisSize.min,
|
|
||||||
children: [
|
|
||||||
Icon(
|
|
||||||
Symbols.cloud_off,
|
|
||||||
size: 16,
|
|
||||||
color: Colors.white,
|
|
||||||
),
|
|
||||||
const Gap(8),
|
|
||||||
Text(
|
|
||||||
'On-device',
|
|
||||||
style: TextStyle(color: Colors.white),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
),
|
|
||||||
],
|
|
||||||
),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -64,7 +64,12 @@ class PostDetailScreen extends HookConsumerWidget {
|
|||||||
child: Material(
|
child: Material(
|
||||||
elevation: 2,
|
elevation: 2,
|
||||||
color: Colors.transparent,
|
color: Colors.transparent,
|
||||||
child: PostQuickReply(parent: post).padding(
|
child: PostQuickReply(
|
||||||
|
parent: post,
|
||||||
|
onPosted: () {
|
||||||
|
ref.invalidate(postRepliesNotifierProvider(id));
|
||||||
|
},
|
||||||
|
).padding(
|
||||||
bottom: MediaQuery.of(context).padding.bottom + 16,
|
bottom: MediaQuery.of(context).padding.bottom + 16,
|
||||||
top: 16,
|
top: 16,
|
||||||
horizontal: 16,
|
horizontal: 16,
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import 'package:auto_route/annotations.dart';
|
import 'package:auto_route/auto_route.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart';
|
import 'package:easy_localization/easy_localization.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
import 'package:flutter/services.dart';
|
||||||
@@ -7,13 +7,16 @@ import 'package:gap/gap.dart';
|
|||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:island/models/post.dart';
|
import 'package:island/models/post.dart';
|
||||||
import 'package:island/models/user.dart';
|
import 'package:island/models/user.dart';
|
||||||
|
import 'package:island/pods/config.dart';
|
||||||
import 'package:island/pods/network.dart';
|
import 'package:island/pods/network.dart';
|
||||||
|
import 'package:island/services/color.dart';
|
||||||
import 'package:island/widgets/account/badge.dart';
|
import 'package:island/widgets/account/badge.dart';
|
||||||
import 'package:island/widgets/account/status.dart';
|
import 'package:island/widgets/account/status.dart';
|
||||||
import 'package:island/widgets/alert.dart';
|
import 'package:island/widgets/alert.dart';
|
||||||
import 'package:island/widgets/app_scaffold.dart';
|
import 'package:island/widgets/app_scaffold.dart';
|
||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:island/widgets/post/post_list.dart';
|
import 'package:island/widgets/post/post_list.dart';
|
||||||
|
import 'package:palette_generator/palette_generator.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
@@ -29,9 +32,9 @@ Future<SnPublisher> publisher(Ref ref, String uname) async {
|
|||||||
@riverpod
|
@riverpod
|
||||||
Future<List<SnAccountBadge>> publisherBadges(Ref ref, String pubName) async {
|
Future<List<SnAccountBadge>> publisherBadges(Ref ref, String pubName) async {
|
||||||
final pub = await ref.watch(publisherProvider(pubName).future);
|
final pub = await ref.watch(publisherProvider(pubName).future);
|
||||||
if (pub.type != 0) return [];
|
if (pub.type != 0 || pub.account == null) return [];
|
||||||
final apiClient = ref.watch(apiClientProvider);
|
final apiClient = ref.watch(apiClientProvider);
|
||||||
final resp = await apiClient.get("/accounts/${pub.name}/badges");
|
final resp = await apiClient.get("/accounts/${pub.account!.name}/badges");
|
||||||
return List<SnAccountBadge>.from(
|
return List<SnAccountBadge>.from(
|
||||||
resp.data.map((x) => SnAccountBadge.fromJson(x)),
|
resp.data.map((x) => SnAccountBadge.fromJson(x)),
|
||||||
);
|
);
|
||||||
@@ -47,6 +50,21 @@ Future<SnSubscriptionStatus> publisherSubscriptionStatus(
|
|||||||
return SnSubscriptionStatus.fromJson(resp.data);
|
return SnSubscriptionStatus.fromJson(resp.data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
Future<Color?> publisherAppbarForcegroundColor(Ref ref, String pubName) async {
|
||||||
|
final publisher = await ref.watch(publisherProvider(pubName).future);
|
||||||
|
if (publisher.background == null) return null;
|
||||||
|
final palette = await PaletteGenerator.fromImageProvider(
|
||||||
|
CloudImageWidget.provider(
|
||||||
|
fileId: publisher.background!.id,
|
||||||
|
serverUrl: ref.watch(serverUrlProvider),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
final dominantColor = palette.dominantColor?.color;
|
||||||
|
if (dominantColor == null) return null;
|
||||||
|
return dominantColor.computeLuminance() > 0.5 ? Colors.black : Colors.white;
|
||||||
|
}
|
||||||
|
|
||||||
@RoutePage()
|
@RoutePage()
|
||||||
class PublisherProfileScreen extends HookConsumerWidget {
|
class PublisherProfileScreen extends HookConsumerWidget {
|
||||||
final String name;
|
final String name;
|
||||||
@@ -60,6 +78,9 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
final publisher = ref.watch(publisherProvider(name));
|
final publisher = ref.watch(publisherProvider(name));
|
||||||
final badges = ref.watch(publisherBadgesProvider(name));
|
final badges = ref.watch(publisherBadgesProvider(name));
|
||||||
final subStatus = ref.watch(publisherSubscriptionStatusProvider(name));
|
final subStatus = ref.watch(publisherSubscriptionStatusProvider(name));
|
||||||
|
final appbarColor = ref.watch(
|
||||||
|
publisherAppbarForcegroundColorProvider(name),
|
||||||
|
);
|
||||||
|
|
||||||
final subscribing = useState(false);
|
final subscribing = useState(false);
|
||||||
|
|
||||||
@@ -91,8 +112,8 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
final iconShadow = Shadow(
|
final appbarShadow = Shadow(
|
||||||
color: Colors.black54,
|
color: appbarColor.value?.invert ?? Colors.black54,
|
||||||
blurRadius: 5.0,
|
blurRadius: 5.0,
|
||||||
offset: Offset(1.0, 1.0),
|
offset: Offset(1.0, 1.0),
|
||||||
);
|
);
|
||||||
@@ -103,24 +124,40 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
body: CustomScrollView(
|
body: CustomScrollView(
|
||||||
slivers: [
|
slivers: [
|
||||||
SliverAppBar(
|
SliverAppBar(
|
||||||
|
foregroundColor: appbarColor.value,
|
||||||
expandedHeight: 180,
|
expandedHeight: 180,
|
||||||
pinned: true,
|
pinned: true,
|
||||||
leading: PageBackButton(shadows: [iconShadow]),
|
leading: PageBackButton(
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
color: appbarColor.value,
|
||||||
background:
|
shadows: [appbarShadow],
|
||||||
data.backgroundId != null
|
),
|
||||||
? CloudImageWidget(fileId: data.backgroundId!)
|
flexibleSpace: Stack(
|
||||||
: Container(
|
children: [
|
||||||
color:
|
Positioned.fill(
|
||||||
Theme.of(context).appBarTheme.backgroundColor,
|
child:
|
||||||
),
|
data.background?.id != null
|
||||||
title: Text(
|
? CloudImageWidget(file: data.background)
|
||||||
data.nick,
|
: Container(
|
||||||
style: TextStyle(
|
color:
|
||||||
color: Theme.of(context).appBarTheme.foregroundColor,
|
Theme.of(
|
||||||
shadows: [iconShadow],
|
context,
|
||||||
|
).appBarTheme.backgroundColor,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
FlexibleSpaceBar(
|
||||||
|
title: Text(
|
||||||
|
data.nick,
|
||||||
|
style: TextStyle(
|
||||||
|
color:
|
||||||
|
appbarColor.value ??
|
||||||
|
Theme.of(context).appBarTheme.foregroundColor,
|
||||||
|
shadows: [appbarShadow],
|
||||||
|
),
|
||||||
|
),
|
||||||
|
background:
|
||||||
|
Container(), // Empty container since background is handled by Stack
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
actions: [
|
actions: [
|
||||||
subStatus.when(
|
subStatus.when(
|
||||||
@@ -136,10 +173,10 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
status.isSubscribed
|
status.isSubscribed
|
||||||
? Icons.remove_circle
|
? Icons.remove_circle
|
||||||
: Icons.add_circle,
|
: Icons.add_circle,
|
||||||
shadows: [iconShadow],
|
shadows: [appbarShadow],
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
error: (_, __) => const SizedBox(),
|
error: (_, _) => const SizedBox(),
|
||||||
loading:
|
loading:
|
||||||
() => const SizedBox(
|
() => const SizedBox(
|
||||||
width: 48,
|
width: 48,
|
||||||
@@ -163,7 +200,7 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
crossAxisAlignment: CrossAxisAlignment.start,
|
crossAxisAlignment: CrossAxisAlignment.start,
|
||||||
spacing: 20,
|
spacing: 20,
|
||||||
children: [
|
children: [
|
||||||
ProfilePictureWidget(fileId: data.pictureId!, radius: 32),
|
ProfilePictureWidget(file: data.picture, radius: 32),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: Column(
|
child: Column(
|
||||||
crossAxisAlignment: CrossAxisAlignment.stretch,
|
crossAxisAlignment: CrossAxisAlignment.stretch,
|
||||||
@@ -177,9 +214,29 @@ class PublisherProfileScreen extends HookConsumerWidget {
|
|||||||
).fontSize(14).opacity(0.85),
|
).fontSize(14).opacity(0.85),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
if (data.type == 0)
|
if (data.type == 0 && data.account != null)
|
||||||
|
InkWell(
|
||||||
|
onTap: () {
|
||||||
|
context.router.pushPath(
|
||||||
|
'/account/${data.account!.name}',
|
||||||
|
);
|
||||||
|
},
|
||||||
|
child: Row(
|
||||||
|
crossAxisAlignment: CrossAxisAlignment.center,
|
||||||
|
spacing: 4,
|
||||||
|
children: [
|
||||||
|
Text(
|
||||||
|
'publisherVisitAccountPage'.tr(
|
||||||
|
args: ['@${data.account!.name}'],
|
||||||
|
),
|
||||||
|
).fontSize(14),
|
||||||
|
Icon(Icons.launch, size: 14),
|
||||||
|
],
|
||||||
|
).opacity(0.85),
|
||||||
|
).padding(bottom: 6),
|
||||||
|
if (data.type == 0 && data.account != null)
|
||||||
AccountStatusWidget(
|
AccountStatusWidget(
|
||||||
uname: name,
|
uname: data.account!.name,
|
||||||
padding: EdgeInsets.zero,
|
padding: EdgeInsets.zero,
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
|
|||||||
@@ -145,7 +145,7 @@ class _PublisherProviderElement
|
|||||||
String get uname => (origin as PublisherProvider).uname;
|
String get uname => (origin as PublisherProvider).uname;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _$publisherBadgesHash() => r'b26d8804ddc9734c453bdf76af0a9336f166542c';
|
String _$publisherBadgesHash() => r'a5781deded7e682a781ccd7854418f050438e3f4';
|
||||||
|
|
||||||
/// See also [publisherBadges].
|
/// See also [publisherBadges].
|
||||||
@ProviderFor(publisherBadges)
|
@ProviderFor(publisherBadges)
|
||||||
@@ -399,5 +399,136 @@ class _PublisherSubscriptionStatusProviderElement
|
|||||||
String get pubName => (origin as PublisherSubscriptionStatusProvider).pubName;
|
String get pubName => (origin as PublisherSubscriptionStatusProvider).pubName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
String _$publisherAppbarForcegroundColorHash() =>
|
||||||
|
r'3ff2eebb48d3f3af1907052f471e648f5b14b13c';
|
||||||
|
|
||||||
|
/// See also [publisherAppbarForcegroundColor].
|
||||||
|
@ProviderFor(publisherAppbarForcegroundColor)
|
||||||
|
const publisherAppbarForcegroundColorProvider =
|
||||||
|
PublisherAppbarForcegroundColorFamily();
|
||||||
|
|
||||||
|
/// See also [publisherAppbarForcegroundColor].
|
||||||
|
class PublisherAppbarForcegroundColorFamily extends Family<AsyncValue<Color?>> {
|
||||||
|
/// See also [publisherAppbarForcegroundColor].
|
||||||
|
const PublisherAppbarForcegroundColorFamily();
|
||||||
|
|
||||||
|
/// See also [publisherAppbarForcegroundColor].
|
||||||
|
PublisherAppbarForcegroundColorProvider call(String pubName) {
|
||||||
|
return PublisherAppbarForcegroundColorProvider(pubName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
PublisherAppbarForcegroundColorProvider getProviderOverride(
|
||||||
|
covariant PublisherAppbarForcegroundColorProvider provider,
|
||||||
|
) {
|
||||||
|
return call(provider.pubName);
|
||||||
|
}
|
||||||
|
|
||||||
|
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'publisherAppbarForcegroundColorProvider';
|
||||||
|
}
|
||||||
|
|
||||||
|
/// See also [publisherAppbarForcegroundColor].
|
||||||
|
class PublisherAppbarForcegroundColorProvider
|
||||||
|
extends AutoDisposeFutureProvider<Color?> {
|
||||||
|
/// See also [publisherAppbarForcegroundColor].
|
||||||
|
PublisherAppbarForcegroundColorProvider(String pubName)
|
||||||
|
: this._internal(
|
||||||
|
(ref) => publisherAppbarForcegroundColor(
|
||||||
|
ref as PublisherAppbarForcegroundColorRef,
|
||||||
|
pubName,
|
||||||
|
),
|
||||||
|
from: publisherAppbarForcegroundColorProvider,
|
||||||
|
name: r'publisherAppbarForcegroundColorProvider',
|
||||||
|
debugGetCreateSourceHash:
|
||||||
|
const bool.fromEnvironment('dart.vm.product')
|
||||||
|
? null
|
||||||
|
: _$publisherAppbarForcegroundColorHash,
|
||||||
|
dependencies: PublisherAppbarForcegroundColorFamily._dependencies,
|
||||||
|
allTransitiveDependencies:
|
||||||
|
PublisherAppbarForcegroundColorFamily._allTransitiveDependencies,
|
||||||
|
pubName: pubName,
|
||||||
|
);
|
||||||
|
|
||||||
|
PublisherAppbarForcegroundColorProvider._internal(
|
||||||
|
super._createNotifier, {
|
||||||
|
required super.name,
|
||||||
|
required super.dependencies,
|
||||||
|
required super.allTransitiveDependencies,
|
||||||
|
required super.debugGetCreateSourceHash,
|
||||||
|
required super.from,
|
||||||
|
required this.pubName,
|
||||||
|
}) : super.internal();
|
||||||
|
|
||||||
|
final String pubName;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Override overrideWith(
|
||||||
|
FutureOr<Color?> Function(PublisherAppbarForcegroundColorRef provider)
|
||||||
|
create,
|
||||||
|
) {
|
||||||
|
return ProviderOverride(
|
||||||
|
origin: this,
|
||||||
|
override: PublisherAppbarForcegroundColorProvider._internal(
|
||||||
|
(ref) => create(ref as PublisherAppbarForcegroundColorRef),
|
||||||
|
from: from,
|
||||||
|
name: null,
|
||||||
|
dependencies: null,
|
||||||
|
allTransitiveDependencies: null,
|
||||||
|
debugGetCreateSourceHash: null,
|
||||||
|
pubName: pubName,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
AutoDisposeFutureProviderElement<Color?> createElement() {
|
||||||
|
return _PublisherAppbarForcegroundColorProviderElement(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return other is PublisherAppbarForcegroundColorProvider &&
|
||||||
|
other.pubName == pubName;
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
int get hashCode {
|
||||||
|
var hash = _SystemHash.combine(0, runtimeType.hashCode);
|
||||||
|
hash = _SystemHash.combine(hash, pubName.hashCode);
|
||||||
|
|
||||||
|
return _SystemHash.finish(hash);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Deprecated('Will be removed in 3.0. Use Ref instead')
|
||||||
|
// ignore: unused_element
|
||||||
|
mixin PublisherAppbarForcegroundColorRef
|
||||||
|
on AutoDisposeFutureProviderRef<Color?> {
|
||||||
|
/// The parameter `pubName` of this provider.
|
||||||
|
String get pubName;
|
||||||
|
}
|
||||||
|
|
||||||
|
class _PublisherAppbarForcegroundColorProviderElement
|
||||||
|
extends AutoDisposeFutureProviderElement<Color?>
|
||||||
|
with PublisherAppbarForcegroundColorRef {
|
||||||
|
_PublisherAppbarForcegroundColorProviderElement(super.provider);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String get pubName =>
|
||||||
|
(origin as PublisherAppbarForcegroundColorProvider).pubName;
|
||||||
|
}
|
||||||
|
|
||||||
// ignore_for_file: type=lint
|
// ignore_for_file: type=lint
|
||||||
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
// ignore_for_file: subtype_of_sealed_class, invalid_use_of_internal_member, invalid_use_of_visible_for_testing_member, deprecated_member_use_from_same_package
|
||||||
|
|||||||
@@ -15,6 +15,7 @@ import 'package:island/widgets/app_scaffold.dart';
|
|||||||
import 'package:island/widgets/content/cloud_files.dart';
|
import 'package:island/widgets/content/cloud_files.dart';
|
||||||
import 'package:material_symbols_icons/symbols.dart';
|
import 'package:material_symbols_icons/symbols.dart';
|
||||||
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
import 'package:riverpod_annotation/riverpod_annotation.dart';
|
||||||
|
import 'package:riverpod_paging_utils/riverpod_paging_utils.dart';
|
||||||
import 'package:styled_widget/styled_widget.dart';
|
import 'package:styled_widget/styled_widget.dart';
|
||||||
|
|
||||||
part 'detail.g.dart';
|
part 'detail.g.dart';
|
||||||
@@ -54,8 +55,8 @@ class RealmDetailScreen extends HookConsumerWidget {
|
|||||||
leading: PageBackButton(shadows: [iconShadow]),
|
leading: PageBackButton(shadows: [iconShadow]),
|
||||||
flexibleSpace: FlexibleSpaceBar(
|
flexibleSpace: FlexibleSpaceBar(
|
||||||
background:
|
background:
|
||||||
realm!.backgroundId != null
|
realm!.background?.id != null
|
||||||
? CloudImageWidget(fileId: realm.backgroundId!)
|
? CloudImageWidget(fileId: realm.background!.id)
|
||||||
: Container(
|
: Container(
|
||||||
color:
|
color:
|
||||||
Theme.of(context).appBarTheme.backgroundColor,
|
Theme.of(context).appBarTheme.backgroundColor,
|
||||||
@@ -118,7 +119,7 @@ class _RealmActionMenu extends HookConsumerWidget {
|
|||||||
final isModerator = realmIdentityAsync.when(
|
final isModerator = realmIdentityAsync.when(
|
||||||
data: (identity) => (identity?.role ?? 0) >= 50,
|
data: (identity) => (identity?.role ?? 0) >= 50,
|
||||||
loading: () => false,
|
loading: () => false,
|
||||||
error: (_, __) => false,
|
error: (_, _) => false,
|
||||||
);
|
);
|
||||||
|
|
||||||
return PopupMenuButton(
|
return PopupMenuButton(
|
||||||
@@ -212,7 +213,7 @@ class _RealmActionMenu extends HookConsumerWidget {
|
|||||||
child: Center(child: CircularProgressIndicator()),
|
child: Center(child: CircularProgressIndicator()),
|
||||||
),
|
),
|
||||||
error:
|
error:
|
||||||
(_, __) => PopupMenuItem(
|
(_, _) => PopupMenuItem(
|
||||||
child: Row(
|
child: Row(
|
||||||
children: [
|
children: [
|
||||||
Icon(
|
Icon(
|
||||||
@@ -250,6 +251,42 @@ class _RealmActionMenu extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@riverpod
|
||||||
|
class RealmMemberListNotifier extends _$RealmMemberListNotifier
|
||||||
|
with CursorPagingNotifierMixin<SnRealmMember> {
|
||||||
|
static const int _pageSize = 20;
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<CursorPagingData<SnRealmMember>> build(String realmSlug) async {
|
||||||
|
return fetch();
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
Future<CursorPagingData<SnRealmMember>> fetch({String? cursor}) async {
|
||||||
|
final apiClient = ref.read(apiClientProvider);
|
||||||
|
final offset = cursor != null ? int.parse(cursor) : 0;
|
||||||
|
|
||||||
|
final response = await apiClient.get(
|
||||||
|
'/realms/$realmSlug/members',
|
||||||
|
queryParameters: {'offset': offset, 'take': _pageSize},
|
||||||
|
);
|
||||||
|
|
||||||
|
final total = int.parse(response.headers.value('X-Total') ?? '0');
|
||||||
|
final List<dynamic> data = response.data;
|
||||||
|
final members = data.map((e) => SnRealmMember.fromJson(e)).toList();
|
||||||
|
|
||||||
|
final hasMore = offset + members.length < total;
|
||||||
|
final nextCursor = hasMore ? (offset + members.length).toString() : null;
|
||||||
|
|
||||||
|
return CursorPagingData(
|
||||||
|
items: members,
|
||||||
|
hasMore: hasMore,
|
||||||
|
nextCursor: nextCursor,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Keep the old provider for backward compatibility
|
||||||
final realmMemberStateProvider =
|
final realmMemberStateProvider =
|
||||||
StateNotifierProvider.family<RealmMemberNotifier, RealmMemberState, String>(
|
StateNotifierProvider.family<RealmMemberNotifier, RealmMemberState, String>(
|
||||||
(ref, realmSlug) {
|
(ref, realmSlug) {
|
||||||
@@ -302,13 +339,15 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
|
final realmIdentity = ref.watch(realmIdentityProvider(realmSlug));
|
||||||
|
final memberListProvider = realmMemberListNotifierProvider(realmSlug);
|
||||||
|
|
||||||
|
// For backward compatibility and to show total count in the header
|
||||||
final memberState = ref.watch(realmMemberStateProvider(realmSlug));
|
final memberState = ref.watch(realmMemberStateProvider(realmSlug));
|
||||||
final memberNotifier = ref.read(
|
final memberNotifier = ref.read(
|
||||||
realmMemberStateProvider(realmSlug).notifier,
|
realmMemberStateProvider(realmSlug).notifier,
|
||||||
);
|
);
|
||||||
|
|
||||||
final realmIdentity = ref.watch(realmIdentityProvider(realmSlug));
|
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
Future(() {
|
Future(() {
|
||||||
memberNotifier.loadMore();
|
memberNotifier.loadMore();
|
||||||
@@ -329,8 +368,10 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
'/realms/invites/$realmSlug',
|
'/realms/invites/$realmSlug',
|
||||||
data: {'related_user_id': result.id, 'role': 0},
|
data: {'related_user_id': result.id, 'role': 0},
|
||||||
);
|
);
|
||||||
|
// Refresh both providers
|
||||||
memberNotifier.reset();
|
memberNotifier.reset();
|
||||||
await memberNotifier.loadMore();
|
await memberNotifier.loadMore();
|
||||||
|
ref.invalidate(memberListProvider);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
}
|
}
|
||||||
@@ -362,8 +403,10 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.refresh),
|
icon: const Icon(Symbols.refresh),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
|
// Refresh both providers
|
||||||
memberNotifier.reset();
|
memberNotifier.reset();
|
||||||
memberNotifier.loadMore();
|
memberNotifier.loadMore();
|
||||||
|
ref.invalidate(memberListProvider);
|
||||||
},
|
},
|
||||||
),
|
),
|
||||||
IconButton(
|
IconButton(
|
||||||
@@ -376,108 +419,103 @@ class _RealmMemberListSheet extends HookConsumerWidget {
|
|||||||
),
|
),
|
||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
Expanded(
|
Expanded(
|
||||||
child:
|
child: PagingHelperView(
|
||||||
memberState.error != null
|
provider: memberListProvider,
|
||||||
? Center(child: Text(memberState.error!))
|
futureRefreshable: memberListProvider.future,
|
||||||
: ListView.builder(
|
notifierRefreshable: memberListProvider.notifier,
|
||||||
itemCount: memberState.members.length + 1,
|
contentBuilder: (data, widgetCount, endItemView) {
|
||||||
itemBuilder: (context, index) {
|
return ListView.builder(
|
||||||
if (index == memberState.members.length) {
|
itemCount: widgetCount,
|
||||||
if (memberState.isLoading) {
|
itemBuilder: (context, index) {
|
||||||
return const Center(
|
if (index == data.items.length) {
|
||||||
child: Padding(
|
return endItemView;
|
||||||
padding: EdgeInsets.all(16.0),
|
}
|
||||||
child: CircularProgressIndicator(),
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
|
||||||
if (memberState.members.length < memberState.total) {
|
|
||||||
memberNotifier.loadMore(
|
|
||||||
offset: memberState.members.length,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
return const SizedBox.shrink();
|
|
||||||
}
|
|
||||||
|
|
||||||
final member = memberState.members[index];
|
final member = data.items[index];
|
||||||
return ListTile(
|
return ListTile(
|
||||||
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
contentPadding: EdgeInsets.only(left: 16, right: 12),
|
||||||
leading: ProfilePictureWidget(
|
leading: ProfilePictureWidget(
|
||||||
fileId: member.account!.profile.pictureId,
|
fileId: member.account!.profile.picture?.id,
|
||||||
),
|
),
|
||||||
title: Row(
|
title: Row(
|
||||||
spacing: 6,
|
spacing: 6,
|
||||||
children: [
|
children: [
|
||||||
Flexible(child: Text(member.account!.nick)),
|
Flexible(child: Text(member.account!.nick)),
|
||||||
if (member.joinedAt == null)
|
if (member.joinedAt == null)
|
||||||
const Icon(Symbols.pending_actions, size: 20),
|
const Icon(Symbols.pending_actions, size: 20),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
subtitle: Row(
|
subtitle: Row(
|
||||||
children: [
|
children: [
|
||||||
Text(
|
Text(
|
||||||
member.role >= 100
|
member.role >= 100
|
||||||
? 'permissionOwner'
|
? 'permissionOwner'
|
||||||
: member.role >= 50
|
: member.role >= 50
|
||||||
? 'permissionModerator'
|
? 'permissionModerator'
|
||||||
: 'permissionMember',
|
: 'permissionMember',
|
||||||
).tr(),
|
).tr(),
|
||||||
Text('·').bold().padding(horizontal: 6),
|
Text('·').bold().padding(horizontal: 6),
|
||||||
Expanded(child: Text("@${member.account!.name}")),
|
Expanded(child: Text("@${member.account!.name}")),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
trailing: Row(
|
trailing: Row(
|
||||||
mainAxisSize: MainAxisSize.min,
|
mainAxisSize: MainAxisSize.min,
|
||||||
children: [
|
children: [
|
||||||
if ((realmIdentity.value?.role ?? 0) >= 50)
|
if ((realmIdentity.value?.role ?? 0) >= 50)
|
||||||
IconButton(
|
IconButton(
|
||||||
icon: const Icon(Symbols.edit),
|
icon: const Icon(Symbols.edit),
|
||||||
onPressed: () {
|
onPressed: () {
|
||||||
showModalBottomSheet(
|
showModalBottomSheet(
|
||||||
isScrollControlled: true,
|
isScrollControlled: true,
|
||||||
context: context,
|
context: context,
|
||||||
builder:
|
builder:
|
||||||
(context) => _RealmMemberRoleSheet(
|
(context) => _RealmMemberRoleSheet(
|
||||||
realmSlug: realmSlug,
|
realmSlug: realmSlug,
|
||||||
member: member,
|
member: member,
|
||||||
),
|
),
|
||||||
).then((value) {
|
).then((value) {
|
||||||
if (value != null) {
|
if (value != null) {
|
||||||
memberNotifier.reset();
|
// Refresh both providers
|
||||||
memberNotifier.loadMore();
|
memberNotifier.reset();
|
||||||
}
|
memberNotifier.loadMore();
|
||||||
});
|
ref.invalidate(memberListProvider);
|
||||||
},
|
}
|
||||||
),
|
});
|
||||||
if ((realmIdentity.value?.role ?? 0) >= 50)
|
},
|
||||||
IconButton(
|
),
|
||||||
icon: const Icon(Symbols.delete),
|
if ((realmIdentity.value?.role ?? 0) >= 50)
|
||||||
onPressed: () {
|
IconButton(
|
||||||
showConfirmAlert(
|
icon: const Icon(Symbols.delete),
|
||||||
'removeRealmMemberHint'.tr(),
|
onPressed: () {
|
||||||
'removeRealmMember'.tr(),
|
showConfirmAlert(
|
||||||
).then((confirm) async {
|
'removeRealmMemberHint'.tr(),
|
||||||
if (confirm != true) return;
|
'removeRealmMember'.tr(),
|
||||||
try {
|
).then((confirm) async {
|
||||||
final apiClient = ref.watch(
|
if (confirm != true) return;
|
||||||
apiClientProvider,
|
try {
|
||||||
);
|
final apiClient = ref.watch(
|
||||||
await apiClient.delete(
|
apiClientProvider,
|
||||||
'/realms/$realmSlug/members/${member.accountId}',
|
);
|
||||||
);
|
await apiClient.delete(
|
||||||
memberNotifier.reset();
|
'/realms/$realmSlug/members/${member.accountId}',
|
||||||
memberNotifier.loadMore();
|
);
|
||||||
} catch (err) {
|
// Refresh both providers
|
||||||
showErrorAlert(err);
|
memberNotifier.reset();
|
||||||
}
|
memberNotifier.loadMore();
|
||||||
});
|
ref.invalidate(memberListProvider);
|
||||||
},
|
} catch (err) {
|
||||||
),
|
showErrorAlert(err);
|
||||||
],
|
}
|
||||||
),
|
});
|
||||||
);
|
},
|
||||||
},
|
),
|
||||||
),
|
],
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user