Compare commits
483 Commits
3.2.0+125
...
983ae2a1fc
| Author | SHA1 | Date | |
|---|---|---|---|
|
983ae2a1fc
|
|||
|
6fc94001b3
|
|||
|
44dbcfdc94
|
|||
|
b57caf56db
|
|||
|
dbcd1b6d36
|
|||
|
a8055de910
|
|||
|
49b15e7674
|
|||
|
e2369c40db
|
|||
|
44c5d91620
|
|||
|
7a5a2407b7
|
|||
|
234434f102
|
|||
|
9c3b228d02
|
|||
|
82682cae9a
|
|||
|
fcbd5fe680
|
|||
|
ad91b17af7
|
|||
|
24fa637329
|
|||
|
926ae5402f
|
|||
|
1a37d384e6
|
|||
|
d4cf598f69
|
|||
|
0106c08891
|
|||
|
9697def808
|
|||
|
6572875229
|
|||
|
66590b9079
|
|||
|
08b9604b55
|
|||
|
0602bbd277
|
|||
|
76e7ba7898
|
|||
|
6e6616b236
|
|||
|
071d51b25e
|
|||
|
a958362461
|
|||
|
6749bb00fe
|
|||
|
11fb20c673
|
|||
|
a7990f83db
|
|||
|
5f4cdf7937
|
|||
|
3330ca14dd
|
|||
|
1719b1c8fe
|
|||
|
3c2c51bfaf
|
|||
|
239d6750ff
|
|||
|
8b0c91977a
|
|||
|
f74cca8464
|
|||
|
08091d51bf
|
|||
|
481190811b
|
|||
|
4b32b65d1c
|
|||
|
50ac7109bb
|
|||
|
62da279c71
|
|||
|
fde6dbf891
|
|||
|
613bf4fb42
|
|||
|
00ae586016
|
|||
|
ea0d132dce
|
|||
|
aa2df1e847
|
|||
|
50672795f3
|
|||
|
383de9568d
|
|||
|
01fa228e45
|
|||
|
1e71ad33a6
|
|||
|
92c0260ecd
|
|||
|
0a161ad255
|
|||
|
c003f27b9a
|
|||
|
19db8309c4
|
|||
|
aa72ce08e8
|
|||
|
4639b00b86
|
|||
|
cc5460ea55
|
|||
|
eafac811e6
|
|||
|
e3be691596
|
|||
|
aa180a1358
|
|||
|
c2707b8af1
|
|||
|
62fd0500f3
|
|||
|
eeae865cc8
|
|||
|
cdf1413fe0
|
|||
|
327b4c04f1
|
|||
|
bd903ce29c
|
|||
|
1b8ecb15ce
|
|||
|
d4e380a97a
|
|||
|
126048b4fa
|
|||
|
8bec18813d
|
|||
|
1ae81794b1
|
|||
|
2a7d12de48
|
|||
|
64c60ead48
|
|||
| 001549b190 | |||
| 4595865ad3 | |||
|
|
1834643167 | ||
|
|
0e816eaa3e | ||
|
|
7c1f24b824 | ||
|
c6594ea2ce
|
|||
|
3bec6e683e
|
|||
|
83e92e2eed
|
|||
|
|
b7d44d96ba | ||
|
a83b929d42
|
|||
|
9423affa75
|
|||
|
cda23db609
|
|||
|
61074bc5a3
|
|||
|
5feafa9255
|
|||
|
e604577c1f
|
|||
|
af0ddd1273
|
|||
|
8a6bb34808
|
|||
|
4ef8445c77
|
|||
|
ec39ad6ca3
|
|||
|
eabb3154f1
|
|||
|
910bf20eef
|
|||
|
5efa9b2ae8
|
|||
|
dd3e39e891
|
|||
|
b6896ded23
|
|||
|
f28a73ff9c
|
|||
|
a014b64235
|
|||
|
7e0e7c20d7
|
|||
|
389fa515ba
|
|||
|
681ead02eb
|
|||
|
8d1c145b0b
|
|||
|
51b4754182
|
|||
|
8a2b321701
|
|||
|
f685a7a249
|
|||
|
76009147e9
|
|||
|
ce12f28e56
|
|||
|
3604373a1e
|
|||
|
9704a4c2c7
|
|||
|
67def56ad1
|
|||
|
1be33916af
|
|||
|
e8ff1bfd22
|
|||
|
3ae56f3d89
|
|||
|
707143e998
|
|||
|
1fd34eb2a3
|
|||
|
d7ca41e946
|
|||
|
ad9fb0719a
|
|||
|
e2d315afd4
|
|||
|
6124dbfd79
|
|||
|
5327f04ec0
|
|||
|
41c56a2319
|
|||
|
f9d033542e
|
|||
|
91784e65e6
|
|||
|
9d39c6a825
|
|||
|
537e49f1a4
|
|||
|
75bbd4df71
|
|||
|
6ef4580d93
|
|||
|
6ffd498761
|
|||
|
27157e7cc1
|
|||
|
bbb07d574a
|
|||
|
c660a419e2
|
|||
|
c3f61467c8
|
|||
|
9bc47df452
|
|||
|
9ef8ca4d45
|
|||
|
b55cbd08d1
|
|||
|
8c6bd0feaa
|
|||
|
7dd4b20628
|
|||
|
fec0cb7640
|
|||
|
75deb04a2b
|
|||
|
7c7ed21a96
|
|||
|
a201f20793
|
|||
|
598c51bc1a
|
|||
|
e1ea61c5f1
|
|||
|
ac424bde36
|
|||
|
b43b70df3f
|
|||
|
4321aa621a
|
|||
|
d5d275fb43
|
|||
|
6bb3307144
|
|||
|
391604d4a2
|
|||
|
1d9361c12f
|
|||
|
a129b9cdd0
|
|||
|
3bf815ac61
|
|||
|
77bae4d6fd
|
|||
|
0a301c4c9b
|
|||
|
27b390a51c
|
|||
|
018386d14e
|
|||
|
3825d7c6c7
|
|||
|
bf930291e4
|
|||
|
a8c4988790
|
|||
|
28dd204b1a
|
|||
|
3cbc1a59a7
|
|||
|
277e9ae3d1
|
|||
|
27b3ca25b7
|
|||
|
f871cd3b62
|
|||
|
a8a59ee30c
|
|||
|
2cd1416a13
|
|||
|
6be7dfbc61
|
|||
|
1abbd85614
|
|||
|
31ac5ad07c
|
|||
|
ae2ba495e9
|
|||
|
637aa44548
|
|||
|
44dbfc36d9
|
|||
|
5dbe7371cb
|
|||
|
6c91093198
|
|||
|
3f640b7898
|
|||
|
7db164fda6
|
|||
|
6df1d96cc9
|
|||
|
122a796f8c
|
|||
|
fbc7812a16
|
|||
|
0b1a23e81a
|
|||
|
c87e6cfe07
|
|||
|
53d51b8a0e
|
|||
|
337ae39e08
|
|||
|
8fe3a664a6
|
|||
|
3bfc0b8181
|
|||
| ac2951479b | |||
| 2bfd13d843 | |||
| 28db6f9f01 | |||
|
a4f7b8415d
|
|||
|
2255d3d591
|
|||
|
97792ae734
|
|||
|
a5d13250cc
|
|||
|
de9e235d0c
|
|||
|
56fb5451cd
|
|||
|
870de961f5
|
|||
|
22bf6d1c33
|
|||
|
5b62f89531
|
|||
|
b1326d8f04
|
|||
|
fffca4a78c
|
|||
|
42bd7f97cb
|
|||
| 6377856ae0 | |||
| 0f1c52b9e3 | |||
| 6ed6f60fbc | |||
| e65a414065 | |||
| 214d5c4a53 | |||
| fe33931304 | |||
| 113309257e | |||
| b95a8b2ed2 | |||
|
|
e922971a5e | ||
| 9d5b71bead | |||
| 890efa2efb | |||
| 674097e425 | |||
|
3379dcb7f3
|
|||
| eb5a849e1f | |||
|
4981a23e8e
|
|||
|
c64d4bacb6
|
|||
|
838d18013b
|
|||
|
3f7902e463
|
|||
|
54560ad5d8
|
|||
|
0c729db639
|
|||
|
1fbaac8d88
|
|||
|
b9dc724f0b
|
|||
|
a2cc55696f
|
|||
|
e79f857feb
|
|||
|
affba29c04
|
|||
|
756746b144
|
|||
|
28b6eade48
|
|||
| 1de7ef8c96 | |||
| 67eac5dcf5 | |||
|
7a44bfa075
|
|||
|
1c2f25a152
|
|||
|
be26ea280e
|
|||
|
b4996d069f
|
|||
|
bf4892b34d
|
|||
|
5f84751fd5
|
|||
|
457d1bac60
|
|||
|
02ec11845b
|
|||
|
612f1bf004
|
|||
|
fd80b713ad
|
|||
|
508805368c
|
|||
|
98eb28a4ec
|
|||
|
d1a2f59dd1
|
|||
|
bb9adb963a
|
|||
|
83e40cd860
|
|||
|
c06fb12f6a
|
|||
|
6600cf4df8
|
|||
|
4293daaa2f
|
|||
|
866674ddde
|
|||
|
27d478ba4f
|
|||
|
cccade763f
|
|||
|
f760b85186
|
|||
|
e68c5f4f92
|
|||
|
b0f3b6b5c3
|
|||
|
cb2af379fa
|
|||
|
38f8103265
|
|||
|
06bb18bdaa
|
|||
|
84c38500d0
|
|||
|
9529bbf08b
|
|||
|
8baf77bcf7
|
|||
|
b2ac5fbef2
|
|||
|
c79b1d7aab
|
|||
|
|
4f55a8209c | ||
|
|
ace302111a | ||
|
|
1391fa0dde | ||
|
|
cbdc7acdcd | ||
|
|
b80d91825a | ||
|
|
1a703b7eba | ||
|
|
3621ea7744 | ||
|
|
b638343f02 | ||
|
|
269a64cabb | ||
|
406e5187a8
|
|||
|
9bdd08d8dd
|
|||
|
d737232dcf
|
|||
|
c9d751479e
|
|||
|
a2c2bfe585
|
|||
|
c7f9da0dee
|
|||
|
|
a243cda1df | ||
|
|
7b238f32fd | ||
|
313af28d7f
|
|||
|
c64e1e208c
|
|||
|
c9b07a9a2a
|
|||
| 55c0e355f1 | |||
| be414891ec | |||
| 787876ab6a | |||
|
8578cde620
|
|||
|
14d55d45a8
|
|||
|
724391584e
|
|||
| 3a5e45808a | |||
|
488055955c
|
|||
|
|
313ebc64cc | ||
|
|
1ed8b1d0c1 | ||
| 4af816d931 | |||
| 1c058a4323 | |||
| 461ed1fcda | |||
|
5363afa558
|
|||
|
f0d2737da8
|
|||
|
1f2f80aa3e
|
|||
|
240a872e65
|
|||
| c1ec6f0849 | |||
| ab42686d4d | |||
|
c9727e92b8
|
|||
|
9b8768061d
|
|||
|
0949f0da54
|
|||
|
215ca705ac
|
|||
|
03457af04a
|
|||
|
73c6a1febf
|
|||
|
ba8d30bcde
|
|||
|
8449658b47
|
|||
|
c7f417234e
|
|||
|
6c847ee1e1
|
|||
|
18ad4d376e
|
|||
|
c4d5ba5c9d
|
|||
|
1069669049
|
|||
|
aa648fec62
|
|||
|
541900673a
|
|||
|
265502ffd0
|
|||
|
3bd79350d1
|
|||
|
5294d1fb23
|
|||
|
ec1269dcf1
|
|||
|
edb0a25f34
|
|||
|
7cd10118cc
|
|||
|
fcddc8f345
|
|||
|
1cc34240da
|
|||
|
013f7f02bc
|
|||
|
4e79e4100f
|
|||
|
feda1f067f
|
|||
|
fe0e192a43
|
|||
|
93df294142
|
|||
|
78d65c39f3
|
|||
|
18b0dbd797
|
|||
|
80cc8cbb40
|
|||
|
646e95a9fc
|
|||
|
6f9d51673b
|
|||
|
f8c6887769
|
|||
|
cd2a507b7f
|
|||
|
3cafce00a2
|
|||
|
837f3fbe98
|
|||
|
ca7cc5d7ee
|
|||
|
ef2c14daa2
|
|||
|
3a17837cc6
|
|||
|
2617a64acf
|
|||
|
afe1e12a3b
|
|||
|
be80f5ff85
|
|||
|
3281d69eba
|
|||
|
77b6ce9937
|
|||
|
39275f61b5
|
|||
|
72193ba8f3
|
|||
|
98dd9b6617
|
|||
|
a22b94a263
|
|||
|
9c75eafdb3
|
|||
|
28fda3d0c7
|
|||
|
187c2ea43e
|
|||
|
ae7d967461
|
|||
|
1ce71f1fa1
|
|||
|
9b68808c77
|
|||
|
|
99b7bf8199 | ||
|
|
eb9bb73c31 | ||
|
|
a8c3830d67 | ||
|
|
07a5a19141 | ||
| ecc100ac45 | |||
| 573b76d3ff | |||
| f7dad5e419 | |||
| 9f2f1c0848 | |||
| 580d9fd979 | |||
| 3b375abc09 | |||
| c527b5e67c | |||
| e9f09bbe54 | |||
| 3aece9316c | |||
| a61c889c6c | |||
| 0dd3221a56 | |||
| 66918521f8 | |||
| bb1846e462 | |||
| a976a6eaf4 | |||
| 4252f66fd3 | |||
| f2d780b48f | |||
| 300541f9bb | |||
| 43787bb813 | |||
| 3417c51a3b | |||
| f98e603e82 | |||
| c9b71701c8 | |||
| 28e98488f1 | |||
| b4d476613e | |||
| b48a1aac44 | |||
| 596d212593 | |||
| 54f290327e | |||
| 16f248ceab | |||
| 856d811187 | |||
| d07b194c04 | |||
| 2554b58be6 | |||
| a627b5838e | |||
| c479a9f381 | |||
| 02057e663b | |||
| 6501594100 | |||
| c6599edc3d | |||
| 709a0620b6 | |||
| f9b2a96c7c | |||
| 4dca6189cb | |||
| c7f5b63fe5 | |||
| 96c2f45c85 | |||
| 06f04eb3a5 | |||
| 8af97e43b4 | |||
| d1e8234b93 | |||
| a03d6015a6 | |||
| 246ac52d0a | |||
| abf395ff9a | |||
| 4fdc8eb1d0 | |||
| d7dcde898c | |||
| f85484d3ed | |||
| 5060bd30c9 | |||
| 3959f2260b | |||
| 6f4f1216ad | |||
| f401ffbf81 | |||
| 0251697951 | |||
| 178c12b893 | |||
| 4beda9200e | |||
| 7dfe411053 | |||
| 1232318a5d | |||
|
|
56f41b6c0e | ||
|
|
3ea717d25a | ||
| 1fe4889460 | |||
| cdf2722268 | |||
| a127b5bace | |||
| b2097cf044 | |||
| 701f29748d | |||
| 9e40ed4600 | |||
| c90e6fe661 | |||
| 569483300d | |||
| bab602d98b | |||
| b4f2bb803a | |||
| 03bfed6f46 | |||
| f98e5a0aec | |||
| 3d473e2fec | |||
| 0b6efa373a | |||
| 9b60e96cde | |||
| 81cd9b2082 | |||
| 923d5d7514 | |||
| 7169aff841 | |||
| fac3efb50c | |||
| e809aadaea | |||
| f33b569221 | |||
| e5f2e2d146 | |||
| 11368d064f | |||
| 246b163aec | |||
| 10e0d2fe5f | |||
| 99e10cb612 | |||
| 1db6941431 | |||
| 8370da4fe3 | |||
| 2bdf7029e9 | |||
| 86682a3a9a | |||
| c3925e81b5 | |||
| 6f1f488490 | |||
| 31b2de2e46 | |||
| 412dcfa62a | |||
| ffdc7e81ae | |||
| 1d3357803d | |||
| 6c48aa2356 | |||
| 466e354679 | |||
| 5d4b896f70 | |||
| a04dffdfe8 | |||
| ff871943cf | |||
| 1a892ab227 | |||
| af1b303211 | |||
| 6fd702eba8 | |||
| d220d43cd2 | |||
| 6892afb974 | |||
| 007b46b080 | |||
| 67d130dc34 | |||
| 7e923c77fe | |||
| a593b52812 | |||
|
|
520dc80303 | ||
| 001897bbcd | |||
|
|
bab29c23e3 | ||
| 76b39f2df3 | |||
| 509b3e145b | |||
| 2b80ebc2d0 | |||
| 0ab908dd2a | |||
| 6007467e7a | |||
| 3745157c42 | |||
| 94481ec7bd |
@@ -14,13 +14,13 @@ The backend of the Solar Network is written in Go and is a microservices app. Th
|
|||||||
|
|
||||||
## Commit Messages
|
## Commit Messages
|
||||||
|
|
||||||
We're using the gitmoji to clarify the reason and changes of the commit. To learn more about gitmoji, visit https://gitmoji.dev
|
We're using the gitmoji to clarify the reason and changes of the commit. To learn more about gitmoji, visit <https://gitmoji.dev>
|
||||||
|
|
||||||
All the commit message should follow `:[gitmoji]: <commit message>` syntax
|
All the commit message should follow `:[gitmoji]: <commit message>` syntax
|
||||||
|
|
||||||
## Translations & Localization
|
## Translations & Localization
|
||||||
|
|
||||||
We're not accepting translation and localization improvements, or fixes on the GitHub or Solsynth Git Repository. If you want to contribute to those, please head to our Crowdin project: https://crowdin.com/project/solian
|
We're not accepting translation and localization improvements, or fixes on the GitHub or Solsynth Git Repository. If you want to contribute to those, please head to our Crowdin project: <https://crowdin.com/project/solian>
|
||||||
|
|
||||||
## New Features
|
## New Features
|
||||||
|
|
||||||
@@ -30,7 +30,12 @@ To contribute new features, please create an issue or mention the feature you wa
|
|||||||
|
|
||||||
Read the error message, check for the update (including pre-releases), and wiki before creating an issue. At the same time, be respectful and don't argue with our developers and contributors in the development chat or GitHub issue. Otherwise your issue may got deleted and your Solar Network Account may got a strike.
|
Read the error message, check for the update (including pre-releases), and wiki before creating an issue. At the same time, be respectful and don't argue with our developers and contributors in the development chat or GitHub issue. Otherwise your issue may got deleted and your Solar Network Account may got a strike.
|
||||||
|
|
||||||
|
## Styles of Code
|
||||||
|
|
||||||
|
Before you create a Pull Request, make sure your code has pass the `flutter analyze` check, if there is any notes, fix as much as possible, if there is no way to fix, do ignore.
|
||||||
|
|
||||||
|
When the code contains comments, use English. We do not any other language of comments existing in the codebase. It might confuse future contributors, cause the code hard to understand and maintaiance.
|
||||||
|
|
||||||
-----------
|
-----------
|
||||||
|
|
||||||
We appreciate every single commit you contributed. Let's work together and create a better Solar Network!
|
We appreciate every single commit you contributed. Let's work together and create a better Solar Network!
|
||||||
|
|
||||||
|
|||||||
@@ -62,4 +62,3 @@ If you want to build the release version, use the flutter build command. Learn m
|
|||||||
```bash
|
```bash
|
||||||
flutter build <platform>
|
flutter build <platform>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -24,6 +24,8 @@ android {
|
|||||||
ndkVersion = "29.0.13113456"
|
ndkVersion = "29.0.13113456"
|
||||||
|
|
||||||
compileOptions {
|
compileOptions {
|
||||||
|
isCoreLibraryDesugaringEnabled = true
|
||||||
|
|
||||||
sourceCompatibility = JavaVersion.VERSION_17
|
sourceCompatibility = JavaVersion.VERSION_17
|
||||||
targetCompatibility = JavaVersion.VERSION_17
|
targetCompatibility = JavaVersion.VERSION_17
|
||||||
}
|
}
|
||||||
@@ -63,6 +65,8 @@ android {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
||||||
|
|
||||||
implementation("com.google.android.material:material:1.12.0")
|
implementation("com.google.android.material:material:1.12.0")
|
||||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||||
implementation("com.squareup.okhttp3:okhttp:5.1.0")
|
implementation("com.squareup.okhttp3:okhttp:5.1.0")
|
||||||
@@ -71,3 +75,4 @@ dependencies {
|
|||||||
flutter {
|
flutter {
|
||||||
source = "../.."
|
source = "../.."
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -51,6 +51,12 @@
|
|||||||
<data android:scheme="http" android:host="solian.app" />
|
<data android:scheme="http" android:host="solian.app" />
|
||||||
<data android:scheme="https" />
|
<data android:scheme="https" />
|
||||||
</intent-filter>
|
</intent-filter>
|
||||||
|
<intent-filter android:autoVerify="true">
|
||||||
|
<action android:name="android.intent.action.VIEW" />
|
||||||
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
<category android:name="android.intent.category.BROWSABLE" />
|
||||||
|
<data android:scheme="solian" />
|
||||||
|
</intent-filter>
|
||||||
|
|
||||||
<!-- Share Intent Filters -->
|
<!-- Share Intent Filters -->
|
||||||
<intent-filter>
|
<intent-filter>
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 70 KiB |
41
android/app/src/main/res/drawable/ic_notification.xml
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
android:width="192dp"
|
||||||
|
android:height="192dp"
|
||||||
|
android:viewportWidth="192"
|
||||||
|
android:viewportHeight="192">
|
||||||
|
<path
|
||||||
|
android:pathData="M54,147h86"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="12"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M57,111s-2,-4.5 -2,-10m22,22s-4,7 -11,4m9,-22s-2,-4.5 -2,-10"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="10"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M54,147a32,32 0,0 1,-12 -61.67A39,39 0,0 1,81 46m59,101a30,30 0,0 0,29.93 -28"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="12"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M132,75m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="8"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
<path
|
||||||
|
android:pathData="M112.5,41.22C100.84,47.96 93,60.56 93,75c0,6.38 1.53,12.39 4.24,17.71m69.51,-35.42A38.84,38.84 0,0 1,171 75c0,14.43 -7.84,27.03 -19.49,33.78m-0.79,-43.32A20.9,20.9 0,0 1,153 75c0,7.77 -4.22,14.56 -10.49,18.19m-21,-36.38C115.22,60.44 111,67.23 111,75a20.9,20.9 0,0 0,2.28 9.53"
|
||||||
|
android:strokeLineJoin="round"
|
||||||
|
android:strokeWidth="10"
|
||||||
|
android:fillColor="#00000000"
|
||||||
|
android:strokeColor="#000"
|
||||||
|
android:strokeLineCap="round"/>
|
||||||
|
</vector>
|
||||||
@@ -46,31 +46,10 @@
|
|||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
"deletePublisher": "Delete Publisher",
|
"deletePublisher": "Delete Publisher",
|
||||||
"deletePublisherHint": "Are you sure to delete this publisher? This will also deleted all the post and collections under this publisher.",
|
"deletePublisherHint": "Are you sure to delete this publisher? This will also deleted all the post and collections under this publisher.",
|
||||||
"somethingWentWrong": "Something went wrong",
|
|
||||||
"deletePost": "Delete Post",
|
"deletePost": "Delete Post",
|
||||||
"safetyReport": "Report",
|
|
||||||
"safetyReportTitle": "Safety Report",
|
|
||||||
"safetyReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
|
||||||
"safetyReportType": "Report Type",
|
|
||||||
"safetyReportReason": "Additional Details",
|
|
||||||
"safetyReportReasonHint": "Please provide more details about the issue...",
|
|
||||||
"safetyReportSubmit": "Submit Report",
|
|
||||||
"safetyReportSubmitting": "Submitting...",
|
|
||||||
"safetyReportSuccess": "Report submitted successfully. Thank you for helping keep our community safe.",
|
|
||||||
"safetyReportError": "Failed to submit report. Please try again.",
|
|
||||||
"safetyReportReasonRequired": "Please provide details about the issue",
|
|
||||||
"safetyReportTypeSpam": "Spam or Misleading",
|
|
||||||
"safetyReportTypeHarassment": "Harassment or Abuse",
|
|
||||||
"safetyReportTypeHateSpeech": "Hate Speech",
|
|
||||||
"safetyReportTypeViolence": "Violence or Threats",
|
|
||||||
"safetyReportTypeAdultContent": "Adult Content",
|
|
||||||
"safetyReportTypeIntellectualProperty": "Intellectual Property Violation",
|
|
||||||
"safetyReportTypeOther": "Other",
|
|
||||||
"safetyReportTypeInappropriate": "Inappropriate Content",
|
|
||||||
"safetyReportTypeCopyright": "Copyright Violation",
|
|
||||||
"safetyReportSuccessTitle": "Report Submitted",
|
|
||||||
"safetyReportErrorTitle": "Error",
|
|
||||||
"deletePostHint": "Are you sure to delete this post?",
|
"deletePostHint": "Are you sure to delete this post?",
|
||||||
|
"deleteMessage": "Delete Message",
|
||||||
|
"deleteMessageConfirmation": "Are you sure you want to delete this message?",
|
||||||
"copyLink": "Copy Link",
|
"copyLink": "Copy Link",
|
||||||
"postCreateAccountTitle": "Thanks for joining!",
|
"postCreateAccountTitle": "Thanks for joining!",
|
||||||
"postCreateAccountNext": "What's next?",
|
"postCreateAccountNext": "What's next?",
|
||||||
@@ -98,8 +77,6 @@
|
|||||||
"explore": "Explore",
|
"explore": "Explore",
|
||||||
"exploreFilterSubscriptions": "Subscriptions",
|
"exploreFilterSubscriptions": "Subscriptions",
|
||||||
"exploreFilterFriends": "Friends",
|
"exploreFilterFriends": "Friends",
|
||||||
"discover": "Discover",
|
|
||||||
"joinRealm": "Join Realm",
|
|
||||||
"account": "Account",
|
"account": "Account",
|
||||||
"name": "Name",
|
"name": "Name",
|
||||||
"slug": "Slug",
|
"slug": "Slug",
|
||||||
@@ -144,16 +121,9 @@
|
|||||||
"other": "{} attachments"
|
"other": "{} attachments"
|
||||||
},
|
},
|
||||||
"edited": "Edited",
|
"edited": "Edited",
|
||||||
"editedAt": "Edited at {}",
|
|
||||||
"addVideo": "Add video",
|
"addVideo": "Add video",
|
||||||
"addPhoto": "Add photo",
|
"addPhoto": "Add photo",
|
||||||
"addAudio": "Add audio",
|
|
||||||
"addFile": "Add file",
|
"addFile": "Add file",
|
||||||
"recordAudio": "Record Audio",
|
|
||||||
"linkAttachment": "Link Attachment",
|
|
||||||
"fileIdCannotBeEmpty": "File ID cannot be empty",
|
|
||||||
"fileIdLinkHint": "Haven't upload to the Solar Network? Tap here to open Solar Network Drive to customize your uploads.",
|
|
||||||
"failedToFetchFile": "Failed to fetch file: {}",
|
|
||||||
"createDirectMessage": "Send new DM",
|
"createDirectMessage": "Send new DM",
|
||||||
"gotoDirectMessage": "Go to DM",
|
"gotoDirectMessage": "Go to DM",
|
||||||
"react": "React",
|
"react": "React",
|
||||||
@@ -165,6 +135,11 @@
|
|||||||
"reactionPositive": "Postive",
|
"reactionPositive": "Postive",
|
||||||
"reactionNegative": "Negative",
|
"reactionNegative": "Negative",
|
||||||
"reactionNeutral": "Neutral",
|
"reactionNeutral": "Neutral",
|
||||||
|
"customReaction": "Custom Reaction",
|
||||||
|
"customReactions": "Custom Reactions",
|
||||||
|
"stickerPlaceholder": "Sticker Placeholder",
|
||||||
|
"reactionAttitude": "Reaction Attitude",
|
||||||
|
"addReaction": "Add Reaction",
|
||||||
"connectionConnected": "Connected",
|
"connectionConnected": "Connected",
|
||||||
"connectionDisconnected": "Disconnected",
|
"connectionDisconnected": "Disconnected",
|
||||||
"connectionReconnecting": "Reconnecting",
|
"connectionReconnecting": "Reconnecting",
|
||||||
@@ -196,8 +171,8 @@
|
|||||||
"checkInResultLevel3": "Good Luck",
|
"checkInResultLevel3": "Good Luck",
|
||||||
"checkInResultLevel4": "Best Luck",
|
"checkInResultLevel4": "Best Luck",
|
||||||
"checkInActivityTitle": "{} checked in on {} and got a {}",
|
"checkInActivityTitle": "{} checked in on {} and got a {}",
|
||||||
"eventCalander": "Event Calander",
|
"eventCalendar": "Event Calendar",
|
||||||
"eventCalanderEmpty": "No events on that day.",
|
"eventCalendarEmpty": "No events on that day.",
|
||||||
"fortuneGraph": "Fortune Trend",
|
"fortuneGraph": "Fortune Trend",
|
||||||
"noFortuneData": "No fortune data available for this month.",
|
"noFortuneData": "No fortune data available for this month.",
|
||||||
"creatorHub": "Creator Hub",
|
"creatorHub": "Creator Hub",
|
||||||
@@ -283,11 +258,16 @@
|
|||||||
"translatorBadgeName": "Translator",
|
"translatorBadgeName": "Translator",
|
||||||
"translatorBadgeDescription": "Helping translate Solar Network into different languages",
|
"translatorBadgeDescription": "Helping translate Solar Network into different languages",
|
||||||
"wallet": "Wallet",
|
"wallet": "Wallet",
|
||||||
|
"walletStats": "Wallet Statistics",
|
||||||
|
"totalTransactions": "Total Transactions",
|
||||||
|
"totalOrders": "Total Orders",
|
||||||
|
"totalIncome": "Total Income",
|
||||||
|
"totalOutgoing": "Total Outgoing",
|
||||||
|
"netBalance": "Net Balance",
|
||||||
"walletCurrencyPoints": "New Solar Points",
|
"walletCurrencyPoints": "New Solar Points",
|
||||||
"walletCurrencyShortPoints": "NSP",
|
"walletCurrencyShortPoints": "NSP",
|
||||||
"walletCurrencyGolds": "The Solar Dollars",
|
"walletCurrencyGolds": "The Solar Dollars",
|
||||||
"walletCurrencyShortGolds": "NSD",
|
"walletCurrencyShortGolds": "NSD",
|
||||||
"retry": "Retry",
|
|
||||||
"creatorHubUnselectedHint": "Pick / create a publisher to get started.",
|
"creatorHubUnselectedHint": "Pick / create a publisher to get started.",
|
||||||
"relationships": "Relationships",
|
"relationships": "Relationships",
|
||||||
"addFriend": "Send a Friend Request",
|
"addFriend": "Send a Friend Request",
|
||||||
@@ -316,8 +296,6 @@
|
|||||||
"removeChatMemberHint": "Are you sure to remove this member from the room?",
|
"removeChatMemberHint": "Are you sure to remove this member from the room?",
|
||||||
"removeRealmMember": "Remove Realm Member",
|
"removeRealmMember": "Remove Realm Member",
|
||||||
"removeRealmMemberHint": "Are you sure to remove this member from the realm?",
|
"removeRealmMemberHint": "Are you sure to remove this member from the realm?",
|
||||||
"removePublisherMember": "Remove Publisher Member",
|
|
||||||
"removePublisherMemberHint": "Are you sure to remove this member from the publisher?",
|
|
||||||
"memberRole": "Member Role",
|
"memberRole": "Member Role",
|
||||||
"memberRoleHint": "Greater number has higher permission.",
|
"memberRoleHint": "Greater number has higher permission.",
|
||||||
"memberRoleEdit": "Edit role for @{}",
|
"memberRoleEdit": "Edit role for @{}",
|
||||||
@@ -340,6 +318,8 @@
|
|||||||
"settingsBackgroundImageClear": "Clear Background Image",
|
"settingsBackgroundImageClear": "Clear Background Image",
|
||||||
"settingsBackgroundGenerateColor": "Generate color scheme from Bacground Image",
|
"settingsBackgroundGenerateColor": "Generate color scheme from Bacground Image",
|
||||||
"messageNone": "No content to display",
|
"messageNone": "No content to display",
|
||||||
|
"messageUpdateLinks": "Server generated links previews",
|
||||||
|
"messageUpdateEdited": "Edited a message",
|
||||||
"unreadMessages": {
|
"unreadMessages": {
|
||||||
"one": "{} unread message",
|
"one": "{} unread message",
|
||||||
"other": "{} unread messages"
|
"other": "{} unread messages"
|
||||||
@@ -353,14 +333,13 @@
|
|||||||
"settingsAprilFoolFeatures": "April Fool Features",
|
"settingsAprilFoolFeatures": "April Fool Features",
|
||||||
"settingsEnterToSend": "Enter to Send",
|
"settingsEnterToSend": "Enter to Send",
|
||||||
"settingsTransparentAppBar": "Transparent App Bar",
|
"settingsTransparentAppBar": "Transparent App Bar",
|
||||||
|
"settingsCardBackgroundOpacity": "Card Background Opacity",
|
||||||
"settingsCustomFonts": "Custom Fonts",
|
"settingsCustomFonts": "Custom Fonts",
|
||||||
"settingsCustomFontsHint": "Custom fonts will be used for all text in the app. Make sure it is installed on your device.",
|
"settingsCustomFontsHint": "Custom fonts will be used for all text in the app. Make sure it is installed on your device.",
|
||||||
"settingsColorScheme": "Color Scheme",
|
"settingsColorScheme": "Color Scheme",
|
||||||
"postTitle": "Title",
|
"postTitle": "Title",
|
||||||
"postDescription": "Description",
|
"postDescription": "Description",
|
||||||
"call": "Call",
|
"call": "Call",
|
||||||
"callLeave": "Leave",
|
|
||||||
"callEnd": "End this call",
|
|
||||||
"done": "Done",
|
"done": "Done",
|
||||||
"loginResetPasswordSent": "Password reset link sent, please check your email inbox.",
|
"loginResetPasswordSent": "Password reset link sent, please check your email inbox.",
|
||||||
"accountDeletion": "Delete Account",
|
"accountDeletion": "Delete Account",
|
||||||
@@ -384,9 +363,6 @@
|
|||||||
"postContent": "Content",
|
"postContent": "Content",
|
||||||
"postSettings": "Settings",
|
"postSettings": "Settings",
|
||||||
"postPublisherUnselected": "Publisher Unspecified",
|
"postPublisherUnselected": "Publisher Unspecified",
|
||||||
"postType": "Post Type",
|
|
||||||
"articleAttachmentHint": "Attachments must be uploaded and inserted into the article body to be visible.",
|
|
||||||
"postVisibility": "Post Visibility",
|
|
||||||
"postVisibilityPublic": "Public",
|
"postVisibilityPublic": "Public",
|
||||||
"postVisibilityFriends": "Friends Only",
|
"postVisibilityFriends": "Friends Only",
|
||||||
"postVisibilityUnlisted": "Unlisted",
|
"postVisibilityUnlisted": "Unlisted",
|
||||||
@@ -405,7 +381,6 @@
|
|||||||
"authFactorSecretHint": "Create an secret for this factor.",
|
"authFactorSecretHint": "Create an secret for this factor.",
|
||||||
"authFactorQrCodeScan": "Scan this QR code with your authenticator app to set up TOTP authentication",
|
"authFactorQrCodeScan": "Scan this QR code with your authenticator app to set up TOTP authentication",
|
||||||
"authFactorNoQrCode": "No QR code available for this authentication factor",
|
"authFactorNoQrCode": "No QR code available for this authentication factor",
|
||||||
"cancel": "Cancel",
|
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"authFactorAdditional": "One more step",
|
"authFactorAdditional": "One more step",
|
||||||
"authFactorHint": "Contact method hint",
|
"authFactorHint": "Contact method hint",
|
||||||
@@ -420,16 +395,20 @@
|
|||||||
"lastActiveAt": "Last active at {}",
|
"lastActiveAt": "Last active at {}",
|
||||||
"authDeviceLogout": "Logout",
|
"authDeviceLogout": "Logout",
|
||||||
"authDeviceLogoutHint": "Are you sure you want to logout this device? This will also disable the push notification to this device.",
|
"authDeviceLogoutHint": "Are you sure you want to logout this device? This will also disable the push notification to this device.",
|
||||||
"typingHint": {
|
|
||||||
"one": "{} is typing...",
|
|
||||||
"other": "{} are typing..."
|
|
||||||
},
|
|
||||||
"authDeviceEditLabel": "Edit Label",
|
"authDeviceEditLabel": "Edit Label",
|
||||||
"authDeviceLabelTitle": "Edit Device Label",
|
"authDeviceLabelTitle": "Edit Device Label",
|
||||||
"authDeviceLabelHint": "Enter a name for this device",
|
"authDeviceLabelHint": "Enter a name for this device",
|
||||||
"authDeviceSwipeEditHint": "Swipe left to edit label",
|
"authDeviceSwipeEditHint": "Swipe left to edit label",
|
||||||
"authDeviceSwipeLogoutHint": "Swipe right to logout device",
|
"authDeviceSwipeLogoutHint": "Swipe right to logout device",
|
||||||
|
"typingHint": {
|
||||||
|
"one": "{} is typing...",
|
||||||
|
"other": "{} are typing..."
|
||||||
|
},
|
||||||
"settingsAppearance": "Appearance",
|
"settingsAppearance": "Appearance",
|
||||||
|
"settingsThemeMode": "Theme Mode",
|
||||||
|
"settingsThemeModeSystem": "System",
|
||||||
|
"settingsThemeModeLight": "Light",
|
||||||
|
"settingsThemeModeDark": "Dark",
|
||||||
"settingsServer": "Server",
|
"settingsServer": "Server",
|
||||||
"settingsBehavior": "Behavior",
|
"settingsBehavior": "Behavior",
|
||||||
"settingsDesktop": "Desktop",
|
"settingsDesktop": "Desktop",
|
||||||
@@ -442,27 +421,6 @@
|
|||||||
"settingsKeyboardShortcutNewMessage": "New Message",
|
"settingsKeyboardShortcutNewMessage": "New Message",
|
||||||
"settingsKeyboardShortcutCloseDialog": "Close Dialog",
|
"settingsKeyboardShortcutCloseDialog": "Close Dialog",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"drafts": "Drafts",
|
|
||||||
"noDrafts": "No drafts yet",
|
|
||||||
"articleDrafts": "Article drafts",
|
|
||||||
"postDrafts": "Post drafts",
|
|
||||||
"saveDraft": "Save draft",
|
|
||||||
"draftSaved": "Draft saved",
|
|
||||||
"draftSaveFailed": "Failed to save draft",
|
|
||||||
"clearAllDrafts": "Clear All Drafts",
|
|
||||||
"clearAllDraftsConfirm": "Are you sure you want to delete all drafts? This action cannot be undone.",
|
|
||||||
"clearAll": "Clear All",
|
|
||||||
"untitled": "Untitled",
|
|
||||||
"noContent": "No content",
|
|
||||||
"justNow": "Just now",
|
|
||||||
"minutesAgo": "{} minutes ago",
|
|
||||||
"hoursAgo": "{} hours ago",
|
|
||||||
"daysAgo": "{} days ago",
|
|
||||||
"public": "Public",
|
|
||||||
"unlisted": "Unlisted",
|
|
||||||
"friends": "Friends",
|
|
||||||
"selected": "Selected",
|
|
||||||
"private": "Private",
|
|
||||||
"contactMethod": "Contact Method",
|
"contactMethod": "Contact Method",
|
||||||
"contactMethodType": "Contact Type",
|
"contactMethodType": "Contact Type",
|
||||||
"contactMethodTypeEmail": "Email",
|
"contactMethodTypeEmail": "Email",
|
||||||
@@ -480,7 +438,6 @@
|
|||||||
"contactMethodDelete": "Delete Contact",
|
"contactMethodDelete": "Delete Contact",
|
||||||
"contactMethodNew": "New Contact Method",
|
"contactMethodNew": "New Contact Method",
|
||||||
"contactMethodContentEmpty": "Contact content cannot be empty",
|
"contactMethodContentEmpty": "Contact content cannot be empty",
|
||||||
"postContentEmpty": "Post content cannot be empty",
|
|
||||||
"contactMethodVerificationSent": "Verification code sent to your contact method",
|
"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.",
|
"contactMethodVerificationNeeded": "The contact method is added, but not verified yet. You can verify it by tapping it and select verify.",
|
||||||
"accountContactMethod": "Contact Methods",
|
"accountContactMethod": "Contact Methods",
|
||||||
@@ -522,7 +479,6 @@
|
|||||||
"accountProfileView": "View Profile",
|
"accountProfileView": "View Profile",
|
||||||
"unspecified": "Unspecified",
|
"unspecified": "Unspecified",
|
||||||
"added": "Added",
|
"added": "Added",
|
||||||
"preview": "Preview",
|
|
||||||
"togglePreview": "Toggle Preview",
|
"togglePreview": "Toggle Preview",
|
||||||
"subscribe": "Subscribe",
|
"subscribe": "Subscribe",
|
||||||
"unsubscribe": "Unsubscribe",
|
"unsubscribe": "Unsubscribe",
|
||||||
@@ -533,6 +489,7 @@
|
|||||||
"pinCode": "PIN Code",
|
"pinCode": "PIN Code",
|
||||||
"biometric": "Biometric",
|
"biometric": "Biometric",
|
||||||
"enterPinToConfirm": "Enter your 6-digit PIN to confirm payment",
|
"enterPinToConfirm": "Enter your 6-digit PIN to confirm payment",
|
||||||
|
"enterPin": "Enter your PIN code",
|
||||||
"clearPin": "Clear PIN",
|
"clearPin": "Clear PIN",
|
||||||
"useBiometricToConfirm": "Use biometric authentication to confirm payment",
|
"useBiometricToConfirm": "Use biometric authentication to confirm payment",
|
||||||
"touchSensorToAuthenticate": "Touch the sensor to authenticate",
|
"touchSensorToAuthenticate": "Touch the sensor to authenticate",
|
||||||
@@ -549,19 +506,26 @@
|
|||||||
"paymentError": "Payment failed: {error}",
|
"paymentError": "Payment failed: {error}",
|
||||||
"usePinInstead": "Use PIN Code",
|
"usePinInstead": "Use PIN Code",
|
||||||
"levelProgress": "Level Progress",
|
"levelProgress": "Level Progress",
|
||||||
|
"unlockedFeatures": "Unlocked Features",
|
||||||
|
"unlockedFeaturesDescription": "Features unlocked at your current level will be displayed here.",
|
||||||
"stellarMembership": "Stellar Membership",
|
"stellarMembership": "Stellar Membership",
|
||||||
"upgradeYourPlan": "Upgrade Your Plan",
|
"upgradeYourPlan": "Upgrade Your Plan",
|
||||||
"chooseYourPlan": "Choose Your Plan",
|
"chooseYourPlan": "Choose Your Plan",
|
||||||
"currentMembership": "Current: {}",
|
"currentMembership": "Current: {}",
|
||||||
"currentMembershipMember": "A member of Stellar Program · {}",
|
|
||||||
"membershipExpires": "Expires: {}",
|
"membershipExpires": "Expires: {}",
|
||||||
"membershipTierStellar": "Stellar",
|
"membershipTierStellar": "Stellar",
|
||||||
"membershipTierNova": "Nova",
|
"membershipTierNova": "Nova",
|
||||||
"membershipTierSupernova": "Supernova",
|
"membershipTierSupernova": "Supernova",
|
||||||
"membershipTierUnknown": "Unknown",
|
"membershipTierUnknown": "Unknown",
|
||||||
"membershipPriceStellar": "1200 NSP per month, level 3+ required",
|
"membershipFeatureBasic": "Basic features",
|
||||||
"membershipPriceNova": "2400 NSP per month, level 6+ required",
|
"membershipFeaturePrioritySupport": "Priority support",
|
||||||
"membershipPriceSupernova": "3600 NSP per month, level 9+ required",
|
"membershipFeatureAdFree": "Ad-free experience",
|
||||||
|
"membershipFeatureAllPrimary": "All Primary features",
|
||||||
|
"membershipFeatureAdvancedCustomization": "Advanced customization",
|
||||||
|
"membershipFeatureEarlyAccess": "Early access",
|
||||||
|
"membershipFeatureAllNova": "All Nova features",
|
||||||
|
"membershipFeatureExclusiveContent": "Exclusive content",
|
||||||
|
"membershipFeatureVipSupport": "VIP support",
|
||||||
"membershipCurrentBadge": "CURRENT",
|
"membershipCurrentBadge": "CURRENT",
|
||||||
"restorePurchase": "Restore Purchase",
|
"restorePurchase": "Restore Purchase",
|
||||||
"restorePurchaseDescription": "Enter your payment provider and order ID to restore your purchase.",
|
"restorePurchaseDescription": "Enter your payment provider and order ID to restore your purchase.",
|
||||||
@@ -571,9 +535,56 @@
|
|||||||
"enterOrderId": "Enter your order ID",
|
"enterOrderId": "Enter your order ID",
|
||||||
"restore": "Restore",
|
"restore": "Restore",
|
||||||
"keyboardShortcuts": "Keyboard Shortcuts",
|
"keyboardShortcuts": "Keyboard Shortcuts",
|
||||||
|
"safetyReport": "Report",
|
||||||
|
"safetyReportTitle": "Safety Report",
|
||||||
|
"safetyReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
||||||
|
"safetyReportType": "Report Type",
|
||||||
|
"safetyReportReason": "Additional Details",
|
||||||
|
"safetyReportReasonHint": "Please provide more details about the issue...",
|
||||||
|
"safetyReportSubmit": "Submit Report",
|
||||||
|
"safetyReportSubmitting": "Submitting...",
|
||||||
|
"safetyReportSuccess": "Report submitted successfully. Thank you for helping keep our community safe.",
|
||||||
|
"safetyReportError": "Failed to submit report. Please try again.",
|
||||||
|
"safetyReportReasonRequired": "Please provide details about the issue",
|
||||||
|
"safetyReportTypeSpam": "Spam or Misleading",
|
||||||
|
"safetyReportTypeHarassment": "Harassment or Abuse",
|
||||||
|
"safetyReportTypeHateSpeech": "Hate Speech",
|
||||||
|
"safetyReportTypeViolence": "Violence or Threats",
|
||||||
|
"safetyReportTypeAdultContent": "Adult Content",
|
||||||
|
"safetyReportTypeIntellectualProperty": "Intellectual Property Violation",
|
||||||
|
"safetyReportTypeOther": "Other",
|
||||||
|
"safetyReportTypeInappropriate": "Inappropriate Content",
|
||||||
|
"safetyReportTypeCopyright": "Copyright Violation",
|
||||||
|
"safetyReportSuccessTitle": "Report Submitted",
|
||||||
|
"safetyReportErrorTitle": "Error",
|
||||||
|
"discover": "Discover",
|
||||||
|
"joinRealm": "Join Realm",
|
||||||
|
"removePublisherMember": "Remove Publisher Member",
|
||||||
|
"removePublisherMemberHint": "Are you sure to remove this member from the publisher?",
|
||||||
|
"drafts": "Drafts",
|
||||||
|
"noDrafts": "No drafts yet",
|
||||||
|
"articleDrafts": "Article drafts",
|
||||||
|
"postDrafts": "Post drafts",
|
||||||
|
"saveDraft": "Save draft",
|
||||||
|
"draftSaved": "Draft saved",
|
||||||
|
"draftSaveFailed": "Failed to save draft",
|
||||||
|
"clearAllDrafts": "Clear All Drafts",
|
||||||
|
"clearAllDraftsConfirm": "Are you sure you want to delete all drafts? This action cannot be undone.",
|
||||||
|
"clearAll": "Clear All",
|
||||||
|
"untitled": "Untitled",
|
||||||
|
"noContent": "No content",
|
||||||
|
"justNow": "Just now",
|
||||||
|
"minutesAgo": "{} minutes ago",
|
||||||
|
"hoursAgo": "{} hours ago",
|
||||||
|
"daysAgo": "{} days ago",
|
||||||
|
"public": "Public",
|
||||||
|
"unlisted": "Unlisted",
|
||||||
|
"friends": "Friends",
|
||||||
|
"selected": "Selected",
|
||||||
|
"private": "Private",
|
||||||
|
"postContentEmpty": "Post content cannot be empty",
|
||||||
"share": "Share",
|
"share": "Share",
|
||||||
"sharePost": "Share Post",
|
"sharePost": "Share Post",
|
||||||
"sharePostPhoto": "Share Post as Photo",
|
|
||||||
"quickActions": "Quick Actions",
|
"quickActions": "Quick Actions",
|
||||||
"post": "Post",
|
"post": "Post",
|
||||||
"copy": "Copy",
|
"copy": "Copy",
|
||||||
@@ -599,8 +610,6 @@
|
|||||||
"no": "No",
|
"no": "No",
|
||||||
"yes": "Yes",
|
"yes": "Yes",
|
||||||
"navigateToChat": "Navigate to Chat",
|
"navigateToChat": "Navigate to Chat",
|
||||||
"wouldYouLikeToNavigateToChat": "Would You like to navigate to the chat?",
|
|
||||||
"abuseReports": "Abuse Reports",
|
|
||||||
"abuseReport": "Report",
|
"abuseReport": "Report",
|
||||||
"abuseReportTitle": "Report Content",
|
"abuseReportTitle": "Report Content",
|
||||||
"abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
"abuseReportDescription": "Help us keep the community safe by reporting inappropriate content or behavior.",
|
||||||
@@ -630,10 +639,12 @@
|
|||||||
"chatNotJoined": "You have not joined this chat yet.",
|
"chatNotJoined": "You have not joined this chat yet.",
|
||||||
"chatUnableJoin": "You can't join this chat due to it's access control settings.",
|
"chatUnableJoin": "You can't join this chat due to it's access control settings.",
|
||||||
"chatJoin": "Join the Chat",
|
"chatJoin": "Join the Chat",
|
||||||
|
"chatReplyingTo": "Replying to {}",
|
||||||
|
"chatForwarding": "Forwarding message",
|
||||||
|
"chatEditing": "Editing message",
|
||||||
|
"chatNoContent": "No content",
|
||||||
"realmJoin": "Join the Realm",
|
"realmJoin": "Join the Realm",
|
||||||
"realmJoinSuccess": "Successfully joined the realm.",
|
"realmJoinSuccess": "Successfully joined the realm.",
|
||||||
"discoverRealms": "Discover realms",
|
|
||||||
"discoverPublishers": "Discover publishers",
|
|
||||||
"search": "Search",
|
"search": "Search",
|
||||||
"publisherMembers": "Collaborators",
|
"publisherMembers": "Collaborators",
|
||||||
"developerHub": "Developer Hub",
|
"developerHub": "Developer Hub",
|
||||||
@@ -679,9 +690,28 @@
|
|||||||
"publisherFeatureDevelopDescription": "Unlock development abilities for your publisher, including custom apps, API keys, and more.",
|
"publisherFeatureDevelopDescription": "Unlock development abilities for your publisher, including custom apps, API keys, and more.",
|
||||||
"publisherFeatureDevelopHint": "Currently, this feature is under active development, you need send a request to unlock this feature.",
|
"publisherFeatureDevelopHint": "Currently, this feature is under active development, you need send a request to unlock this feature.",
|
||||||
"learnMore": "Learn More",
|
"learnMore": "Learn More",
|
||||||
"discoverWebArticles": "Articles from external sites",
|
|
||||||
"webArticlesStand": "Article Stand",
|
"webArticlesStand": "Article Stand",
|
||||||
"about": "About",
|
"about": "About",
|
||||||
|
"somethingWentWrong": "Something went wrong",
|
||||||
|
"editedAt": "Edited at {}",
|
||||||
|
"addAudio": "Add audio",
|
||||||
|
"recordAudio": "Record Audio",
|
||||||
|
"linkAttachment": "Link Attachment",
|
||||||
|
"fileIdCannotBeEmpty": "File ID cannot be empty",
|
||||||
|
"fileIdLinkHint": "Haven't upload to the Solar Network? Tap here to open Solar Network Drive to customize your uploads.",
|
||||||
|
"failedToFetchFile": "Failed to fetch file: {}",
|
||||||
|
"callLeave": "Leave",
|
||||||
|
"callEnd": "End this call",
|
||||||
|
"postType": "Post Type",
|
||||||
|
"articleAttachmentHint": "Attachments must be uploaded and inserted into the article body to be visible.",
|
||||||
|
"postVisibility": "Post Visibility",
|
||||||
|
"currentMembershipMember": "A member of Stellar Program · {}",
|
||||||
|
"membershipPriceStellar": "1200 NSP per month, level 3+ required",
|
||||||
|
"membershipPriceNova": "2400 NSP per month, level 6+ required",
|
||||||
|
"membershipPriceSupernova": "3600 NSP per month, level 9+ required",
|
||||||
|
"sharePostPhoto": "Share Post as Photo",
|
||||||
|
"wouldYouLikeToNavigateToChat": "Would You like to navigate to the chat?",
|
||||||
|
"abuseReports": "Abuse Reports",
|
||||||
"membershipCancel": "Cancel Membership",
|
"membershipCancel": "Cancel Membership",
|
||||||
"membershipCancelConfirm": "Are you sure to cancel your membership?",
|
"membershipCancelConfirm": "Are you sure to cancel your membership?",
|
||||||
"membershipCancelHint": "Are you sure to cancel your membership? You will not be charged again. Your membership will remain active until the end of the current billing period. And you will not able to resubscribe until the end of the current subscription ends.",
|
"membershipCancelHint": "Are you sure to cancel your membership? You will not be charged again. Your membership will remain active until the end of the current billing period. And you will not able to resubscribe until the end of the current subscription ends.",
|
||||||
@@ -744,24 +774,25 @@
|
|||||||
"rename": "Rename",
|
"rename": "Rename",
|
||||||
"markAsSensitive": "Mark as Sensitive",
|
"markAsSensitive": "Mark as Sensitive",
|
||||||
"fileName": "File name",
|
"fileName": "File name",
|
||||||
"sensitiveCategories.language": "Language",
|
"sensitiveCategories": {
|
||||||
"sensitiveCategories.sexualContent": "Sexual Content",
|
"language": "Language",
|
||||||
"sensitiveCategories.violence": "Violence",
|
"sexualContent": "Sexual Content",
|
||||||
"sensitiveCategories.profanity": "Profanity",
|
"violence": "Violence",
|
||||||
"sensitiveCategories.hateSpeech": "Hate Speech",
|
"profanity": "Profanity",
|
||||||
"sensitiveCategories.racism": "Racism",
|
"hateSpeech": "Hate Speech",
|
||||||
"sensitiveCategories.adultContent": "Adult Content",
|
"racism": "Racism",
|
||||||
"sensitiveCategories.drugAbuse": "Drug Abuse",
|
"adultContent": "Adult Content",
|
||||||
"sensitiveCategories.alcoholAbuse": "Alcohol Abuse",
|
"drugAbuse": "Drug Abuse",
|
||||||
"sensitiveCategories.gambling": "Gambling",
|
"alcoholAbuse": "Alcohol Abuse",
|
||||||
"sensitiveCategories.selfHarm": "Self-harm",
|
"gambling": "Gambling",
|
||||||
"sensitiveCategories.childAbuse": "Child Abuse",
|
"selfHarm": "Self-harm",
|
||||||
"sensitiveCategories.other": "Other",
|
"childAbuse": "Child Abuse",
|
||||||
|
"other": "Other"
|
||||||
|
},
|
||||||
"poll": "Poll",
|
"poll": "Poll",
|
||||||
"pollsRecent": "Recent Polls",
|
"pollsRecent": "Recent Polls",
|
||||||
"pollCreateNew": "Create New",
|
"pollCreateNew": "Create New",
|
||||||
"pollCreateNewHint": "Create a new poll for your post. Pick a publisher and continue.",
|
"pollCreateNewHint": "Create a new poll for your post. Pick a publisher and continue.",
|
||||||
"pollQuestions": "Questions",
|
|
||||||
"publisher": "Publisher",
|
"publisher": "Publisher",
|
||||||
"publisherHint": "Enter the publisher name",
|
"publisherHint": "Enter the publisher name",
|
||||||
"publisherCannotBeEmpty": "Publisher cannot be empty",
|
"publisherCannotBeEmpty": "Publisher cannot be empty",
|
||||||
@@ -800,6 +831,7 @@
|
|||||||
"one": "+{} file remaining",
|
"one": "+{} file remaining",
|
||||||
"other": "+{} files remaining"
|
"other": "+{} files remaining"
|
||||||
},
|
},
|
||||||
|
"pollQuestions": "Questions",
|
||||||
"pollAnswerSubmitted": "Poll answer has been submitted.",
|
"pollAnswerSubmitted": "Poll answer has been submitted.",
|
||||||
"modifyAnswers": "Modify Answers",
|
"modifyAnswers": "Modify Answers",
|
||||||
"back": "Back",
|
"back": "Back",
|
||||||
@@ -836,5 +868,439 @@
|
|||||||
"pollAddOption": "Add option",
|
"pollAddOption": "Add option",
|
||||||
"pollOptionLabel": "Option label",
|
"pollOptionLabel": "Option label",
|
||||||
"pollLongTextAnswerPreview": "Long text answer (preview)",
|
"pollLongTextAnswerPreview": "Long text answer (preview)",
|
||||||
"pollShortTextAnswerPreview": "Short text answer (preview)"
|
"pollShortTextAnswerPreview": "Short text answer (preview)",
|
||||||
|
"award": "Award",
|
||||||
|
"awardPost": "Award Post",
|
||||||
|
"awardPoints": "Awarded {} points",
|
||||||
|
"awardMessage": "Message",
|
||||||
|
"awardMessageHint": "Enter your award message...",
|
||||||
|
"awardAttitude": "Attitude",
|
||||||
|
"awardAttitudePositive": "Positive",
|
||||||
|
"awardAttitudeNegative": "Negative",
|
||||||
|
"awardAmount": "Amount",
|
||||||
|
"awardAmountHint": "Enter amount...",
|
||||||
|
"awardAmountRequired": "Amount is required",
|
||||||
|
"awardAmountInvalid": "Please enter a valid amount",
|
||||||
|
"awardMessageTooLong": "Message is too long (max 4096 characters)",
|
||||||
|
"awardSuccess": "Award sent successfully!",
|
||||||
|
"awardSubmit": "Award",
|
||||||
|
"awardPostPreview": "Post Preview",
|
||||||
|
"awardNoContent": "No content available",
|
||||||
|
"awardByPublisher": "By {}",
|
||||||
|
"awardBenefits": "Award Benefits",
|
||||||
|
"awardBenefitsDescription": "Awarding this post increases its value and visibility. Higher valued posts have a better chance of being featured and highlighted in the community.",
|
||||||
|
"checkInResultLevel5": "Happy Birthday 🥳",
|
||||||
|
"region": "Region",
|
||||||
|
"accountRegionHint": "This region will be used for content delivery and localization.",
|
||||||
|
"settingsCustomFontsHelper": "Use comma to seprate.",
|
||||||
|
"settingsBackgroundImageEnable": "Show Background Image",
|
||||||
|
"settingsDataSavingMode": "Data Saving Mode",
|
||||||
|
"dataSavingHint": "Data Saving Mode",
|
||||||
|
"postTypePost": "Post",
|
||||||
|
"searchDrafts": "Search drafts...",
|
||||||
|
"noSearchResults": "No search results",
|
||||||
|
"contactMethodMakePublic": "Make Public",
|
||||||
|
"contactMethodMakePrivate": "Make Private",
|
||||||
|
"contactMethodPublic": "Public",
|
||||||
|
"contactMethodPrivate": "Private",
|
||||||
|
"discoverRealms": "Realms",
|
||||||
|
"discoverPublishers": "Publishers",
|
||||||
|
"discoverShuffledPost": "Random Posts",
|
||||||
|
"projects": "Projects",
|
||||||
|
"noProjects": "No projects found.",
|
||||||
|
"deleteProject": "Delete Project",
|
||||||
|
"deleteProjectHint": "Are you sure you want to delete this project? This action cannot be undone.",
|
||||||
|
"createProject": "Create Project",
|
||||||
|
"editProject": "Edit Project",
|
||||||
|
"projectDetails": "Project Details",
|
||||||
|
"createBot": "Create Bot",
|
||||||
|
"bots": "Bots",
|
||||||
|
"noBots": "No bots yet.",
|
||||||
|
"deleteBotHint": "Are you sure you want to delete this bot? This action cannot be undone.",
|
||||||
|
"deleteBot": "Delete Bot",
|
||||||
|
"discoverWebArticles": "Web Feed Articles",
|
||||||
|
"messageJumpNotLoaded": "The referenced message was not loaded, unable to jump to it.",
|
||||||
|
"postUnlinkRealm": "No linked realm",
|
||||||
|
"postSlug": "Slug",
|
||||||
|
"postSlugHint": "The slug can be used to access your post via URL in the webpage, it should be publisher-wide unique.",
|
||||||
|
"attachmentOnDevice": "On-device",
|
||||||
|
"attachmentOnCloud": "On-cloud",
|
||||||
|
"attachments": "Attachments",
|
||||||
|
"publisherCollabInvitation": "Collabration invitations",
|
||||||
|
"publisherCollabInvitationCount": {
|
||||||
|
"zero": "No invitation",
|
||||||
|
"one": "{} available invitation",
|
||||||
|
"other": "{} available invitations"
|
||||||
|
},
|
||||||
|
"failedToLoadUserInfo": "Failed to load user info",
|
||||||
|
"failedToLoadUserInfoNetwork": "It seems be network issue, you can tap the button below to try again.",
|
||||||
|
"failedToLoadUserInfoUnauthorized": "It seems your session has been logged out or not available anymore, you can still try agian to fetch the user info if you want.",
|
||||||
|
"okay": "Okay",
|
||||||
|
"postDetail": "Post Detail",
|
||||||
|
"postCount": {
|
||||||
|
"zero": "No posts",
|
||||||
|
"one": "{} post",
|
||||||
|
"other": "{} posts"
|
||||||
|
},
|
||||||
|
"mimeType": "MIME Type",
|
||||||
|
"fileSize": "File Size",
|
||||||
|
"fileHash": "File Hash",
|
||||||
|
"exifData": "EXIF Data",
|
||||||
|
"postShuffle": "Shuffle Posts",
|
||||||
|
"leveling": "Leveling",
|
||||||
|
"levelingHistory": "Leveling History",
|
||||||
|
"stellarProgram": "Stellar Program",
|
||||||
|
"socialCredits": "Social Credits",
|
||||||
|
"credits": "Credits",
|
||||||
|
"creditsStatus": "Credits Status",
|
||||||
|
"socialCreditsDescription": "Social Credit is a way for Solar Network to evaluate users. It is calculated based on their behavior and interactions. With a base score of 100, higher scores indicate a user's credibility within the community. Scores change over time to reflect a user's recent behavior. Users with higher credit ratings enjoy more benefits, while users with lower credit ratings may have some functionality restricted.",
|
||||||
|
"socialCreditsLevelPoor": "Poor",
|
||||||
|
"socialCreditsLevelNormal": "Normal",
|
||||||
|
"socialCreditsLevelGood": "Good",
|
||||||
|
"socialCreditsLevelExcellent": "Excellent",
|
||||||
|
"orderByPopularity": "Sort by popularity",
|
||||||
|
"orderByReleaseDate": "Sort by release date",
|
||||||
|
"editBot": "Edit Bot",
|
||||||
|
"botAutomatedBy": "Automated by {}",
|
||||||
|
"botDetails": "Bot Details",
|
||||||
|
"overview": "Overview",
|
||||||
|
"keys": "Keys",
|
||||||
|
"botNotFound": "Bot not found.",
|
||||||
|
"newBotKey": "New Bot Key",
|
||||||
|
"newBotKeyHint": "Enter a name for your new key. The key will be shown only once.",
|
||||||
|
"revokeBotKey": "Revoke Bot Key",
|
||||||
|
"revokeBotKeyHint": "Are you sure you want to revoke this key? This action cannot be undone and any application using this key will stop working.",
|
||||||
|
"noBotKeys": "No bot keys yet.",
|
||||||
|
"revoke": "Revoke",
|
||||||
|
"keyName": "Key Name",
|
||||||
|
"newKeyGenerated": "New Key Generated",
|
||||||
|
"copyKeyHint": "Please copy this key and store it somewhere safe. You will not be able to see it again.",
|
||||||
|
"rotateKey": "Rotate Key",
|
||||||
|
"rotateBotKey": "Rotate Bot Key",
|
||||||
|
"rotateBotKeyHint": "Are you sure you want to rotate this key? The old key will become invalid immediately. This action cannot be undone.",
|
||||||
|
"webFeedArticleCount": {
|
||||||
|
"zero": "No articles",
|
||||||
|
"one": "{} article",
|
||||||
|
"other": "{} articles"
|
||||||
|
},
|
||||||
|
"webFeedSubscribed": "The feed has been subscribed",
|
||||||
|
"webFeedUnsubscribed": "The feed has been unsubscribed",
|
||||||
|
"appDetails": "App Details",
|
||||||
|
"secrets": "Secrets",
|
||||||
|
"appNotFound": "App not found.",
|
||||||
|
"secretCopied": "Secret copied to clipboard.",
|
||||||
|
"deleteSecret": "Delete Secret",
|
||||||
|
"deleteSecretHint": "Are you sure you want to delete this secret? This action cannot be undone.",
|
||||||
|
"generateSecret": "Generate New Secret",
|
||||||
|
"createdAt": "Created at {}",
|
||||||
|
"newSecretGenerated": "New Secret Generated",
|
||||||
|
"copySecretHint": "Please copy this secret and store it somewhere safe. You will not be able to see it again.",
|
||||||
|
"expiresIn": "Expires In (seconds)",
|
||||||
|
"isOidc": "OIDC Compliant",
|
||||||
|
"pinPost": "Pin Post",
|
||||||
|
"unpinPost": "Unpin Post",
|
||||||
|
"pinnedPost": "Pinned",
|
||||||
|
"publisherPage": "Publisher Page",
|
||||||
|
"realmPage": "Realm Page",
|
||||||
|
"replyPage": "Reply Page",
|
||||||
|
"pinPostPublisherHint": "Pin this post to your publisher page",
|
||||||
|
"pinPostRealmHint": "Pin this post to the realm page",
|
||||||
|
"pinPostRealmDisabledHint": "This post doesn't belong to any realm",
|
||||||
|
"pinPostReplyHint": "Pin this post to the reply page",
|
||||||
|
"pinPostReplyDisabledHint": "This post is not a reply",
|
||||||
|
"pin": "Pin",
|
||||||
|
"unpinPostHint": "Are you sure you want to unpin this post?",
|
||||||
|
"all": "All",
|
||||||
|
"statusPresent": "Present",
|
||||||
|
"accountAutomated": "Automated",
|
||||||
|
"chatBreakClearButton": "Clear",
|
||||||
|
"chatBreak5m": "5m",
|
||||||
|
"chatBreak10m": "10m",
|
||||||
|
"chatBreak15m": "15m",
|
||||||
|
"chatBreak30m": "30m",
|
||||||
|
"chatBreakCustomMinutes": "Custom (minutes)",
|
||||||
|
"errorGeneric": "Error: {}",
|
||||||
|
"searchMessages": "Search Messages",
|
||||||
|
"messagesCount": "{} messages",
|
||||||
|
"dotSeparator": "·",
|
||||||
|
"roleValidationHint": "Role must be between 0 and 100",
|
||||||
|
"searchMessagesHint": "Search messages...",
|
||||||
|
"searchLinks": "Links",
|
||||||
|
"searchAttachments": "Attachments",
|
||||||
|
"noMessagesFound": "No messages found",
|
||||||
|
"Searching...": "Searching...",
|
||||||
|
"searchError": "Search failed. Please try again.",
|
||||||
|
"tryDifferentKeywords": "Try different keywords or remove search filters",
|
||||||
|
"retry": "Retry",
|
||||||
|
"openInBrowser": "Open in Browser",
|
||||||
|
"highlightPost": "Highlight Post",
|
||||||
|
"filters": "Filters",
|
||||||
|
"apply": "Apply",
|
||||||
|
"pubName": "Pub Name",
|
||||||
|
"realm": "Realm",
|
||||||
|
"shuffle": "Shuffle",
|
||||||
|
"pinned": "Pinned",
|
||||||
|
"noResultsFound": "No results found",
|
||||||
|
"toggleFilters": "Toggle filters",
|
||||||
|
"notableDayNext": "{} is in",
|
||||||
|
"expandPoll": "Expand Poll",
|
||||||
|
"collapsePoll": "Collapse Poll",
|
||||||
|
"embedView": "Embed View",
|
||||||
|
"embedUri": "Embed URI",
|
||||||
|
"aspectRatio": "Aspect Ratio",
|
||||||
|
"renderer": "Renderer",
|
||||||
|
"addEmbed": "Add Embed",
|
||||||
|
"editEmbed": "Edit Embed",
|
||||||
|
"deleteEmbed": "Delete Embed",
|
||||||
|
"deleteEmbedConfirm": "Are you sure you want to delete this embed?",
|
||||||
|
"currentEmbed": "Current Embed",
|
||||||
|
"noEmbed": "No embed yet",
|
||||||
|
"save": "Save",
|
||||||
|
"webView": "Web View",
|
||||||
|
"settingsDefaultPool": "Default file pool",
|
||||||
|
"settingsDefaultPoolHelper": "Select the default storage pool for file uploads",
|
||||||
|
"uploadFile": "Upload File",
|
||||||
|
"authDeviceChallenges": "Device Usage",
|
||||||
|
"authDeviceHint": "Swipe left to edit label, swipe right to logout device.",
|
||||||
|
"settingsMessageDisplayStyle": "Message Display Style",
|
||||||
|
"settingsWindowOpacity": "Window Opacity",
|
||||||
|
"auto": "Auto",
|
||||||
|
"manual": "Manual",
|
||||||
|
"iframeCode": "Iframe Code",
|
||||||
|
"iframeCodeHint": "<iframe src=\"...\" width=\"...\" height=\"...\">",
|
||||||
|
"parseIframe": "Parse Iframe",
|
||||||
|
"messageActions": "Message Actions",
|
||||||
|
"messageContent": "Message Content",
|
||||||
|
"viewEmbedLoadHint": "Tap to load",
|
||||||
|
"levelingStage1": "Novice",
|
||||||
|
"levelingStage2": "Apprentice",
|
||||||
|
"levelingStage3": "Journeyman",
|
||||||
|
"levelingStage4": "Adept",
|
||||||
|
"levelingStage5": "Expert",
|
||||||
|
"levelingStage6": "Master",
|
||||||
|
"levelingStage7": "Grandmaster",
|
||||||
|
"levelingStage8": "Legend",
|
||||||
|
"levelingStage9": "Myth",
|
||||||
|
"levelingStage10": "Immortal",
|
||||||
|
"levelingStage11": "Divine",
|
||||||
|
"levelingStage12": "Transcendent",
|
||||||
|
"uploadAttachment": "Upload Attachment",
|
||||||
|
"attachmentPreview": "Attachment Preview",
|
||||||
|
"selectPool": "Select Pool",
|
||||||
|
"choosePool": "Choose a pool",
|
||||||
|
"errorLoadingPools": "Error loading pools",
|
||||||
|
"quotaCostInfo": "This upload will cost {} quota points",
|
||||||
|
"uploadConstraints": "Upload Constraints",
|
||||||
|
"fileSizeExceeded": "File size exceeds the maximum limit of {}",
|
||||||
|
"fileTypeNotAccepted": "File type is not accepted by this pool",
|
||||||
|
"files": "Files",
|
||||||
|
"confirmDeleteFile": "Are you sure you want to delete this file?",
|
||||||
|
"deleteFile": "Delete File",
|
||||||
|
"failedToDeleteFile": "Failed to delete file",
|
||||||
|
"drive": "Drive",
|
||||||
|
"allPools": "All Pools",
|
||||||
|
"includeRecycled": "Include Recycled",
|
||||||
|
"confirmDeleteRecycledFiles": "Are you sure you want to delete all recycled files?",
|
||||||
|
"deleteRecycledFiles": "Delete Recycled Files",
|
||||||
|
"recycledFilesDeleted": "Recycled files deleted successfully",
|
||||||
|
"failedToDeleteRecycledFiles": "Failed to delete recycled files",
|
||||||
|
"upload": "Upload",
|
||||||
|
"updateAvailable": "Update available",
|
||||||
|
"noChangelogProvided": "No changelog provided.",
|
||||||
|
"useSecondarySourceForDownload": "Use secondary source for download",
|
||||||
|
"installUpdate": "Install update",
|
||||||
|
"openReleasePage": "Open release page",
|
||||||
|
"postCompose": "Compose Post",
|
||||||
|
"postPublish": "Publish Post",
|
||||||
|
"restoreDraftTitle": "Restore Draft",
|
||||||
|
"restoreDraftMessage": "A draft was found. Do you want to restore it?",
|
||||||
|
"draft": "Draft",
|
||||||
|
"purchaseGift": "Purchase Gift",
|
||||||
|
"selectRecipient": "Select Recipient",
|
||||||
|
"changeRecipient": "Change Recipient",
|
||||||
|
"addMessage": "Add Message",
|
||||||
|
"skipRecipient": "Skip Recipient",
|
||||||
|
"giftSubscriptions": "Gift Subscriptions",
|
||||||
|
"purchaseAGift": "Purchase a Gift",
|
||||||
|
"redeemAGift": "Redeem a Gift",
|
||||||
|
"giftHistory": "Gift History",
|
||||||
|
"sentGifts": "Sent Gifts",
|
||||||
|
"receivedGifts": "Received Gifts",
|
||||||
|
"noSentGifts": "No sent gifts",
|
||||||
|
"noReceivedGifts": "No received gifts",
|
||||||
|
"stellarGift": "Stellar Gift",
|
||||||
|
"novaGift": "Nova Gift",
|
||||||
|
"supernovaGift": "Supernova Gift",
|
||||||
|
"sameAsMembership": "Same as membership",
|
||||||
|
"enterGiftCodeToRedeem": "Enter gift code to redeem",
|
||||||
|
"enterGiftCode": "Enter gift code",
|
||||||
|
"giftPurchased": "Gift Purchased!",
|
||||||
|
"shareCodeWithRecipient": "Share this code with the recipient to redeem the gift.",
|
||||||
|
"openGiftAnyoneCanRedeem": "This is an open gift that anyone can redeem.",
|
||||||
|
"ok": "OK",
|
||||||
|
"selectedRecipient": "Selected recipient",
|
||||||
|
"noRecipientSelected": "No recipient selected",
|
||||||
|
"thisWillBeAnOpenGift": "This will be an open gift",
|
||||||
|
"personalMessage": "Personal Message",
|
||||||
|
"addPersonalMessageForRecipient": "Add a personal message for the recipient",
|
||||||
|
"cancel": "Cancel",
|
||||||
|
"giftStatusCreated": "Created",
|
||||||
|
"giftStatusSent": "Sent",
|
||||||
|
"giftStatusRedeemed": "Redeemed",
|
||||||
|
"giftStatusCancelled": "Cancelled",
|
||||||
|
"giftStatusExpired": "Expired",
|
||||||
|
"giftStatusUnknown": "Unknown",
|
||||||
|
"giftCodeCopiedToClipboard": "Gift code copied to clipboard",
|
||||||
|
"codeLabel": "Code: ",
|
||||||
|
"subscriptionLabel": "Subscription: ",
|
||||||
|
"toLabel": "To: ",
|
||||||
|
"fromLabel": "From: ",
|
||||||
|
"messageLabel": "Message: ",
|
||||||
|
"giftRedeemed": "Gift Redeemed!",
|
||||||
|
"giftRedeemedSuccessfully": "You have successfully redeemed the gift. Your new subscription is now active.",
|
||||||
|
"cancelGift": "Cancel Gift",
|
||||||
|
"cancelGiftConfirm": "Are you sure you want to cancel this gift? This action cannot be undone.",
|
||||||
|
"giftCancelledSuccessfully": "Gift cancelled successfully",
|
||||||
|
"createFund": "Create Fund",
|
||||||
|
"fundAmount": "Fund Amount",
|
||||||
|
"enterAmount": "Enter Amount",
|
||||||
|
"selectCurrency": "Select Currency",
|
||||||
|
"splitType": "Split Type",
|
||||||
|
"evenSplit": "Even Split",
|
||||||
|
"equalAmountEach": "Equal amount for each recipient",
|
||||||
|
"randomSplit": "Random Split",
|
||||||
|
"randomAmountEach": "Random amount for each recipient",
|
||||||
|
"recipientCount": "Recipient Count",
|
||||||
|
"numberOfRecipients": "Number of Recipients",
|
||||||
|
"addPersonalMessageForRecipients": "Add a personal message for recipients",
|
||||||
|
"invalidAmount": "Invalid amount",
|
||||||
|
"invalidRecipientCount": "Invalid recipient count",
|
||||||
|
"fundOverview": "Fund Overview",
|
||||||
|
"totalFundsSent": "Total Funds Sent",
|
||||||
|
"totalFundsReceived": "Total Funds Received",
|
||||||
|
"transactions": "Transactions",
|
||||||
|
"myFunds": "My Funds",
|
||||||
|
"availableFunds": "Available Funds",
|
||||||
|
"fundStatusCreated": "Created",
|
||||||
|
"fundStatusPartial": "Partially Claimed",
|
||||||
|
"fundStatusCompleted": "Fully Claimed",
|
||||||
|
"fundStatusExpired": "Expired",
|
||||||
|
"fundStatusUnknown": "Unknown",
|
||||||
|
"recipients": "Recipients",
|
||||||
|
"fundClaimedSuccessfully": "Fund claimed successfully!",
|
||||||
|
"claim": "Claim",
|
||||||
|
"noFundsCreated": "No funds created yet",
|
||||||
|
"createYourFirstFund": "Create your first fund to get started",
|
||||||
|
"noAvailableFunds": "No available funds",
|
||||||
|
"fundsWillAppearHere": "Funds you can claim will appear here",
|
||||||
|
"fundCreatedSuccessfully": "Fund created successfully!",
|
||||||
|
"selectRecipients": "Select Recipients",
|
||||||
|
"noRecipientsSelected": "No recipients selected",
|
||||||
|
"selectRecipientsToSendFund": "Select recipients to send the fund to",
|
||||||
|
"addRecipient": "Add Recipient",
|
||||||
|
"addMoreRecipients": "Add More Recipients",
|
||||||
|
"transactionDetails": "Transaction Details",
|
||||||
|
"remarks": "Remarks",
|
||||||
|
"payer": "Payer",
|
||||||
|
"payee": "Payee",
|
||||||
|
"transactionType": "Transaction Type",
|
||||||
|
"transfer": "Transfer",
|
||||||
|
"payment": "Payment",
|
||||||
|
"systemWallet": "System Wallet",
|
||||||
|
"date": "Date",
|
||||||
|
"createTransfer": "Create Transfer",
|
||||||
|
"transferAmount": "Transfer Amount",
|
||||||
|
"selectPayee": "Select Payee",
|
||||||
|
"selectedPayee": "Selected Payee",
|
||||||
|
"noPayeeSelected": "No payee selected",
|
||||||
|
"selectPayeeToTransfer": "Select payee to transfer to",
|
||||||
|
"addRemark": "Add Remark",
|
||||||
|
"transferRemark": "Transfer Remark",
|
||||||
|
"addRemarkForTransfer": "Add remark for transfer",
|
||||||
|
"enterPinToConfirmTransfer": "Enter your 6-digit PIN to confirm transfer",
|
||||||
|
"transferCreatedSuccessfully": "Transfer created successfully!",
|
||||||
|
"postUpdate": "Update",
|
||||||
|
"fileMetadata": "File Metadata",
|
||||||
|
"resend": "Resend",
|
||||||
|
"fileInfoTitle": "File Information",
|
||||||
|
"download": "Download",
|
||||||
|
"info": "Info",
|
||||||
|
"noStickers": "No Stickers",
|
||||||
|
"noStickersInPack": "This pack does not contains stickers",
|
||||||
|
"noStickerPacks": "No Sticker Packs",
|
||||||
|
"refresh": "Refresh",
|
||||||
|
"spoiler": "Spoiler",
|
||||||
|
"activityHeatmap": "Activity Heatmap",
|
||||||
|
"custom": "Custom",
|
||||||
|
"usernameColor": "Username Color",
|
||||||
|
"colorType": "Color Type",
|
||||||
|
"plain": "Plain",
|
||||||
|
"gradient": "Gradient",
|
||||||
|
"colorValue": "Color Value",
|
||||||
|
"gradientDirection": "Gradient Direction",
|
||||||
|
"gradientDirectionToRight": "To Right",
|
||||||
|
"gradientDirectionToLeft": "To Left",
|
||||||
|
"gradientDirectionToBottom": "To Bottom",
|
||||||
|
"gradientDirectionToTop": "To Top",
|
||||||
|
"gradientDirectionToBottomRight": "To Bottom Right",
|
||||||
|
"gradientDirectionToBottomLeft": "To Bottom Left",
|
||||||
|
"gradientDirectionToTopRight": "To Top Right",
|
||||||
|
"gradientDirectionToTopLeft": "To Top Left",
|
||||||
|
"gradientColors": "Gradient Colors",
|
||||||
|
"color": "Color",
|
||||||
|
"addColor": "Add Color",
|
||||||
|
"preview": "Preview",
|
||||||
|
"availableWithYourPlan": "Available with your plan",
|
||||||
|
"upgradeRequired": "Upgrade required",
|
||||||
|
"settingsDisableAnimation": "Disable Animation",
|
||||||
|
"addTag": "Add Tag",
|
||||||
|
"postFeaturedOn": "Post featured on {}",
|
||||||
|
"messageSentAt": "Sent at {}",
|
||||||
|
"myTickets": "My Tickets",
|
||||||
|
"drawHistory": "Draw History",
|
||||||
|
"lottery": "Lottery",
|
||||||
|
"noLotteryTickets": "No lottery tickets yet",
|
||||||
|
"buyYourFirstTicket": "Buy your first lottery ticket to get started!",
|
||||||
|
"buyTicket": "Buy Ticket",
|
||||||
|
"ticketNumbers": "Numbers: {}, Special: {}",
|
||||||
|
"cost": "Cost",
|
||||||
|
"multiplier": "Multiplier",
|
||||||
|
"prizeWon": "Prize Won",
|
||||||
|
"pending": "Pending",
|
||||||
|
"drawn": "Drawn",
|
||||||
|
"won": "Won",
|
||||||
|
"lost": "Lost",
|
||||||
|
"noDrawHistory": "No draw history yet",
|
||||||
|
"buyLotteryTicket": "Buy Lottery Ticket",
|
||||||
|
"selectNumbers": "Select Numbers",
|
||||||
|
"select5UniqueNumbers": "Select 5 unique numbers",
|
||||||
|
"selectSpecialNumber": "Select Special Number",
|
||||||
|
"selectMultiplier": "Select Multiplier",
|
||||||
|
"baseCost": "Base Cost",
|
||||||
|
"totalCost": "Total Cost",
|
||||||
|
"prizeStructure": "Prize Structure",
|
||||||
|
"enterPinToConfirmPurchase": "Enter your PIN to confirm purchase",
|
||||||
|
"ticketPurchasedSuccessfully": "Ticket purchased successfully!",
|
||||||
|
"winningNumbers": "Winning Numbers",
|
||||||
|
"specialNumber": "Special Number",
|
||||||
|
"totalTickets": "Total Tickets",
|
||||||
|
"totalWinners": "Total Winners",
|
||||||
|
"prizePool": "Prize Pool",
|
||||||
|
"enterPinToConfirmPayment": "Enter your PIN code to confirm payment",
|
||||||
|
"purchase": "Purchase",
|
||||||
|
"multiplierLabel": "Multiplier",
|
||||||
|
"specialOnly": "Special Only",
|
||||||
|
"matches": "Matches",
|
||||||
|
"thoughtDefaultTopic": "Reflection",
|
||||||
|
"thoughtAiName": "SN-chan",
|
||||||
|
"thoughtUserName": "You",
|
||||||
|
"thoughtStreamingHint": "Sn-chan is thinking...",
|
||||||
|
"thoughtInputHint": "Ask sn-chan anything...",
|
||||||
|
"thoughtNewConversation": "Start New Conversation",
|
||||||
|
"thoughtParseError": "Failed to parse AI response",
|
||||||
|
"thoughtFunctionCall": "Function Call",
|
||||||
|
"aiThought": "AI Thought",
|
||||||
|
"aiThoughtTitle": "Let sn-chan think",
|
||||||
|
"postReferenceUnavailable": "Referenced post is unavailable",
|
||||||
|
"fabLocation": "FAB Location"
|
||||||
}
|
}
|
||||||
1079
assets/i18n/es-ES.json
Normal file
1079
assets/i18n/ja-JP.json
Normal file
1079
assets/i18n/ko-KR.json
Normal file
@@ -668,7 +668,6 @@
|
|||||||
"publisherFeatureDevelopDescription": "为你的开发者解锁包括应用套件,API 及更多开发功能。",
|
"publisherFeatureDevelopDescription": "为你的开发者解锁包括应用套件,API 及更多开发功能。",
|
||||||
"publisherFeatureDevelopHint": "目前该功能还在开发中,你需要邀请才可解锁。",
|
"publisherFeatureDevelopHint": "目前该功能还在开发中,你需要邀请才可解锁。",
|
||||||
"learnMore": "了解更多",
|
"learnMore": "了解更多",
|
||||||
"discoverWebArticles": "来自站外的文章",
|
|
||||||
"webArticlesStand": "文章亭",
|
"webArticlesStand": "文章亭",
|
||||||
"about": "关于",
|
"about": "关于",
|
||||||
"somethingWentWrong": "发生了一些错误",
|
"somethingWentWrong": "发生了一些错误",
|
||||||
@@ -691,8 +690,6 @@
|
|||||||
"sharePostPhoto": "通过图片分享帖子",
|
"sharePostPhoto": "通过图片分享帖子",
|
||||||
"wouldYouLikeToNavigateToChat": "你想要前往聊天页面吗?",
|
"wouldYouLikeToNavigateToChat": "你想要前往聊天页面吗?",
|
||||||
"abuseReports": "举报",
|
"abuseReports": "举报",
|
||||||
"discoverRealms": "发现领域",
|
|
||||||
"discoverPublishers": "发现发布者",
|
|
||||||
"membershipCancel": "取消会员订阅",
|
"membershipCancel": "取消会员订阅",
|
||||||
"membershipCancelConfirm": "你确定要取消会员订阅吗?",
|
"membershipCancelConfirm": "你确定要取消会员订阅吗?",
|
||||||
"membershipCancelHint": "你确定要取消会员订阅吗?你将不会再次被扣费。你的会员资格将在当前计费周期结束前保持有效。并且你将无法重新订阅,直到当前订阅结束。",
|
"membershipCancelHint": "你确定要取消会员订阅吗?你将不会再次被扣费。你的会员资格将在当前计费周期结束前保持有效。并且你将无法重新订阅,直到当前订阅结束。",
|
||||||
@@ -811,5 +808,287 @@
|
|||||||
"filesListAdditional": {
|
"filesListAdditional": {
|
||||||
"one": "+{} 个文件被折叠",
|
"one": "+{} 个文件被折叠",
|
||||||
"other": "+{} 个文件被折叠"
|
"other": "+{} 个文件被折叠"
|
||||||
}
|
},
|
||||||
|
"pollQuestions": "问题",
|
||||||
|
"pollAnswerSubmitted": "调查问卷已提交。",
|
||||||
|
"modifyAnswers": "修改问卷",
|
||||||
|
"back": "返回",
|
||||||
|
"submit": "提交",
|
||||||
|
"pollOptionDefaultLabel": "选项 1",
|
||||||
|
"pollUpdated": "投票已更新。",
|
||||||
|
"pollCreated": "投票已创建。",
|
||||||
|
"pollCreate": "创建投票",
|
||||||
|
"pollEdit": "编辑投票",
|
||||||
|
"pollPreviewJsonDebug": "调试预览",
|
||||||
|
"pollTitleRequired": "标题不可为空",
|
||||||
|
"pollEndDateOptional": "结束日期和时间 (可选)",
|
||||||
|
"notSet": "未设置",
|
||||||
|
"pick": "选择",
|
||||||
|
"clear": "清除",
|
||||||
|
"questions": "问题",
|
||||||
|
"pollAddQuestion": "新增问题",
|
||||||
|
"pollQuestionTypeSingleChoice": "单选",
|
||||||
|
"pollQuestionTypeMultipleChoice": "多选",
|
||||||
|
"pollQuestionTypeFreeText": "自由文本",
|
||||||
|
"pollQuestionTypeYesNo": "是/否",
|
||||||
|
"pollQuestionTypeRating": "评价",
|
||||||
|
"pollNoQuestionsYet": "没有问题",
|
||||||
|
"pollNoQuestionsHint": "点击「添加问题」开始建立您的问卷调查。",
|
||||||
|
"pollDebugPreview": "调试预览",
|
||||||
|
"pollUntitledQuestion": "无标题的问题",
|
||||||
|
"moveUp": "上移",
|
||||||
|
"moveDown": "下移",
|
||||||
|
"required": "必填项",
|
||||||
|
"pollQuestionTitle": "题目",
|
||||||
|
"pollQuestionTitleRequired": "题目是必填项",
|
||||||
|
"pollQuestionDescriptionOptional": "题目描述(可选)",
|
||||||
|
"options": "选项",
|
||||||
|
"pollAddOption": "添加选项",
|
||||||
|
"pollOptionLabel": "选项标签",
|
||||||
|
"pollLongTextAnswerPreview": "长文本答案 (预览)",
|
||||||
|
"pollShortTextAnswerPreview": "短文本答案 (预览)",
|
||||||
|
"award": "赞赏",
|
||||||
|
"awardPost": "赞赏帖子",
|
||||||
|
"awardMessage": "消息",
|
||||||
|
"awardMessageHint": "输入您的赞赏信息……",
|
||||||
|
"awardAttitude": "态度",
|
||||||
|
"awardAttitudePositive": "积极",
|
||||||
|
"awardAttitudeNegative": "消极的",
|
||||||
|
"awardAmount": "金额",
|
||||||
|
"awardAmountHint": "输入金额……",
|
||||||
|
"awardAmountRequired": "「金额」为必填字段",
|
||||||
|
"awardAmountInvalid": "请输入有效金额",
|
||||||
|
"awardMessageTooLong": "消息太长(最多4096个字符)",
|
||||||
|
"awardSuccess": "奖励已成功发送!",
|
||||||
|
"awardSubmit": "赞赏",
|
||||||
|
"awardPostPreview": "帖子预览",
|
||||||
|
"awardNoContent": "暂无内容",
|
||||||
|
"awardByPublisher": "由 {} 发表",
|
||||||
|
"awardBenefits": "赞赏福利",
|
||||||
|
"awardBenefitsDescription": "为该帖子授予奖励可以提升其价值和曝光度。价值更高的帖子更有可能在社区中被推荐和突出显示。",
|
||||||
|
"checkInResultLevel5": "生日快乐 🥳",
|
||||||
|
"region": "区域",
|
||||||
|
"accountRegionHint": "该地区将用于内容交付和本地化。",
|
||||||
|
"settingsCustomFontsHelper": "用逗号分隔。",
|
||||||
|
"settingsBackgroundImageEnable": "显示背景图片",
|
||||||
|
"settingsDataSavingMode": "流量节省模式",
|
||||||
|
"dataSavingHint": "流量节省模式",
|
||||||
|
"postTypePost": "帖子",
|
||||||
|
"searchDrafts": "搜索草稿……",
|
||||||
|
"noSearchResults": "无搜索结果",
|
||||||
|
"contactMethodMakePublic": "设为公开",
|
||||||
|
"contactMethodMakePrivate": "设为仅自己可见",
|
||||||
|
"contactMethodPublic": "公开",
|
||||||
|
"contactMethodPrivate": "私密",
|
||||||
|
"discoverRealms": "发现领域",
|
||||||
|
"discoverPublishers": "发现发布者",
|
||||||
|
"discoverShuffledPost": "随机的帖子",
|
||||||
|
"projects": "项目",
|
||||||
|
"noProjects": "未找到项目。",
|
||||||
|
"deleteProject": "删除项目",
|
||||||
|
"deleteProjectHint": "确定要删除此项目吗?此操作无法撤销。",
|
||||||
|
"createProject": "新建项目",
|
||||||
|
"editProject": "编辑项目",
|
||||||
|
"projectDetails": "项目详情",
|
||||||
|
"createBot": "创建机器人",
|
||||||
|
"bots": "机器人",
|
||||||
|
"noBots": "暂无机器人。",
|
||||||
|
"deleteBotHint": "您确定要删除此机器人吗?此操作无法撤消。",
|
||||||
|
"deleteBot": "删除机器人",
|
||||||
|
"discoverWebArticles": "来自站外的文章",
|
||||||
|
"messageJumpNotLoaded": "引用的消息没有被加载,无法跳转。",
|
||||||
|
"postUnlinkRealm": "不关联领域",
|
||||||
|
"postSlug": "别名",
|
||||||
|
"postSlugHint": "这个别名可以用于在网页通过 URL 浏览到你的帖子,它应该在同一发布者中是唯一。",
|
||||||
|
"attachmentOnDevice": "离线",
|
||||||
|
"attachmentOnCloud": "在线",
|
||||||
|
"attachments": "附件",
|
||||||
|
"publisherCollabInvitation": "协作邀请",
|
||||||
|
"publisherCollabInvitationCount": {
|
||||||
|
"zero": "无邀请",
|
||||||
|
"one": "{} 个可用邀请",
|
||||||
|
"other": "{} 个可用邀请"
|
||||||
|
},
|
||||||
|
"failedToLoadUserInfo": "加载用户信息失败",
|
||||||
|
"failedToLoadUserInfoNetwork": "这看起来是个网络问题,你可以按下面的按钮来重试。",
|
||||||
|
"failedToLoadUserInfoUnauthorized": "看来您的会话已被注销或不再可用,如果您愿意,您仍然可以再次尝试获取用户信息。",
|
||||||
|
"okay": "了解",
|
||||||
|
"postDetail": "帖子详情",
|
||||||
|
"postCount": {
|
||||||
|
"zero": "没有帖子",
|
||||||
|
"one": "{} 帖子",
|
||||||
|
"other": "{} 帖子"
|
||||||
|
},
|
||||||
|
"mimeType": "类型",
|
||||||
|
"fileSize": "大小",
|
||||||
|
"fileHash": "哈希",
|
||||||
|
"exifData": "EXIF 数据",
|
||||||
|
"postShuffle": "随机帖子",
|
||||||
|
"leveling": "等级",
|
||||||
|
"levelingHistory": "经验记录",
|
||||||
|
"stellarProgram": "恒星计划",
|
||||||
|
"socialCredits": "社会信用点",
|
||||||
|
"credits": "信用",
|
||||||
|
"creditsStatus": "积分状态",
|
||||||
|
"socialCreditsDescription": "社会信用是 Solar Network 评价用户的一种方式。它基于用户的行为和互动来计算。以 100 分为基准,分数越高表示用户在社区中的信誉越好。分数会随着时间的推移而变化,反映用户的最新行为。信用等级高的用户可以享受到更多的福利,反之的用户部份功能可能受到限制。",
|
||||||
|
"socialCreditsLevelPoor": "糟糕",
|
||||||
|
"socialCreditsLevelNormal": "正常",
|
||||||
|
"socialCreditsLevelGood": "良好",
|
||||||
|
"socialCreditsLevelExcellent": "优秀",
|
||||||
|
"orderByPopularity": "按热度排序",
|
||||||
|
"orderByReleaseDate": "按发布日期排序",
|
||||||
|
"editBot": "编辑机器人",
|
||||||
|
"botAutomatedBy": "由 {} 自动化",
|
||||||
|
"botDetails": "机器人详情",
|
||||||
|
"overview": "总览",
|
||||||
|
"keys": "密钥",
|
||||||
|
"botNotFound": "机器人未找到。",
|
||||||
|
"newBotKey": "新建密钥",
|
||||||
|
"newBotKeyHint": "输入新密钥的名称,密钥只会显示一次。",
|
||||||
|
"revokeBotKey": "撤销密钥",
|
||||||
|
"revokeBotKeyHint": "你确定要撤销这个密钥?这个操作无法撤回,所有使用该密钥的应用程式会停止工作。",
|
||||||
|
"noBotKeys": "还没有密钥。",
|
||||||
|
"revoke": "撤销",
|
||||||
|
"keyName": "密钥名称",
|
||||||
|
"newKeyGenerated": "新密钥已生成",
|
||||||
|
"copyKeyHint": "请安全的保存该密钥,你不会再次看到它。",
|
||||||
|
"rotateKey": "旋转密钥",
|
||||||
|
"rotateBotKey": "旋转密钥",
|
||||||
|
"rotateBotKeyHint": "你确认要旋转这个密钥?久的密钥会立即失效,该操作无法撤销。",
|
||||||
|
"webFeedArticleCount": {
|
||||||
|
"zero": "没有文章",
|
||||||
|
"one": "{} 篇文章",
|
||||||
|
"other": "{} 篇文章"
|
||||||
|
},
|
||||||
|
"webFeedSubscribed": "你已经订阅了这个源",
|
||||||
|
"webFeedUnsubscribed": "你已经取消订阅这个源",
|
||||||
|
"appDetails": "应用详情",
|
||||||
|
"secrets": "密钥",
|
||||||
|
"appNotFound": "应用未找到。",
|
||||||
|
"secretCopied": "密钥已复制到剪贴板。",
|
||||||
|
"deleteSecret": "删除密钥",
|
||||||
|
"deleteSecretHint": "您确定要删除此密钥吗?此操作无法撤销。",
|
||||||
|
"generateSecret": "生成新密钥",
|
||||||
|
"createdAt": "创建于 {}",
|
||||||
|
"newSecretGenerated": "已生成新密钥",
|
||||||
|
"copySecretHint": "请复制此密钥并将其存放在安全的地方。您将无法再次看到它。",
|
||||||
|
"expiresIn": "过期时间(秒)",
|
||||||
|
"isOidc": "OIDC 兼容",
|
||||||
|
"pinPost": "置顶帖子",
|
||||||
|
"unpinPost": "取消置顶",
|
||||||
|
"pinnedPost": "已置顶",
|
||||||
|
"publisherPage": "发布者页面",
|
||||||
|
"realmPage": "领域页面",
|
||||||
|
"replyPage": "回复页面",
|
||||||
|
"pinPostPublisherHint": "将此帖子置顶于发布者页面",
|
||||||
|
"pinPostRealmHint": "将此帖子置顶于领域页面",
|
||||||
|
"pinPostRealmDisabledHint": "这个帖子不属于任何领域",
|
||||||
|
"pinPostReplyHint": "将此帖子置顶于回复页面",
|
||||||
|
"pinPostReplyDisabledHint": "这个帖子不是回复",
|
||||||
|
"pin": "置顶",
|
||||||
|
"unpinPostHint": "你确定要取消置顶该帖子吗?",
|
||||||
|
"all": "全部",
|
||||||
|
"statusPresent": "至今",
|
||||||
|
"accountAutomated": "机器人",
|
||||||
|
"chatBreakClearButton": "清除",
|
||||||
|
"chatBreak5m": "5 分钟",
|
||||||
|
"chatBreak10m": "10 分钟",
|
||||||
|
"chatBreak15m": "15 分钟",
|
||||||
|
"chatBreak30m": "30 分钟",
|
||||||
|
"chatBreakCustomMinutes": "自定义(分钟)",
|
||||||
|
"errorGeneric": "错误: {}",
|
||||||
|
"searchMessages": "搜索消息",
|
||||||
|
"messagesCount": "{} 消息",
|
||||||
|
"dotSeparator": "·",
|
||||||
|
"roleValidationHint": "成员角色必须设置在0到100之间",
|
||||||
|
"searchMessagesHint": "搜索消息……",
|
||||||
|
"searchLinks": "链接",
|
||||||
|
"searchAttachments": "附件",
|
||||||
|
"noMessagesFound": "未找到消息",
|
||||||
|
"openInBrowser": "在浏览器中打开",
|
||||||
|
"highlightPost": "精选帖子",
|
||||||
|
"filters": "过滤器",
|
||||||
|
"apply": "申请",
|
||||||
|
"pubName": "题目名称",
|
||||||
|
"realm": "领域",
|
||||||
|
"shuffle": "随机",
|
||||||
|
"pinned": "已置顶",
|
||||||
|
"noResultsFound": "未找到结果",
|
||||||
|
"toggleFilters": "切换过滤器",
|
||||||
|
"notableDayNext": "距离 {} 还有",
|
||||||
|
"expandPoll": "展开投票",
|
||||||
|
"collapsePoll": "折叠投票",
|
||||||
|
"embedView": "嵌入视图",
|
||||||
|
"embedUri": "嵌入的 URI",
|
||||||
|
"aspectRatio": "长宽比",
|
||||||
|
"renderer": "渲染器",
|
||||||
|
"addEmbed": "添加嵌入",
|
||||||
|
"editEmbed": "编辑嵌入",
|
||||||
|
"deleteEmbed": "删除嵌入",
|
||||||
|
"deleteEmbedConfirm": "您确定要删除此嵌入吗?",
|
||||||
|
"currentEmbed": "当前嵌入",
|
||||||
|
"noEmbed": "尚未嵌入",
|
||||||
|
"save": "保存",
|
||||||
|
"webView": "Web 视图",
|
||||||
|
"settingsDefaultPool": "选择文件池",
|
||||||
|
"settingsDefaultPoolHelper": "为文件上传选择一个默认池",
|
||||||
|
"uploadFile": "上传文件",
|
||||||
|
"authDeviceChallenges": "设备活动",
|
||||||
|
"authDeviceHint": "向左轻扫以编辑标签,向右轻扫以注销登录设备。",
|
||||||
|
"settingsMessageDisplayStyle": "消息样式",
|
||||||
|
"auto": "自动",
|
||||||
|
"manual": "手动",
|
||||||
|
"iframeCode": "Iframe代码",
|
||||||
|
"iframeCodeHint": "<iframe src=\"...\" width=\"...\" height=\"...\">",
|
||||||
|
"parseIframe": "解析Iframe",
|
||||||
|
"messageActions": "消息选项",
|
||||||
|
"viewEmbedLoadHint": "点击以加载",
|
||||||
|
"levelingStage1": "新手",
|
||||||
|
"levelingStage2": "学徒",
|
||||||
|
"levelingStage3": "熟练工",
|
||||||
|
"levelingStage4": "行家",
|
||||||
|
"levelingStage5": "专家",
|
||||||
|
"levelingStage6": "大师",
|
||||||
|
"levelingStage7": "宗师",
|
||||||
|
"levelingStage8": "传奇",
|
||||||
|
"levelingStage9": "神话",
|
||||||
|
"levelingStage10": "不朽",
|
||||||
|
"levelingStage11": "神圣",
|
||||||
|
"levelingStage12": "超凡",
|
||||||
|
"uploadAttachment": "上传附件",
|
||||||
|
"attachmentPreview": "附件预览",
|
||||||
|
"selectPool": "选择储存池",
|
||||||
|
"choosePool": "选择一个储存池",
|
||||||
|
"errorLoadingPools": "加载池时出错",
|
||||||
|
"quotaCostInfo": "此上传将消耗 {} 配额点",
|
||||||
|
"uploadConstraints": "上传限制",
|
||||||
|
"fileSizeExceeded": "文件大小超过了 {} 的最大限制",
|
||||||
|
"fileTypeNotAccepted": "此储存池不接受该文件类型",
|
||||||
|
"files": "附件",
|
||||||
|
"confirmDeleteFile": "你确定要删除此文件吗?",
|
||||||
|
"deleteFile": "删除文件",
|
||||||
|
"failedToDeleteFile": "删除文件失败",
|
||||||
|
"drive": "云盘",
|
||||||
|
"allPools": "所有池",
|
||||||
|
"includeRecycled": "包括已回收的文件",
|
||||||
|
"confirmDeleteRecycledFiles": "你确定要删除所有被回收的文件吗?",
|
||||||
|
"deleteRecycledFiles": "删除被回收的文件",
|
||||||
|
"recycledFilesDeleted": "被回收文件成功删除",
|
||||||
|
"failedToDeleteRecycledFiles": "删除被回收文件失败",
|
||||||
|
"upload": "上传",
|
||||||
|
"systemWallet": "中央统筹",
|
||||||
|
"postCompose": "撰写帖子",
|
||||||
|
"postPublish": "发布帖子",
|
||||||
|
"restoreDraftTitle": "恢复草稿",
|
||||||
|
"restoreDraftMessage": "发现了一个草稿。你想要恢复它吗?",
|
||||||
|
"draft": "草稿",
|
||||||
|
"thoughtDefaultTopic": "寻思",
|
||||||
|
"thoughtAiName": "SN 酱",
|
||||||
|
"thoughtUserName": "您",
|
||||||
|
"thoughtStreamingHint": "SN 酱正在思考...",
|
||||||
|
"thoughtInputHint": "问 SN 酱任何问题...",
|
||||||
|
"thoughtNewConversation": "开始新对话",
|
||||||
|
"thoughtParseError": "解析 AI 响应失败",
|
||||||
|
"aiThought": "寻思",
|
||||||
|
"aiThoughtTitle": "让 SN 酱寻思寻思"
|
||||||
}
|
}
|
||||||
1079
assets/i18n/zh-OG.json
Normal file
@@ -116,7 +116,7 @@
|
|||||||
},
|
},
|
||||||
"postHasAttachments": {
|
"postHasAttachments": {
|
||||||
"one": "{} 個附件",
|
"one": "{} 個附件",
|
||||||
"other": "{}個附件"
|
"other": "{} 個附件"
|
||||||
},
|
},
|
||||||
"edited": "已編輯",
|
"edited": "已編輯",
|
||||||
"addVideo": "添加視頻",
|
"addVideo": "添加視頻",
|
||||||
@@ -668,7 +668,6 @@
|
|||||||
"publisherFeatureDevelopDescription": "為你的開發者解鎖包括應用套件,API 及更多開發功能。",
|
"publisherFeatureDevelopDescription": "為你的開發者解鎖包括應用套件,API 及更多開發功能。",
|
||||||
"publisherFeatureDevelopHint": "目前該功能還在開發中,你需要邀請才可解鎖。",
|
"publisherFeatureDevelopHint": "目前該功能還在開發中,你需要邀請才可解鎖。",
|
||||||
"learnMore": "瞭解更多",
|
"learnMore": "瞭解更多",
|
||||||
"discoverWebArticles": "來自站外的文章",
|
|
||||||
"webArticlesStand": "文章亭",
|
"webArticlesStand": "文章亭",
|
||||||
"about": "關於",
|
"about": "關於",
|
||||||
"somethingWentWrong": "發生了一些錯誤",
|
"somethingWentWrong": "發生了一些錯誤",
|
||||||
@@ -691,8 +690,6 @@
|
|||||||
"sharePostPhoto": "通過圖片分享帖子",
|
"sharePostPhoto": "通過圖片分享帖子",
|
||||||
"wouldYouLikeToNavigateToChat": "你想要前往聊天頁面嗎?",
|
"wouldYouLikeToNavigateToChat": "你想要前往聊天頁面嗎?",
|
||||||
"abuseReports": "舉報",
|
"abuseReports": "舉報",
|
||||||
"discoverRealms": "發現領域",
|
|
||||||
"discoverPublishers": "發現發佈者",
|
|
||||||
"membershipCancel": "取消會員訂閱",
|
"membershipCancel": "取消會員訂閱",
|
||||||
"membershipCancelConfirm": "你確定要取消會員訂閱嗎?",
|
"membershipCancelConfirm": "你確定要取消會員訂閱嗎?",
|
||||||
"membershipCancelHint": "你確定要取消會員訂閱嗎?你將不會再次被扣費。你的會員資格將在當前計費週期結束前保持有效。並且你將無法重新訂閱,直到當前訂閱結束。",
|
"membershipCancelHint": "你確定要取消會員訂閱嗎?你將不會再次被扣費。你的會員資格將在當前計費週期結束前保持有效。並且你將無法重新訂閱,直到當前訂閱結束。",
|
||||||
@@ -811,5 +808,274 @@
|
|||||||
"filesListAdditional": {
|
"filesListAdditional": {
|
||||||
"one": "+{} 個文件被摺疊",
|
"one": "+{} 個文件被摺疊",
|
||||||
"other": "+{} 個文件被摺疊"
|
"other": "+{} 個文件被摺疊"
|
||||||
}
|
},
|
||||||
|
"pollQuestions": "問題",
|
||||||
|
"pollAnswerSubmitted": "投票答案已提交。",
|
||||||
|
"modifyAnswers": "修改答案",
|
||||||
|
"back": "返回",
|
||||||
|
"submit": "提交",
|
||||||
|
"pollOptionDefaultLabel": "選項1",
|
||||||
|
"pollUpdated": "投票已更新。",
|
||||||
|
"pollCreated": "投票已創建。",
|
||||||
|
"pollCreate": "創建投票",
|
||||||
|
"pollEdit": "編輯投票",
|
||||||
|
"pollPreviewJsonDebug": "調試預覽",
|
||||||
|
"pollTitleRequired": "標題不可為空",
|
||||||
|
"pollEndDateOptional": "結束日期和時間 (可選)",
|
||||||
|
"notSet": "未設定",
|
||||||
|
"pick": "選擇",
|
||||||
|
"clear": "清除",
|
||||||
|
"questions": "問題",
|
||||||
|
"pollAddQuestion": "添加問題",
|
||||||
|
"pollQuestionTypeSingleChoice": "單選框",
|
||||||
|
"pollQuestionTypeMultipleChoice": "多選框",
|
||||||
|
"pollQuestionTypeFreeText": "自由文本",
|
||||||
|
"pollQuestionTypeYesNo": "是 / 不是",
|
||||||
|
"pollQuestionTypeRating": "評分",
|
||||||
|
"pollNoQuestionsYet": "尚未有問題",
|
||||||
|
"pollNoQuestionsHint": "使用「添加問題」開始建立您的投票。",
|
||||||
|
"pollDebugPreview": "調試預覽",
|
||||||
|
"pollUntitledQuestion": "無標題問題",
|
||||||
|
"moveUp": "往上移動",
|
||||||
|
"moveDown": "往下移動",
|
||||||
|
"required": "必需的",
|
||||||
|
"pollQuestionTitle": "問題標題",
|
||||||
|
"pollQuestionTitleRequired": "問題標題是必需的",
|
||||||
|
"pollQuestionDescriptionOptional": "問題描述(選填)",
|
||||||
|
"options": "選項",
|
||||||
|
"pollAddOption": "添加選項",
|
||||||
|
"pollOptionLabel": "選項標籤",
|
||||||
|
"pollLongTextAnswerPreview": "長文本答案 (預覽)",
|
||||||
|
"pollShortTextAnswerPreview": "短文本答案 (預覽)",
|
||||||
|
"award": "讚賞",
|
||||||
|
"awardPost": "讚賞帖子",
|
||||||
|
"awardMessage": "消息",
|
||||||
|
"awardMessageHint": "輸入您的讚賞消息...",
|
||||||
|
"awardAttitude": "態度",
|
||||||
|
"awardAttitudePositive": "積極",
|
||||||
|
"awardAttitudeNegative": "消极",
|
||||||
|
"awardAmount": "金額",
|
||||||
|
"awardAmountHint": "輸入金額……",
|
||||||
|
"awardAmountRequired": "「金額」為必填字段",
|
||||||
|
"awardAmountInvalid": "請輸入有效金額",
|
||||||
|
"awardMessageTooLong": "消息太長(最多4096個字符)",
|
||||||
|
"awardSuccess": "獎勵已成功發送!",
|
||||||
|
"awardSubmit": "讚賞",
|
||||||
|
"awardPostPreview": "帖子預覽",
|
||||||
|
"awardNoContent": "暫無內容",
|
||||||
|
"awardByPublisher": "由 {} 發表",
|
||||||
|
"awardBenefits": "讚賞福利",
|
||||||
|
"awardBenefitsDescription": "為該帖子授予獎勵可以提升其價值和曝光度。價值更高的帖子更有可能在社區中被推薦和突出顯示。",
|
||||||
|
"checkInResultLevel5": "生日快樂 🥳",
|
||||||
|
"region": "區域",
|
||||||
|
"accountRegionHint": "這個區域將用於內容傳遞和本地化。",
|
||||||
|
"settingsCustomFontsHelper": "使用逗號分隔。",
|
||||||
|
"settingsBackgroundImageEnable": "顯示背景圖片",
|
||||||
|
"settingsDataSavingMode": "低數據模式",
|
||||||
|
"dataSavingHint": "低數據模式",
|
||||||
|
"postTypePost": "帖子",
|
||||||
|
"searchDrafts": "搜尋草稿……",
|
||||||
|
"noSearchResults": "無搜尋結果",
|
||||||
|
"contactMethodMakePublic": "設為公開",
|
||||||
|
"contactMethodMakePrivate": "設定為僅自己可見",
|
||||||
|
"contactMethodPublic": "公開",
|
||||||
|
"contactMethodPrivate": "私密",
|
||||||
|
"discoverRealms": "發現領域",
|
||||||
|
"discoverPublishers": "發現發佈者",
|
||||||
|
"discoverShuffledPost": "隨機帖子",
|
||||||
|
"projects": "項目",
|
||||||
|
"noProjects": "未找到項目。",
|
||||||
|
"deleteProject": "刪除項目",
|
||||||
|
"deleteProjectHint": "確定要刪除此項目嗎?此操作無法撤銷。",
|
||||||
|
"createProject": "新建專案",
|
||||||
|
"editProject": "編輯項目",
|
||||||
|
"projectDetails": "專案描述",
|
||||||
|
"createBot": "創建機器人",
|
||||||
|
"bots": "機器人",
|
||||||
|
"noBots": "還沒有機器人。",
|
||||||
|
"deleteBotHint": "您確定要刪除這個機器人嗎?此操作無法撤銷。",
|
||||||
|
"deleteBot": "刪除機器人",
|
||||||
|
"discoverWebArticles": "來自站外的文章",
|
||||||
|
"messageJumpNotLoaded": "引用的訊息未加載,無法跳轉到該訊息。",
|
||||||
|
"postUnlinkRealm": "未連結到領域",
|
||||||
|
"postSlug": "別名",
|
||||||
|
"postSlugHint": "這個別名可以用於在網頁通過 URL 瀏覽到你的帖子,它應該在同一發布者中是唯一。",
|
||||||
|
"attachmentOnDevice": "離線",
|
||||||
|
"attachmentOnCloud": "在線",
|
||||||
|
"attachments": "附件",
|
||||||
|
"publisherCollabInvitation": "協作邀請",
|
||||||
|
"publisherCollabInvitationCount": {
|
||||||
|
"zero": "無邀請",
|
||||||
|
"one": "{} 個可用邀請",
|
||||||
|
"other": "{} 個可用邀請"
|
||||||
|
},
|
||||||
|
"failedToLoadUserInfo": "無法加載用戶資訊",
|
||||||
|
"failedToLoadUserInfoNetwork": "看起來是網絡問題,您可以點擊下面的按鈕再試一次。",
|
||||||
|
"failedToLoadUserInfoUnauthorized": "看起來您的會話已經登出或不再可用,如果您想的話,您仍然可以嘗試再次獲取用戶資訊。",
|
||||||
|
"okay": "好的",
|
||||||
|
"postDetail": "帖子詳情",
|
||||||
|
"postCount": {
|
||||||
|
"zero": "沒有帖子",
|
||||||
|
"one": "{} 帖子",
|
||||||
|
"other": "{} 帖子"
|
||||||
|
},
|
||||||
|
"mimeType": "類型",
|
||||||
|
"fileSize": "文件大小",
|
||||||
|
"fileHash": "文件哈希",
|
||||||
|
"exifData": "EXIF 數據",
|
||||||
|
"postShuffle": "隨機帖子",
|
||||||
|
"leveling": "等級",
|
||||||
|
"levelingHistory": "經驗記錄",
|
||||||
|
"stellarProgram": "恆星計畫",
|
||||||
|
"socialCredits": "社會信用點",
|
||||||
|
"credits": "信用",
|
||||||
|
"creditsStatus": "積分狀態",
|
||||||
|
"socialCreditsDescription": "社會信用是 Solar Network 評價用戶的一種方式。它基於用戶的行為和互動來計算。以 100 分為基準,分數越高表示用戶在社區中的信譽越好。分數會隨著時間的推移而變化,反映用戶的最新行為。信用等級高的用戶可以享受到更多的福利,反之的用戶部分功能可能受到限制。",
|
||||||
|
"socialCreditsLevelPoor": "糟糕",
|
||||||
|
"socialCreditsLevelNormal": "正常",
|
||||||
|
"socialCreditsLevelGood": "良好",
|
||||||
|
"socialCreditsLevelExcellent": "優秀",
|
||||||
|
"orderByPopularity": "按熱度排序",
|
||||||
|
"orderByReleaseDate": "按發佈日期排序",
|
||||||
|
"editBot": "編輯機器人",
|
||||||
|
"botAutomatedBy": "由 {} 自動化",
|
||||||
|
"botDetails": "機器人描述",
|
||||||
|
"overview": "概述",
|
||||||
|
"keys": "密鑰",
|
||||||
|
"botNotFound": "機器人未找到。",
|
||||||
|
"newBotKey": "新建密鑰",
|
||||||
|
"newBotKeyHint": "輸入新密鑰的名稱,密鑰只會顯示一次。",
|
||||||
|
"revokeBotKey": "撤銷密鑰",
|
||||||
|
"revokeBotKeyHint": "你確定要撤銷這個密鑰?這個操作無法撤回,所有使用該密鑰的應用程式會停止工作。",
|
||||||
|
"noBotKeys": "機器人未找到。",
|
||||||
|
"revoke": "撤銷",
|
||||||
|
"keyName": "密鑰名稱",
|
||||||
|
"newKeyGenerated": "新密鑰已生成",
|
||||||
|
"copyKeyHint": "請安全地保存該密鑰,你不會再次看到它。",
|
||||||
|
"rotateKey": "旋轉密鑰",
|
||||||
|
"rotateBotKey": "旋轉密鑰",
|
||||||
|
"rotateBotKeyHint": "你確認要旋轉這個密鑰?久的密鑰會立即失效,該操作無法撤銷。",
|
||||||
|
"webFeedArticleCount": {
|
||||||
|
"zero": "無文章",
|
||||||
|
"one": "{} 文章",
|
||||||
|
"other": "{} 文章"
|
||||||
|
},
|
||||||
|
"webFeedSubscribed": "你已經訂閱了這個來源",
|
||||||
|
"webFeedUnsubscribed": "你已經取消訂閱這個來源",
|
||||||
|
"appDetails": "應用程式詳情",
|
||||||
|
"secrets": "密鑰",
|
||||||
|
"appNotFound": "找不到應用程式。",
|
||||||
|
"secretCopied": "密鑰已複製到剪貼簿。",
|
||||||
|
"deleteSecret": "刪除密鑰",
|
||||||
|
"deleteSecretHint": "您確定要刪除此密鑰嗎?此操作無法復原。",
|
||||||
|
"generateSecret": "產生新密鑰",
|
||||||
|
"createdAt": "建立於 {}",
|
||||||
|
"newSecretGenerated": "已產生新密鑰",
|
||||||
|
"copySecretHint": "請複製此密鑰並將其存放在安全的地方。您將無法再次看到它。",
|
||||||
|
"expiresIn": "過期時間(秒)",
|
||||||
|
"isOidc": "OIDC 相容",
|
||||||
|
"pinPost": "置頂帖子",
|
||||||
|
"unpinPost": "取消置頂",
|
||||||
|
"pinnedPost": "已置顶",
|
||||||
|
"publisherPage": "發布者頁面",
|
||||||
|
"realmPage": "領域頁面",
|
||||||
|
"replyPage": "回覆頁面",
|
||||||
|
"pinPostPublisherHint": "將這篇文章置顶到您的發佈者頁面",
|
||||||
|
"pinPostRealmHint": "將這篇文章置顶到領域頁面",
|
||||||
|
"pinPostRealmDisabledHint": "這個帖子不屬於任何領域",
|
||||||
|
"pinPostReplyHint": "將這篇文章置顶到回覆頁面",
|
||||||
|
"pinPostReplyDisabledHint": "這篇帖子不是回覆",
|
||||||
|
"pin": "置顶",
|
||||||
|
"unpinPostHint": "你確定要取消置顶這篇帖子嗎?",
|
||||||
|
"all": "所有",
|
||||||
|
"statusPresent": "至今",
|
||||||
|
"accountAutomated": "機器人",
|
||||||
|
"chatBreakClearButton": "清除",
|
||||||
|
"chatBreak5m": "5 分鐘",
|
||||||
|
"chatBreak10m": "10 分鐘",
|
||||||
|
"chatBreak15m": "15 分鐘",
|
||||||
|
"chatBreak30m": "30 分鐘",
|
||||||
|
"chatBreakCustomMinutes": "自訂(分鐘)",
|
||||||
|
"errorGeneric": "錯誤:{}",
|
||||||
|
"searchMessages": "搜尋消息",
|
||||||
|
"messagesCount": "{} 消息",
|
||||||
|
"dotSeparator": ".",
|
||||||
|
"roleValidationHint": "成員角色必須設置在0到100之間",
|
||||||
|
"searchMessagesHint": "搜尋消息…",
|
||||||
|
"searchLinks": "連結",
|
||||||
|
"searchAttachments": "附件",
|
||||||
|
"noMessagesFound": "未找到消息",
|
||||||
|
"openInBrowser": "在瀏覽器打開",
|
||||||
|
"highlightPost": "精選帖子",
|
||||||
|
"filters": "過濾器",
|
||||||
|
"apply": "應用",
|
||||||
|
"pubName": "題目名稱",
|
||||||
|
"realm": "領域",
|
||||||
|
"shuffle": "隨機",
|
||||||
|
"pinned": "已置顶",
|
||||||
|
"noResultsFound": "未找到結果",
|
||||||
|
"toggleFilters": "切換篩檢器",
|
||||||
|
"notableDayNext": "距離 {} 還有",
|
||||||
|
"expandPoll": "展開投票",
|
||||||
|
"collapsePoll": "摺叠投票",
|
||||||
|
"embedView": "嵌入視圖",
|
||||||
|
"embedUri": "嵌入URL",
|
||||||
|
"aspectRatio": "縱橫比",
|
||||||
|
"renderer": "渲染器",
|
||||||
|
"addEmbed": "添加嵌入",
|
||||||
|
"editEmbed": "編輯嵌入",
|
||||||
|
"deleteEmbed": "刪除嵌入",
|
||||||
|
"deleteEmbedConfirm": "您確定要刪除這個嵌入嗎?",
|
||||||
|
"currentEmbed": "當前嵌入",
|
||||||
|
"noEmbed": "尚未嵌入",
|
||||||
|
"save": "保存",
|
||||||
|
"webView": "網頁視圖",
|
||||||
|
"settingsDefaultPool": "預設檔案池",
|
||||||
|
"settingsDefaultPoolHelper": "選擇文件上傳的默認儲存池",
|
||||||
|
"uploadFile": "上傳檔案",
|
||||||
|
"authDeviceChallenges": "設備活動",
|
||||||
|
"authDeviceHint": "向左滑動以編輯標籤,向右滑動以登出設備。",
|
||||||
|
"settingsMessageDisplayStyle": "訊息顯示樣式",
|
||||||
|
"auto": "自動",
|
||||||
|
"manual": "手動",
|
||||||
|
"iframeCode": "Iframe 代碼",
|
||||||
|
"iframeCodeHint": "<iframe src=\"...\" width=\"...\" height=\"...\">",
|
||||||
|
"parseIframe": "解析 Iframe",
|
||||||
|
"messageActions": "消息選項",
|
||||||
|
"viewEmbedLoadHint": "點擊以載入",
|
||||||
|
"levelingStage1": "新手",
|
||||||
|
"levelingStage2": "學徒",
|
||||||
|
"levelingStage3": "學徒工",
|
||||||
|
"levelingStage4": "熟練",
|
||||||
|
"levelingStage5": "專家",
|
||||||
|
"levelingStage6": "大師",
|
||||||
|
"levelingStage7": "宗師",
|
||||||
|
"levelingStage8": "傳說",
|
||||||
|
"levelingStage9": "神話",
|
||||||
|
"levelingStage10": "不朽",
|
||||||
|
"levelingStage11": "神聖",
|
||||||
|
"levelingStage12": "超凡",
|
||||||
|
"uploadAttachment": "上傳附件",
|
||||||
|
"attachmentPreview": "附件預覽",
|
||||||
|
"selectPool": "選擇檔案池",
|
||||||
|
"choosePool": "選擇一個檔案池",
|
||||||
|
"errorLoadingPools": "加載池時出錯",
|
||||||
|
"quotaCostInfo": "這次上傳將消耗 {} 配額點",
|
||||||
|
"uploadConstraints": "上傳限制",
|
||||||
|
"fileSizeExceeded": "檔案大小超過了 {} 的最大限制",
|
||||||
|
"fileTypeNotAccepted": "該文件類型不被此池接受",
|
||||||
|
"files": "附件",
|
||||||
|
"confirmDeleteFile": "你確定要刪除這個文件嗎?",
|
||||||
|
"deleteFile": "刪除文件",
|
||||||
|
"failedToDeleteFile": "刪除文件失敗",
|
||||||
|
"drive": "雲盤",
|
||||||
|
"allPools": "全部的池",
|
||||||
|
"includeRecycled": "包含已回收文件",
|
||||||
|
"confirmDeleteRecycledFiles": "您確定要刪除所有回收的檔案嗎?",
|
||||||
|
"deleteRecycledFiles": "刪除已回收檔案",
|
||||||
|
"recycledFilesDeleted": "已回收檔案刪除成功",
|
||||||
|
"failedToDeleteRecycledFiles": "已回收檔案刪除失敗",
|
||||||
|
"upload": "上傳",
|
||||||
|
"postCompose": "撰寫帖子",
|
||||||
|
"postPublish": "發佈帖子"
|
||||||
}
|
}
|
||||||
12
assets/icons/icon-outline.svg
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
<svg xmlns="http://www.w3.org/2000/svg" width="192" height="192" fill="none">
|
||||||
|
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="12"
|
||||||
|
d="M54 147h86" />
|
||||||
|
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"
|
||||||
|
d="M57 111s-2-4.5-2-10m22 22s-4 7-11 4m9-22s-2-4.5-2-10" />
|
||||||
|
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="12"
|
||||||
|
d="M54 147a32 32 0 0 1-11.999-61.665A39 39 0 0 1 81 46m59 101a30 30 0 0 0 29.933-28" />
|
||||||
|
<circle cx="132" cy="75" r="4" stroke="#fff" stroke-linecap="round" stroke-linejoin="round"
|
||||||
|
stroke-width="8" />
|
||||||
|
<path stroke="#fff" stroke-linecap="round" stroke-linejoin="round" stroke-width="10"
|
||||||
|
d="M112.5 41.217C100.843 47.961 93 60.564 93 75c0 6.375 1.53 12.393 4.242 17.707m69.513-35.419A38.84 38.84 0 0 1 171 75c0 14.433-7.84 27.034-19.493 33.779m-.793-43.317A20.9 20.9 0 0 1 153 75c0 7.77-4.221 14.556-10.495 18.188m-21.003-36.38C115.224 60.44 111 67.226 111 75a20.9 20.9 0 0 0 2.284 9.533" />
|
||||||
|
</svg>
|
||||||
|
After Width: | Height: | Size: 1.0 KiB |
BIN
assets/images/media-offline.jpg
Normal file
|
After Width: | Height: | Size: 461 KiB |
BIN
assets/images/stickers/angry.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
assets/images/stickers/clap.png
Normal file
|
After Width: | Height: | Size: 1.0 MiB |
BIN
assets/images/stickers/confuse.png
Normal file
|
After Width: | Height: | Size: 668 KiB |
BIN
assets/images/stickers/party.png
Normal file
|
After Width: | Height: | Size: 1.1 MiB |
BIN
assets/images/stickers/pray.png
Normal file
|
After Width: | Height: | Size: 666 KiB |
BIN
assets/images/stickers/thumb_up.png
Normal file
|
After Width: | Height: | Size: 623 KiB |
@@ -5,3 +5,7 @@ targets:
|
|||||||
options:
|
options:
|
||||||
explicit_to_json: true
|
explicit_to_json: true
|
||||||
field_rename: snake
|
field_rename: snake
|
||||||
|
drift_dev:
|
||||||
|
options:
|
||||||
|
databases:
|
||||||
|
app_database: lib/database/drift_db.dart
|
||||||
|
|||||||
1
drift_schemas/app_database/drift_schema_v6.json
Normal file
@@ -21,6 +21,6 @@
|
|||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>1.0</string>
|
<string>1.0</string>
|
||||||
<key>MinimumOSVersion</key>
|
<key>MinimumOSVersion</key>
|
||||||
<string>12.0</string>
|
<string>13.0</string>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
15
ios/Podfile
@@ -1,6 +1,3 @@
|
|||||||
# Uncomment this line to define a global platform for your project
|
|
||||||
platform :ios, '15.0'
|
|
||||||
|
|
||||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||||
|
|
||||||
@@ -28,6 +25,8 @@ require File.expand_path(File.join('packages', 'flutter_tools', 'bin', 'podhelpe
|
|||||||
flutter_ios_podfile_setup
|
flutter_ios_podfile_setup
|
||||||
|
|
||||||
target 'Runner' do
|
target 'Runner' do
|
||||||
|
platform :ios, '15.0'
|
||||||
|
|
||||||
use_frameworks!
|
use_frameworks!
|
||||||
use_modular_headers!
|
use_modular_headers!
|
||||||
|
|
||||||
@@ -50,6 +49,16 @@ target 'Runner' do
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
target 'WatchRunner Watch App' do
|
||||||
|
platform :watchos, '11.0'
|
||||||
|
|
||||||
|
use_frameworks!
|
||||||
|
use_modular_headers!
|
||||||
|
|
||||||
|
pod 'Kingfisher', '~> 8.0'
|
||||||
|
pod 'KingfisherWebP'
|
||||||
|
end
|
||||||
|
|
||||||
post_install do |installer|
|
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)
|
||||||
|
|||||||
225
ios/Podfile.lock
@@ -1,5 +1,7 @@
|
|||||||
PODS:
|
PODS:
|
||||||
- Alamofire (5.10.2)
|
- Alamofire (5.10.2)
|
||||||
|
- app_links (6.4.1):
|
||||||
|
- Flutter
|
||||||
- connectivity_plus (0.0.1):
|
- connectivity_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- croppy (0.0.1):
|
- croppy (0.0.1):
|
||||||
@@ -40,83 +42,85 @@ PODS:
|
|||||||
- file_picker (0.0.1):
|
- file_picker (0.0.1):
|
||||||
- DKImagePickerController/PhotoGallery
|
- DKImagePickerController/PhotoGallery
|
||||||
- Flutter
|
- Flutter
|
||||||
- Firebase/CoreOnly (12.0.0):
|
- file_saver (0.0.1):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- Flutter
|
||||||
- Firebase/Crashlytics (12.0.0):
|
- Firebase/CoreOnly (12.4.0):
|
||||||
|
- FirebaseCore (~> 12.4.0)
|
||||||
|
- Firebase/Crashlytics (12.4.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseCrashlytics (~> 12.0.0)
|
- FirebaseCrashlytics (~> 12.4.0)
|
||||||
- Firebase/Messaging (12.0.0):
|
- Firebase/Messaging (12.4.0):
|
||||||
- Firebase/CoreOnly
|
- Firebase/CoreOnly
|
||||||
- FirebaseMessaging (~> 12.0.0)
|
- FirebaseMessaging (~> 12.4.0)
|
||||||
- firebase_analytics (12.0.0):
|
- firebase_analytics (12.0.3):
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- FirebaseAnalytics (= 12.0.0)
|
- FirebaseAnalytics (= 12.4.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_core (4.0.0):
|
- firebase_core (4.2.0):
|
||||||
- Firebase/CoreOnly (= 12.0.0)
|
- Firebase/CoreOnly (= 12.4.0)
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_crashlytics (5.0.0):
|
- firebase_crashlytics (5.0.3):
|
||||||
- Firebase/Crashlytics (= 12.0.0)
|
- Firebase/Crashlytics (= 12.4.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- firebase_messaging (16.0.0):
|
- firebase_messaging (16.0.3):
|
||||||
- Firebase/Messaging (= 12.0.0)
|
- Firebase/Messaging (= 12.4.0)
|
||||||
- firebase_core
|
- firebase_core
|
||||||
- Flutter
|
- Flutter
|
||||||
- FirebaseAnalytics (12.0.0):
|
- FirebaseAnalytics (12.4.0):
|
||||||
- FirebaseAnalytics/Default (= 12.0.0)
|
- FirebaseAnalytics/Default (= 12.4.0)
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.4.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.4.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseAnalytics/Default (12.0.0):
|
- FirebaseAnalytics/Default (12.4.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.4.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.4.0)
|
||||||
- GoogleAppMeasurement/Default (= 12.0.0)
|
- GoogleAppMeasurement/Default (= 12.4.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseCore (12.0.0):
|
- FirebaseCore (12.4.0):
|
||||||
- FirebaseCoreInternal (~> 12.0.0)
|
- FirebaseCoreInternal (~> 12.4.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- FirebaseCoreExtension (12.0.0):
|
- FirebaseCoreExtension (12.4.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.4.0)
|
||||||
- FirebaseCoreInternal (12.0.0):
|
- FirebaseCoreInternal (12.4.0):
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- FirebaseCrashlytics (12.0.0):
|
- FirebaseCrashlytics (12.4.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.4.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.4.0)
|
||||||
- FirebaseRemoteConfigInterop (~> 12.0.0)
|
- FirebaseRemoteConfigInterop (~> 12.4.0)
|
||||||
- FirebaseSessions (~> 12.0.0)
|
- FirebaseSessions (~> 12.4.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseInstallations (12.0.0):
|
- FirebaseInstallations (12.4.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.4.0)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- PromisesObjC (~> 2.4)
|
- PromisesObjC (~> 2.4)
|
||||||
- FirebaseMessaging (12.0.0):
|
- FirebaseMessaging (12.4.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.4.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.4.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Reachability (~> 8.1)
|
- GoogleUtilities/Reachability (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- FirebaseRemoteConfigInterop (12.0.0)
|
- FirebaseRemoteConfigInterop (12.4.0)
|
||||||
- FirebaseSessions (12.0.0):
|
- FirebaseSessions (12.4.0):
|
||||||
- FirebaseCore (~> 12.0.0)
|
- FirebaseCore (~> 12.4.0)
|
||||||
- FirebaseCoreExtension (~> 12.0.0)
|
- FirebaseCoreExtension (~> 12.4.0)
|
||||||
- FirebaseInstallations (~> 12.0.0)
|
- FirebaseInstallations (~> 12.4.0)
|
||||||
- GoogleDataTransport (~> 10.1)
|
- GoogleDataTransport (~> 10.1)
|
||||||
- GoogleUtilities/Environment (~> 8.1)
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||||
@@ -134,6 +138,8 @@ PODS:
|
|||||||
- OrderedSet (~> 6.0.3)
|
- OrderedSet (~> 6.0.3)
|
||||||
- flutter_keyboard_visibility (0.0.1):
|
- flutter_keyboard_visibility (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
|
- flutter_local_notifications (0.0.1):
|
||||||
|
- Flutter
|
||||||
- flutter_native_splash (2.4.3):
|
- flutter_native_splash (2.4.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_platform_alert (0.0.1):
|
- flutter_platform_alert (0.0.1):
|
||||||
@@ -145,33 +151,34 @@ PODS:
|
|||||||
- flutter_udid (0.0.1):
|
- flutter_udid (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain
|
- SAMKeychain
|
||||||
- flutter_webrtc (1.0.0):
|
- flutter_webrtc (1.2.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (= 137.7151.02)
|
- WebRTC-SDK (= 137.7151.04)
|
||||||
- gal (1.0.0):
|
- gal (1.0.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
- GoogleAdsOnDeviceConversion (2.1.0):
|
- GoogleAdsOnDeviceConversion (3.1.0):
|
||||||
|
- GoogleUtilities/Environment (~> 8.1)
|
||||||
- GoogleUtilities/Logger (~> 8.1)
|
- GoogleUtilities/Logger (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/Core (12.0.0):
|
- GoogleAppMeasurement/Core (12.4.0):
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/Default (12.0.0):
|
- GoogleAppMeasurement/Default (12.4.0):
|
||||||
- GoogleAdsOnDeviceConversion (= 2.1.0)
|
- GoogleAdsOnDeviceConversion (~> 3.1.0)
|
||||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
- GoogleAppMeasurement/Core (= 12.4.0)
|
||||||
- GoogleAppMeasurement/IdentitySupport (= 12.0.0)
|
- GoogleAppMeasurement/IdentitySupport (= 12.4.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||||
- nanopb (~> 3.30910.0)
|
- nanopb (~> 3.30910.0)
|
||||||
- GoogleAppMeasurement/IdentitySupport (12.0.0):
|
- GoogleAppMeasurement/IdentitySupport (12.4.0):
|
||||||
- GoogleAppMeasurement/Core (= 12.0.0)
|
- GoogleAppMeasurement/Core (= 12.4.0)
|
||||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||||
- GoogleUtilities/Network (~> 8.1)
|
- GoogleUtilities/Network (~> 8.1)
|
||||||
@@ -211,11 +218,26 @@ PODS:
|
|||||||
- Flutter
|
- Flutter
|
||||||
- irondash_engine_context (0.0.1):
|
- irondash_engine_context (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- Kingfisher (8.5.0)
|
- Kingfisher (8.6.0)
|
||||||
- livekit_client (2.5.0):
|
- KingfisherWebP (1.7.2):
|
||||||
|
- Kingfisher (~> 8.0)
|
||||||
|
- libwebp (>= 1.1.0)
|
||||||
|
- libwebp (1.5.0):
|
||||||
|
- libwebp/demux (= 1.5.0)
|
||||||
|
- libwebp/mux (= 1.5.0)
|
||||||
|
- libwebp/sharpyuv (= 1.5.0)
|
||||||
|
- libwebp/webp (= 1.5.0)
|
||||||
|
- libwebp/demux (1.5.0):
|
||||||
|
- libwebp/webp
|
||||||
|
- libwebp/mux (1.5.0):
|
||||||
|
- libwebp/demux
|
||||||
|
- libwebp/sharpyuv (1.5.0)
|
||||||
|
- libwebp/webp (1.5.0):
|
||||||
|
- libwebp/sharpyuv
|
||||||
|
- livekit_client (2.5.3):
|
||||||
- Flutter
|
- Flutter
|
||||||
- flutter_webrtc
|
- flutter_webrtc
|
||||||
- WebRTC-SDK (= 137.7151.02)
|
- WebRTC-SDK (= 137.7151.04)
|
||||||
- local_auth_darwin (0.0.1):
|
- local_auth_darwin (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- FlutterMacOS
|
- FlutterMacOS
|
||||||
@@ -245,12 +267,12 @@ PODS:
|
|||||||
- PromisesObjC (= 2.4.0)
|
- PromisesObjC (= 2.4.0)
|
||||||
- receive_sharing_intent (1.8.1):
|
- receive_sharing_intent (1.8.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- record_ios (1.0.0):
|
- record_ios (1.1.0):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SAMKeychain (1.5.3)
|
- SAMKeychain (1.5.3)
|
||||||
- SDWebImage (5.21.1):
|
- SDWebImage (5.21.3):
|
||||||
- SDWebImage/Core (= 5.21.1)
|
- SDWebImage/Core (= 5.21.3)
|
||||||
- SDWebImage/Core (5.21.1)
|
- SDWebImage/Core (5.21.3)
|
||||||
- share_plus (0.0.1):
|
- share_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- shared_preferences_foundation (0.0.1):
|
- shared_preferences_foundation (0.0.1):
|
||||||
@@ -289,20 +311,24 @@ PODS:
|
|||||||
- super_native_extensions (0.0.1):
|
- super_native_extensions (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- SwiftyGif (5.4.5)
|
- SwiftyGif (5.4.5)
|
||||||
|
- syncfusion_flutter_pdfviewer (0.0.1):
|
||||||
|
- Flutter
|
||||||
- url_launcher_ios (0.0.1):
|
- url_launcher_ios (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- volume_controller (0.0.1):
|
- volume_controller (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- wakelock_plus (0.0.1):
|
- wakelock_plus (0.0.1):
|
||||||
- Flutter
|
- Flutter
|
||||||
- WebRTC-SDK (137.7151.02)
|
- WebRTC-SDK (137.7151.04)
|
||||||
|
|
||||||
DEPENDENCIES:
|
DEPENDENCIES:
|
||||||
- Alamofire
|
- Alamofire
|
||||||
|
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
- 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`)
|
||||||
|
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
||||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||||
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
||||||
@@ -311,6 +337,7 @@ DEPENDENCIES:
|
|||||||
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
||||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||||
|
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||||
- 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_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||||
@@ -321,6 +348,7 @@ DEPENDENCIES:
|
|||||||
- 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)
|
||||||
|
- KingfisherWebP
|
||||||
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
||||||
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||||
- 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`)
|
||||||
@@ -338,6 +366,7 @@ DEPENDENCIES:
|
|||||||
- 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`)
|
||||||
- super_native_extensions (from `.symlinks/plugins/super_native_extensions/ios`)
|
- super_native_extensions (from `.symlinks/plugins/super_native_extensions/ios`)
|
||||||
|
- syncfusion_flutter_pdfviewer (from `.symlinks/plugins/syncfusion_flutter_pdfviewer/ios`)
|
||||||
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
- url_launcher_ios (from `.symlinks/plugins/url_launcher_ios/ios`)
|
||||||
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
|
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
|
||||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||||
@@ -362,6 +391,8 @@ SPEC REPOS:
|
|||||||
- GoogleDataTransport
|
- GoogleDataTransport
|
||||||
- GoogleUtilities
|
- GoogleUtilities
|
||||||
- Kingfisher
|
- Kingfisher
|
||||||
|
- KingfisherWebP
|
||||||
|
- libwebp
|
||||||
- nanopb
|
- nanopb
|
||||||
- OrderedSet
|
- OrderedSet
|
||||||
- PromisesObjC
|
- PromisesObjC
|
||||||
@@ -373,6 +404,8 @@ SPEC REPOS:
|
|||||||
- WebRTC-SDK
|
- WebRTC-SDK
|
||||||
|
|
||||||
EXTERNAL SOURCES:
|
EXTERNAL SOURCES:
|
||||||
|
app_links:
|
||||||
|
:path: ".symlinks/plugins/app_links/ios"
|
||||||
connectivity_plus:
|
connectivity_plus:
|
||||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||||
croppy:
|
croppy:
|
||||||
@@ -381,6 +414,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||||
file_picker:
|
file_picker:
|
||||||
:path: ".symlinks/plugins/file_picker/ios"
|
:path: ".symlinks/plugins/file_picker/ios"
|
||||||
|
file_saver:
|
||||||
|
:path: ".symlinks/plugins/file_saver/ios"
|
||||||
firebase_analytics:
|
firebase_analytics:
|
||||||
:path: ".symlinks/plugins/firebase_analytics/ios"
|
:path: ".symlinks/plugins/firebase_analytics/ios"
|
||||||
firebase_core:
|
firebase_core:
|
||||||
@@ -397,6 +432,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||||
flutter_keyboard_visibility:
|
flutter_keyboard_visibility:
|
||||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||||
|
flutter_local_notifications:
|
||||||
|
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||||
flutter_native_splash:
|
flutter_native_splash:
|
||||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||||
flutter_platform_alert:
|
flutter_platform_alert:
|
||||||
@@ -449,6 +486,8 @@ EXTERNAL SOURCES:
|
|||||||
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
|
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
|
||||||
super_native_extensions:
|
super_native_extensions:
|
||||||
:path: ".symlinks/plugins/super_native_extensions/ios"
|
:path: ".symlinks/plugins/super_native_extensions/ios"
|
||||||
|
syncfusion_flutter_pdfviewer:
|
||||||
|
:path: ".symlinks/plugins/syncfusion_flutter_pdfviewer/ios"
|
||||||
url_launcher_ios:
|
url_launcher_ios:
|
||||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||||
volume_controller:
|
volume_controller:
|
||||||
@@ -458,46 +497,51 @@ EXTERNAL SOURCES:
|
|||||||
|
|
||||||
SPEC CHECKSUMS:
|
SPEC CHECKSUMS:
|
||||||
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
||||||
|
app_links: 3dbc685f76b1693c66a6d9dd1e9ab6f73d97dc0a
|
||||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||||
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
||||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||||
Firebase: 800d487043c0557d9faed71477a38d9aafb08a41
|
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||||
firebase_analytics: cd56fc56f75c1df30a6ff5290cd56e230996a76d
|
Firebase: f07b15ae5a6ec0f93713e30b923d9970d144af3e
|
||||||
firebase_core: 633e1851ffe1b9ab875f6467a4f574c79cef02e4
|
firebase_analytics: 1d024068b1d4707d5ba7a42a12976ddf3316d835
|
||||||
firebase_crashlytics: 2c6c1a17900a38081d938330e9f48e60ec5b255d
|
firebase_core: 744984dbbed8b3036abf34f0b98d80f130a7e464
|
||||||
firebase_messaging: d17feef781edc84ebefe62624fb384358ad96361
|
firebase_crashlytics: f3a9a4338ab99b67042f64e9e22e1bf349cb44ed
|
||||||
FirebaseAnalytics: 6d790cd1b159b4eb61a99948df0934ce505a34f7
|
firebase_messaging: 82c70650c426a0a14873e1acdb9ec2b443c4e8b4
|
||||||
FirebaseCore: 055f4ab117d5964158c833f3d5e7ec6d91648d4a
|
FirebaseAnalytics: 0fc2b20091f0ddd21bf73397cf8f0eb5346dc24f
|
||||||
FirebaseCoreExtension: 639afb3de6abd611952be78a794c54a47fa0f361
|
FirebaseCore: bb595f3114953664e3c1dc032f008a244147cfd3
|
||||||
FirebaseCoreInternal: dedc28e569a4be85f38f3d6af1070a2e12018d55
|
FirebaseCoreExtension: 7e1f7118ee970e001a8013719fb90950ee5e0018
|
||||||
FirebaseCrashlytics: db75aa0cab8d00f68406fa247c32fe17ade884d7
|
FirebaseCoreInternal: d7f5a043c2cd01a08103ab586587c1468047bca6
|
||||||
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
FirebaseCrashlytics: a6ece278a837c7e88de2d9b5da0a3542f2342395
|
||||||
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
FirebaseInstallations: ae9f4902cb5bf1d0c5eaa31ec1f4e5495a0714e2
|
||||||
FirebaseRemoteConfigInterop: bfa0ea72ba3dc5af739777296424e46bd6f42613
|
FirebaseMessaging: d33971b7bb252745ea6cd31ab190d1a1df4b8ed5
|
||||||
FirebaseSessions: 4e784acda213108aafef536535cdfc03504acc42
|
FirebaseRemoteConfigInterop: 1e31ec72b89c9924367c59bfb5ec9ab60d1d6766
|
||||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
FirebaseSessions: ba7c7a7ca8696a8d540eb3fe3800fbe98c79786d
|
||||||
|
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||||
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
||||||
|
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||||
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
||||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||||
flutter_webrtc: 6f7da106613d52ade777d5b4875a43f48c28b457
|
flutter_webrtc: c3e21fc0dcd9d8eb246ae4d5256fcbeb2f5ecd22
|
||||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||||
GoogleAdsOnDeviceConversion: 2be6297a4f048459e0ae17fad9bfd2844e10cf64
|
GoogleAdsOnDeviceConversion: e03a386840803ea7eef3fd22a061930142c039c1
|
||||||
GoogleAppMeasurement: 8f6ab04ad6ae493b53fcf56bd26323fb2f1384f3
|
GoogleAppMeasurement: 1e718274b7e015cefd846ac1fcf7820c70dc017d
|
||||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||||
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
Kingfisher: 64278f126a815d0e2d391cdf71311b85882c4de0
|
||||||
livekit_client: e3b79b99405428aac439b6b76a254cd9a11dbbfb
|
KingfisherWebP: 38b9721821947f547afb78f933f75f4f9e0ae402
|
||||||
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
|
||||||
|
livekit_client: 86c8af579274e4b7a215185a8080db2d4e176f40
|
||||||
|
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
|
||||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||||
@@ -505,27 +549,28 @@ SPEC CHECKSUMS:
|
|||||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||||
pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c
|
pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c
|
||||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||||
pointer_interceptor_ios: ec847ef8b0915778bed2b2cef636f4d177fa8eed
|
pointer_interceptor_ios: da06a662d5bfd329602b45b2ab41bc0fb5fdb0f0
|
||||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||||
record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b
|
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
|
||||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||||
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
||||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||||
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
|
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
|
||||||
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
|
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
|
||||||
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
||||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
syncfusion_flutter_pdfviewer: 90dc48305d2e33d4aa20681d1e98ddeda891bc14
|
||||||
|
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||||
WebRTC-SDK: d20de357dcbf7c9696b124b39f3ff62125107e4b
|
WebRTC-SDK: 40d4f5ba05cadff14e4db5614aec402a633f007e
|
||||||
|
|
||||||
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
PODFILE CHECKSUM: 3096dc559be56aca856e757e1dc65ca039801e2e
|
||||||
|
|
||||||
COCOAPODS: 1.16.2
|
COCOAPODS: 1.16.2
|
||||||
|
|||||||
@@ -3,13 +3,14 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 54;
|
objectVersion = 77;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
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 */; };
|
||||||
|
7310A7DF2EB10963002C0FD3 /* WatchRunner Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
73ACDFAD2E3D0E6100B63535 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */; };
|
73ACDFAD2E3D0E6100B63535 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */; };
|
||||||
73ACDFC32E3D0E6100B63535 /* SolianBroadcastExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
73ACDFC32E3D0E6100B63535 /* SolianBroadcastExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||||
@@ -20,6 +21,7 @@
|
|||||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
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 */; };
|
||||||
|
A1D34487886D362AC8B99B2E /* Pods_WatchRunner_Watch_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 802C1CFCA7F1E069AAEFB454 /* Pods_WatchRunner_Watch_App.framework */; };
|
||||||
B87C0E607033790E71B54D73 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D834CA86410B09796B312B /* Pods_Runner.framework */; };
|
B87C0E607033790E71B54D73 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F6D834CA86410B09796B312B /* Pods_Runner.framework */; };
|
||||||
D174D53FF3E8EA943491A5CC /* Pods_SolianShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */; };
|
D174D53FF3E8EA943491A5CC /* Pods_SolianShareExtension.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */; };
|
||||||
D1772CE196985AE8E8C9F2E5 /* Pods_SolianNotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */; };
|
D1772CE196985AE8E8C9F2E5 /* Pods_SolianNotificationService.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */; };
|
||||||
@@ -58,6 +60,17 @@
|
|||||||
/* End PBXContainerItemProxy section */
|
/* End PBXContainerItemProxy section */
|
||||||
|
|
||||||
/* Begin PBXCopyFilesBuildPhase section */
|
/* Begin PBXCopyFilesBuildPhase section */
|
||||||
|
7310A7DE2EB10963002C0FD3 /* Embed Watch Content */ = {
|
||||||
|
isa = PBXCopyFilesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
|
||||||
|
dstSubfolderSpec = 16;
|
||||||
|
files = (
|
||||||
|
7310A7DF2EB10963002C0FD3 /* WatchRunner Watch App.app in Embed Watch Content */,
|
||||||
|
);
|
||||||
|
name = "Embed Watch Content";
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */ = {
|
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */ = {
|
||||||
isa = PBXCopyFilesBuildPhase;
|
isa = PBXCopyFilesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -84,6 +97,7 @@
|
|||||||
/* End PBXCopyFilesBuildPhase section */
|
/* End PBXCopyFilesBuildPhase section */
|
||||||
|
|
||||||
/* Begin PBXFileReference section */
|
/* Begin PBXFileReference section */
|
||||||
|
103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.profile.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
14118AC858B441AB16B7309E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
14118AC858B441AB16B7309E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
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>"; };
|
||||||
@@ -100,6 +114,7 @@
|
|||||||
39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianNotificationService.framework; 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>"; };
|
||||||
|
7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "WatchRunner Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||||
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
|
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
|
||||||
@@ -111,6 +126,8 @@
|
|||||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
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>"; };
|
||||||
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
802C1CFCA7F1E069AAEFB454 /* Pods_WatchRunner_Watch_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_WatchRunner_Watch_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
|
86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.debug.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||||
8B40620B1EEBB09456406A3C /* Pods-SolianNotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.profile.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
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>"; };
|
||||||
@@ -120,6 +137,7 @@
|
|||||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
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>"; };
|
||||||
|
A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.release.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
A499FDB2082EB000933AA8C5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
A499FDB2082EB000933AA8C5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||||
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-SolianShareExtension/Pods-SolianShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-SolianShareExtension/Pods-SolianShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
||||||
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
@@ -162,6 +180,11 @@
|
|||||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||||
|
|
||||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||||
|
7310A7D52EB10962002C0FD3 /* WatchRunner Watch App */ = {
|
||||||
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
|
path = "WatchRunner Watch App";
|
||||||
|
sourceTree = "<group>";
|
||||||
|
};
|
||||||
73268D272DEB012A0076E970 /* Services */ = {
|
73268D272DEB012A0076E970 /* Services */ = {
|
||||||
isa = PBXFileSystemSynchronizedRootGroup;
|
isa = PBXFileSystemSynchronizedRootGroup;
|
||||||
exceptions = (
|
exceptions = (
|
||||||
@@ -205,6 +228,14 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
7310A7D12EB10962002C0FD3 /* Frameworks */ = {
|
||||||
|
isa = PBXFrameworksBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
A1D34487886D362AC8B99B2E /* Pods_WatchRunner_Watch_App.framework in Frameworks */,
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
73ACDFA82E3D0E6100B63535 /* Frameworks */ = {
|
73ACDFA82E3D0E6100B63535 /* Frameworks */ = {
|
||||||
isa = PBXFrameworksBuildPhase;
|
isa = PBXFrameworksBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -258,6 +289,7 @@
|
|||||||
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */,
|
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */,
|
||||||
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */,
|
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */,
|
||||||
73ACDFB82E3D0E6100B63535 /* UIKit.framework */,
|
73ACDFB82E3D0E6100B63535 /* UIKit.framework */,
|
||||||
|
802C1CFCA7F1E069AAEFB454 /* Pods_WatchRunner_Watch_App.framework */,
|
||||||
);
|
);
|
||||||
name = Frameworks;
|
name = Frameworks;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -280,6 +312,9 @@
|
|||||||
17FAB080A9C53193ABD9C15B /* Pods-SolianShareExtension.debug.xcconfig */,
|
17FAB080A9C53193ABD9C15B /* Pods-SolianShareExtension.debug.xcconfig */,
|
||||||
27C66EFB5A705F1A822C3EB0 /* Pods-SolianShareExtension.release.xcconfig */,
|
27C66EFB5A705F1A822C3EB0 /* Pods-SolianShareExtension.release.xcconfig */,
|
||||||
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */,
|
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */,
|
||||||
|
86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */,
|
||||||
|
A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */,
|
||||||
|
103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */,
|
||||||
);
|
);
|
||||||
path = Pods;
|
path = Pods;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -303,6 +338,7 @@
|
|||||||
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
||||||
73C305CF2E0BE878009035B9 /* SolianShareExtension */,
|
73C305CF2E0BE878009035B9 /* SolianShareExtension */,
|
||||||
73ACDFAE2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
73ACDFAE2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||||
|
7310A7D52EB10962002C0FD3 /* WatchRunner Watch App */,
|
||||||
97C146EF1CF9000F007C117D /* Products */,
|
97C146EF1CF9000F007C117D /* Products */,
|
||||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||||
91E124CE95BCB4DCD890160D /* Pods */,
|
91E124CE95BCB4DCD890160D /* Pods */,
|
||||||
@@ -319,6 +355,7 @@
|
|||||||
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */,
|
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */,
|
||||||
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */,
|
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */,
|
||||||
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */,
|
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */,
|
||||||
|
7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */,
|
||||||
);
|
);
|
||||||
name = Products;
|
name = Products;
|
||||||
sourceTree = "<group>";
|
sourceTree = "<group>";
|
||||||
@@ -363,6 +400,28 @@
|
|||||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||||
productType = "com.apple.product-type.bundle.unit-test";
|
productType = "com.apple.product-type.bundle.unit-test";
|
||||||
};
|
};
|
||||||
|
7310A7D32EB10962002C0FD3 /* WatchRunner Watch App */ = {
|
||||||
|
isa = PBXNativeTarget;
|
||||||
|
buildConfigurationList = 7310A7E32EB10963002C0FD3 /* Build configuration list for PBXNativeTarget "WatchRunner Watch App" */;
|
||||||
|
buildPhases = (
|
||||||
|
DDEDA1BA6278B94F0F7B9B61 /* [CP] Check Pods Manifest.lock */,
|
||||||
|
7310A7D02EB10962002C0FD3 /* Sources */,
|
||||||
|
7310A7D12EB10962002C0FD3 /* Frameworks */,
|
||||||
|
7310A7D22EB10962002C0FD3 /* Resources */,
|
||||||
|
C74B07D6587D29C67A198025 /* [CP] Embed Pods Frameworks */,
|
||||||
|
);
|
||||||
|
buildRules = (
|
||||||
|
);
|
||||||
|
dependencies = (
|
||||||
|
);
|
||||||
|
fileSystemSynchronizedGroups = (
|
||||||
|
7310A7D52EB10962002C0FD3 /* WatchRunner Watch App */,
|
||||||
|
);
|
||||||
|
name = "WatchRunner Watch App";
|
||||||
|
productName = "WatchRunner Watch App";
|
||||||
|
productReference = 7310A7D42EB10962002C0FD3 /* WatchRunner Watch App.app */;
|
||||||
|
productType = "com.apple.product-type.application";
|
||||||
|
};
|
||||||
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */ = {
|
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */ = {
|
||||||
isa = PBXNativeTarget;
|
isa = PBXNativeTarget;
|
||||||
buildConfigurationList = 73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */;
|
buildConfigurationList = 73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */;
|
||||||
@@ -434,6 +493,7 @@
|
|||||||
97C146EA1CF9000F007C117D /* Sources */,
|
97C146EA1CF9000F007C117D /* Sources */,
|
||||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||||
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */,
|
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */,
|
||||||
|
7310A7DE2EB10963002C0FD3 /* Embed Watch Content */,
|
||||||
97C146EC1CF9000F007C117D /* Resources */,
|
97C146EC1CF9000F007C117D /* Resources */,
|
||||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||||
@@ -463,7 +523,7 @@
|
|||||||
isa = PBXProject;
|
isa = PBXProject;
|
||||||
attributes = {
|
attributes = {
|
||||||
BuildIndependentTargetsInParallel = YES;
|
BuildIndependentTargetsInParallel = YES;
|
||||||
LastSwiftUpdateCheck = 1640;
|
LastSwiftUpdateCheck = 2600;
|
||||||
LastUpgradeCheck = 1510;
|
LastUpgradeCheck = 1510;
|
||||||
ORGANIZATIONNAME = "";
|
ORGANIZATIONNAME = "";
|
||||||
TargetAttributes = {
|
TargetAttributes = {
|
||||||
@@ -471,6 +531,9 @@
|
|||||||
CreatedOnToolsVersion = 14.0;
|
CreatedOnToolsVersion = 14.0;
|
||||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||||
};
|
};
|
||||||
|
7310A7D32EB10962002C0FD3 = {
|
||||||
|
CreatedOnToolsVersion = 26.0.1;
|
||||||
|
};
|
||||||
73ACDFAA2E3D0E6100B63535 = {
|
73ACDFAA2E3D0E6100B63535 = {
|
||||||
CreatedOnToolsVersion = 16.4;
|
CreatedOnToolsVersion = 16.4;
|
||||||
};
|
};
|
||||||
@@ -504,6 +567,7 @@
|
|||||||
73CDD6792DEC00480059D95D /* SolianNotificationService */,
|
73CDD6792DEC00480059D95D /* SolianNotificationService */,
|
||||||
73C305CD2E0BE878009035B9 /* SolianShareExtension */,
|
73C305CD2E0BE878009035B9 /* SolianShareExtension */,
|
||||||
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||||
|
7310A7D32EB10962002C0FD3 /* WatchRunner Watch App */,
|
||||||
);
|
);
|
||||||
};
|
};
|
||||||
/* End PBXProject section */
|
/* End PBXProject section */
|
||||||
@@ -516,6 +580,13 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
7310A7D22EB10962002C0FD3 /* Resources */ = {
|
||||||
|
isa = PBXResourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
73ACDFA92E3D0E6100B63535 /* Resources */ = {
|
73ACDFA92E3D0E6100B63535 /* Resources */ = {
|
||||||
isa = PBXResourcesBuildPhase;
|
isa = PBXResourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -566,7 +637,7 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" embed_and_thin\n";
|
||||||
};
|
};
|
||||||
4815E0A19398E51078F4160D /* [CP] Check Pods Manifest.lock */ = {
|
4815E0A19398E51078F4160D /* [CP] Check Pods Manifest.lock */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
@@ -598,10 +669,14 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
name = "[CP] Copy Pods Resources";
|
name = "[CP] Copy Pods Resources";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
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";
|
||||||
@@ -659,10 +734,14 @@
|
|||||||
inputFileListPaths = (
|
inputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
name = "[CP] Embed Pods Frameworks";
|
name = "[CP] Embed Pods Frameworks";
|
||||||
outputFileListPaths = (
|
outputFileListPaths = (
|
||||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
);
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||||
@@ -683,6 +762,49 @@
|
|||||||
shellPath = /bin/sh;
|
shellPath = /bin/sh;
|
||||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||||
};
|
};
|
||||||
|
C74B07D6587D29C67A198025 /* [CP] Embed Pods Frameworks */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
);
|
||||||
|
name = "[CP] Embed Pods Frameworks";
|
||||||
|
outputFileListPaths = (
|
||||||
|
"${PODS_ROOT}/Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App-frameworks.sh\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
|
DDEDA1BA6278B94F0F7B9B61 /* [CP] Check Pods Manifest.lock */ = {
|
||||||
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
inputFileListPaths = (
|
||||||
|
);
|
||||||
|
inputPaths = (
|
||||||
|
"${PODS_PODFILE_DIR_PATH}/Podfile.lock",
|
||||||
|
"${PODS_ROOT}/Manifest.lock",
|
||||||
|
);
|
||||||
|
name = "[CP] Check Pods Manifest.lock";
|
||||||
|
outputFileListPaths = (
|
||||||
|
);
|
||||||
|
outputPaths = (
|
||||||
|
"$(DERIVED_FILE_DIR)/Pods-WatchRunner Watch App-checkManifestLockResult.txt",
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
shellPath = /bin/sh;
|
||||||
|
shellScript = "diff \"${PODS_PODFILE_DIR_PATH}/Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n# This output is used by Xcode 'outputs' to avoid re-running this script phase.\necho \"SUCCESS\" > \"${SCRIPT_OUTPUT_FILE_0}\"\n";
|
||||||
|
showEnvVarsInLog = 0;
|
||||||
|
};
|
||||||
E86CDE9D6464F4F52B910856 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
|
E86CDE9D6464F4F52B910856 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -734,6 +856,13 @@
|
|||||||
);
|
);
|
||||||
runOnlyForDeploymentPostprocessing = 0;
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
};
|
};
|
||||||
|
7310A7D02EB10962002C0FD3 /* Sources */ = {
|
||||||
|
isa = PBXSourcesBuildPhase;
|
||||||
|
buildActionMask = 2147483647;
|
||||||
|
files = (
|
||||||
|
);
|
||||||
|
runOnlyForDeploymentPostprocessing = 0;
|
||||||
|
};
|
||||||
73ACDFA72E3D0E6100B63535 /* Sources */ = {
|
73ACDFA72E3D0E6100B63535 /* Sources */ = {
|
||||||
isa = PBXSourcesBuildPhase;
|
isa = PBXSourcesBuildPhase;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
@@ -853,7 +982,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -883,6 +1012,7 @@
|
|||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ENABLE_EXPLICIT_MODULES = "$(SWIFT_USE_INTEGRATED_DRIVER)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
@@ -897,6 +1027,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -915,6 +1046,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -931,6 +1063,7 @@
|
|||||||
CODE_SIGN_STYLE = Automatic;
|
CODE_SIGN_STYLE = Automatic;
|
||||||
CURRENT_PROJECT_VERSION = 1;
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
GENERATE_INFOPLIST_FILE = YES;
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
MARKETING_VERSION = 1.0;
|
MARKETING_VERSION = 1.0;
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
@@ -939,6 +1072,144 @@
|
|||||||
};
|
};
|
||||||
name = Profile;
|
name = Profile;
|
||||||
};
|
};
|
||||||
|
7310A7E02EB10963002C0FD3 /* Debug */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_PREVIEWS = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = WatchRunner;
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
|
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_ENABLE_DEBUG_INFO = INCLUDE_SOURCE;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.watchkitapp;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = watchos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = 4;
|
||||||
|
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
|
};
|
||||||
|
name = Debug;
|
||||||
|
};
|
||||||
|
7310A7E12EB10963002C0FD3 /* Release */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_PREVIEWS = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = WatchRunner;
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
|
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.watchkitapp;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = watchos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = 4;
|
||||||
|
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
|
};
|
||||||
|
name = Release;
|
||||||
|
};
|
||||||
|
7310A7E22EB10963002C0FD3 /* Profile */ = {
|
||||||
|
isa = XCBuildConfiguration;
|
||||||
|
baseConfigurationReference = 103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */;
|
||||||
|
buildSettings = {
|
||||||
|
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||||
|
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||||
|
ASSETCATALOG_COMPILER_GLOBAL_ACCENT_COLOR_NAME = AccentColor;
|
||||||
|
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE;
|
||||||
|
CLANG_CXX_LANGUAGE_STANDARD = "gnu++20";
|
||||||
|
CLANG_ENABLE_OBJC_WEAK = YES;
|
||||||
|
CLANG_WARN_DOCUMENTATION_COMMENTS = YES;
|
||||||
|
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
|
||||||
|
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE;
|
||||||
|
CODE_SIGN_STYLE = Automatic;
|
||||||
|
CURRENT_PROJECT_VERSION = 1;
|
||||||
|
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||||
|
ENABLE_PREVIEWS = YES;
|
||||||
|
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||||
|
GCC_C_LANGUAGE_STANDARD = gnu17;
|
||||||
|
GENERATE_INFOPLIST_FILE = YES;
|
||||||
|
INFOPLIST_KEY_CFBundleDisplayName = WatchRunner;
|
||||||
|
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||||
|
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||||
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
|
"$(inherited)",
|
||||||
|
"@executable_path/Frameworks",
|
||||||
|
);
|
||||||
|
LOCALIZATION_PREFERS_STRING_CATALOGS = YES;
|
||||||
|
MARKETING_VERSION = 1.0;
|
||||||
|
MTL_FAST_MATH = YES;
|
||||||
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.watchkitapp;
|
||||||
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SDKROOT = watchos;
|
||||||
|
SKIP_INSTALL = YES;
|
||||||
|
STRING_CATALOG_GENERATE_SYMBOLS = YES;
|
||||||
|
SWIFT_APPROACHABLE_CONCURRENCY = YES;
|
||||||
|
SWIFT_DEFAULT_ACTOR_ISOLATION = MainActor;
|
||||||
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_UPCOMING_FEATURE_MEMBER_IMPORT_VISIBILITY = YES;
|
||||||
|
SWIFT_VERSION = 5.0;
|
||||||
|
TARGETED_DEVICE_FAMILY = 4;
|
||||||
|
WATCHOS_DEPLOYMENT_TARGET = 26.0;
|
||||||
|
};
|
||||||
|
name = Profile;
|
||||||
|
};
|
||||||
73ACDFC42E3D0E6100B63535 /* Debug */ = {
|
73ACDFC42E3D0E6100B63535 /* Debug */ = {
|
||||||
isa = XCBuildConfiguration;
|
isa = XCBuildConfiguration;
|
||||||
buildSettings = {
|
buildSettings = {
|
||||||
@@ -1078,7 +1349,7 @@
|
|||||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1093,6 +1364,7 @@
|
|||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
@@ -1121,7 +1393,7 @@
|
|||||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1134,6 +1406,7 @@
|
|||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
@@ -1161,7 +1434,7 @@
|
|||||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||||
LD_RUNPATH_SEARCH_PATHS = (
|
LD_RUNPATH_SEARCH_PATHS = (
|
||||||
"$(inherited)",
|
"$(inherited)",
|
||||||
"@executable_path/Frameworks",
|
"@executable_path/Frameworks",
|
||||||
@@ -1174,6 +1447,7 @@
|
|||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
SKIP_INSTALL = YES;
|
SKIP_INSTALL = YES;
|
||||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||||
|
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
TARGETED_DEVICE_FAMILY = "1,2";
|
TARGETED_DEVICE_FAMILY = "1,2";
|
||||||
};
|
};
|
||||||
@@ -1348,7 +1622,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = YES;
|
MTL_ENABLE_DEBUG_INFO = YES;
|
||||||
ONLY_ACTIVE_ARCH = YES;
|
ONLY_ACTIVE_ARCH = YES;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
@@ -1399,7 +1673,7 @@
|
|||||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||||
MTL_ENABLE_DEBUG_INFO = NO;
|
MTL_ENABLE_DEBUG_INFO = NO;
|
||||||
SDKROOT = iphoneos;
|
SDKROOT = iphoneos;
|
||||||
SUPPORTED_PLATFORMS = iphoneos;
|
SUPPORTED_PLATFORMS = iphoneos;
|
||||||
@@ -1431,6 +1705,7 @@
|
|||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ENABLE_EXPLICIT_MODULES = "$(SWIFT_USE_INTEGRATED_DRIVER)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
@@ -1459,6 +1734,7 @@
|
|||||||
);
|
);
|
||||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
||||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||||
|
SWIFT_ENABLE_EXPLICIT_MODULES = "$(SWIFT_USE_INTEGRATED_DRIVER)";
|
||||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||||
SWIFT_VERSION = 5.0;
|
SWIFT_VERSION = 5.0;
|
||||||
VERSIONING_SYSTEM = "apple-generic";
|
VERSIONING_SYSTEM = "apple-generic";
|
||||||
@@ -1478,6 +1754,16 @@
|
|||||||
defaultConfigurationIsVisible = 0;
|
defaultConfigurationIsVisible = 0;
|
||||||
defaultConfigurationName = Release;
|
defaultConfigurationName = Release;
|
||||||
};
|
};
|
||||||
|
7310A7E32EB10963002C0FD3 /* Build configuration list for PBXNativeTarget "WatchRunner Watch App" */ = {
|
||||||
|
isa = XCConfigurationList;
|
||||||
|
buildConfigurations = (
|
||||||
|
7310A7E02EB10963002C0FD3 /* Debug */,
|
||||||
|
7310A7E12EB10963002C0FD3 /* Release */,
|
||||||
|
7310A7E22EB10963002C0FD3 /* Profile */,
|
||||||
|
);
|
||||||
|
defaultConfigurationIsVisible = 0;
|
||||||
|
defaultConfigurationName = Release;
|
||||||
|
};
|
||||||
73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */ = {
|
73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */ = {
|
||||||
isa = XCConfigurationList;
|
isa = XCConfigurationList;
|
||||||
buildConfigurations = (
|
buildConfigurations = (
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
import Flutter
|
import Flutter
|
||||||
import UIKit
|
import UIKit
|
||||||
|
import WatchConnectivity
|
||||||
|
|
||||||
@main
|
@main
|
||||||
@objc class AppDelegate: FlutterAppDelegate {
|
@objc class AppDelegate: FlutterAppDelegate {
|
||||||
let notifyDelegate = NotifyDelegate()
|
let notifyDelegate = NotifyDelegate()
|
||||||
|
private var watchConnectivityService: WatchConnectivityService?
|
||||||
|
|
||||||
override func application(
|
override func application(
|
||||||
_ application: UIApplication,
|
_ application: UIApplication,
|
||||||
@@ -12,7 +14,7 @@ import UIKit
|
|||||||
UNUserNotificationCenter.current().delegate = notifyDelegate
|
UNUserNotificationCenter.current().delegate = notifyDelegate
|
||||||
|
|
||||||
let replyableMessageCategory = UNNotificationCategory(
|
let replyableMessageCategory = UNNotificationCategory(
|
||||||
identifier: "REPLYABLE_MESSAGE",
|
identifier: "CHAT_MESSAGE",
|
||||||
actions: [
|
actions: [
|
||||||
UNTextInputNotificationAction(
|
UNTextInputNotificationAction(
|
||||||
identifier: "reply_action",
|
identifier: "reply_action",
|
||||||
@@ -28,6 +30,55 @@ import UIKit
|
|||||||
|
|
||||||
GeneratedPluginRegistrant.register(with: self)
|
GeneratedPluginRegistrant.register(with: self)
|
||||||
|
|
||||||
|
if WCSession.isSupported() {
|
||||||
|
watchConnectivityService = WatchConnectivityService()
|
||||||
|
}
|
||||||
|
|
||||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class WatchConnectivityService: NSObject, WCSessionDelegate {
|
||||||
|
private let session: WCSession
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
self.session = .default
|
||||||
|
super.init()
|
||||||
|
print("[iOS] Activating WCSession")
|
||||||
|
self.session.delegate = self
|
||||||
|
self.session.activate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
|
||||||
|
if let error = error {
|
||||||
|
print("[iOS] WCSession activation failed with error: \(error.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("[iOS] WCSession activated with state: \(activationState.rawValue)")
|
||||||
|
}
|
||||||
|
|
||||||
|
func sessionDidBecomeInactive(_ session: WCSession) {}
|
||||||
|
|
||||||
|
func sessionDidDeactivate(_ session: WCSession) {
|
||||||
|
session.activate()
|
||||||
|
}
|
||||||
|
|
||||||
|
func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
|
||||||
|
print("[iOS] Received message: \(message)")
|
||||||
|
if let request = message["request"] as? String, request == "data" {
|
||||||
|
let token = UserDefaults.standard.getFlutterToken()
|
||||||
|
let serverUrl = UserDefaults.standard.getServerUrl()
|
||||||
|
|
||||||
|
print("[iOS] Retrieved token: \(token ?? "nil")")
|
||||||
|
print("[iOS] Retrieved serverUrl: \(serverUrl)")
|
||||||
|
|
||||||
|
var data: [String: Any] = ["serverUrl": serverUrl]
|
||||||
|
if let token = token {
|
||||||
|
data["token"] = token
|
||||||
|
}
|
||||||
|
|
||||||
|
print("[iOS] Replying with data: \(data)")
|
||||||
|
replyHandler(data)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +1,334 @@
|
|||||||
{"images":[{"size":"20x20","idiom":"universal","filename":"Icon-App-20x20@2x.png","scale":"2x","platform":"ios"},{"size":"20x20","idiom":"universal","filename":"Icon-App-20x20@3x.png","scale":"3x","platform":"ios"},{"size":"29x29","idiom":"universal","filename":"Icon-App-29x29@2x.png","scale":"2x","platform":"ios"},{"size":"29x29","idiom":"universal","filename":"Icon-App-29x29@3x.png","scale":"3x","platform":"ios"},{"size":"38x38","idiom":"universal","filename":"Icon-App-38x38@2x.png","scale":"2x","platform":"ios"},{"size":"38x38","idiom":"universal","filename":"Icon-App-38x38@3x.png","scale":"3x","platform":"ios"},{"size":"40x40","idiom":"universal","filename":"Icon-App-40x40@2x.png","scale":"2x","platform":"ios"},{"size":"40x40","idiom":"universal","filename":"Icon-App-40x40@3x.png","scale":"3x","platform":"ios"},{"size":"60x60","idiom":"universal","filename":"Icon-App-60x60@2x.png","scale":"2x","platform":"ios"},{"size":"60x60","idiom":"universal","filename":"Icon-App-60x60@3x.png","scale":"3x","platform":"ios"},{"size":"64x64","idiom":"universal","filename":"Icon-App-64x64@2x.png","scale":"2x","platform":"ios"},{"size":"64x64","idiom":"universal","filename":"Icon-App-64x64@3x.png","scale":"3x","platform":"ios"},{"size":"68x68","idiom":"universal","filename":"Icon-App-68x68@2x.png","scale":"2x","platform":"ios"},{"size":"76x76","idiom":"universal","filename":"Icon-App-76x76@2x.png","scale":"2x","platform":"ios"},{"size":"83.5x83.5","idiom":"universal","filename":"Icon-App-83.5x83.5@2x.png","scale":"2x","platform":"ios"},{"size":"1024x1024","idiom":"universal","filename":"Icon-App-1024x1024@1x.png","scale":"1x","platform":"ios"},{"size":"1024x1024","idiom":"ios-marketing","filename":"Icon-App-1024x1024@1x.png","scale":"1x"},{"size":"20x20","idiom":"universal","filename":"Icon-App-Dark-20x20@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"20x20","idiom":"universal","filename":"Icon-App-Dark-20x20@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"29x29","idiom":"universal","filename":"Icon-App-Dark-29x29@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"29x29","idiom":"universal","filename":"Icon-App-Dark-29x29@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"38x38","idiom":"universal","filename":"Icon-App-Dark-38x38@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"38x38","idiom":"universal","filename":"Icon-App-Dark-38x38@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"40x40","idiom":"universal","filename":"Icon-App-Dark-40x40@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"40x40","idiom":"universal","filename":"Icon-App-Dark-40x40@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"60x60","idiom":"universal","filename":"Icon-App-Dark-60x60@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"60x60","idiom":"universal","filename":"Icon-App-Dark-60x60@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"64x64","idiom":"universal","filename":"Icon-App-Dark-64x64@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"64x64","idiom":"universal","filename":"Icon-App-Dark-64x64@3x.png","scale":"3x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"68x68","idiom":"universal","filename":"Icon-App-Dark-68x68@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"76x76","idiom":"universal","filename":"Icon-App-Dark-76x76@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"83.5x83.5","idiom":"universal","filename":"Icon-App-Dark-83.5x83.5@2x.png","scale":"2x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]},{"size":"1024x1024","idiom":"universal","filename":"Icon-App-Dark-1024x1024@1x.png","scale":"1x","platform":"ios","appearances":[{"appearance":"luminosity","value":"dark"}]}],"info":{"version":1,"author":"xcode"}}
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-20x20@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-20x20@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-29x29@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-29x29@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-38x38@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "38x38"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-38x38@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "38x38"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-40x40@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-40x40@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-60x60@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-60x60@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-64x64@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "64x64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-64x64@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "64x64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-68x68@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "68x68"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-76x76@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-83.5x83.5@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "83.5x83.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-20x20@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-20x20@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "20x20"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-29x29@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-29x29@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "29x29"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-38x38@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "38x38"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-38x38@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "38x38"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-40x40@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-40x40@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "40x40"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-60x60@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-60x60@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "60x60"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-64x64@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "64x64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-64x64@3x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "3x",
|
||||||
|
"size" : "64x64"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-68x68@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "68x68"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-76x76@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "76x76"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-83.5x83.5@2x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "2x",
|
||||||
|
"size" : "83.5x83.5"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"appearances" : [
|
||||||
|
{
|
||||||
|
"appearance" : "luminosity",
|
||||||
|
"value" : "dark"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"filename" : "Icon-App-Dark-1024x1024@1x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "ios",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
|
"idiom" : "ios-marketing",
|
||||||
|
"scale" : "1x",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
|
Before Width: | Height: | Size: 295 B |
|
Before Width: | Height: | Size: 282 B |
|
Before Width: | Height: | Size: 406 B |
|
Before Width: | Height: | Size: 762 B |
@@ -36,6 +36,14 @@
|
|||||||
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||||
</array>
|
</array>
|
||||||
</dict>
|
</dict>
|
||||||
|
<dict>
|
||||||
|
<key>CFBundleTypeRole</key>
|
||||||
|
<string>Viewer</string>
|
||||||
|
<key>CFBundleURLSchemes</key>
|
||||||
|
<array>
|
||||||
|
<string>solian</string>
|
||||||
|
</array>
|
||||||
|
</dict>
|
||||||
</array>
|
</array>
|
||||||
<key>CFBundleVersion</key>
|
<key>CFBundleVersion</key>
|
||||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
import Foundation
|
import Foundation
|
||||||
|
|
||||||
func getAttachmentUrl(for identifier: String) -> String {
|
func getAttachmentUrl(for identifier: String) -> String {
|
||||||
let serverBaseUrl = "https://api.solian.app"
|
let serverBaseUrl = UserDefaults.standard.getServerUrl()
|
||||||
|
|
||||||
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/drive/files/\(identifier)"
|
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/drive/files/\(identifier)"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,6 +26,6 @@ extension UserDefaults {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func getServerUrl(forKey key: String = "app_server_url") -> String {
|
func getServerUrl(forKey key: String = "app_server_url") -> String {
|
||||||
return self.getFlutterValue(forKey: key) ?? "https://nt.solian.app"
|
return self.getFlutterValue(forKey: key) ?? "https://api.solian.app"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -60,8 +60,6 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
|
|
||||||
let pfpIdentifier = meta["pfp"] as? String
|
let pfpIdentifier = meta["pfp"] as? String
|
||||||
|
|
||||||
content.categoryIdentifier = "REPLYABLE_MESSAGE"
|
|
||||||
|
|
||||||
let metaCopy = meta as? [String: Any] ?? [:]
|
let metaCopy = meta as? [String: Any] ?? [:]
|
||||||
let pfpUrl = pfpIdentifier != nil ? getAttachmentUrl(for: pfpIdentifier!) : nil
|
let pfpUrl = pfpIdentifier != nil ? getAttachmentUrl(for: pfpIdentifier!) : nil
|
||||||
|
|
||||||
@@ -87,10 +85,8 @@ class NotificationService: UNNotificationServiceExtension {
|
|||||||
customIdentifier: nil
|
customIdentifier: nil
|
||||||
)
|
)
|
||||||
|
|
||||||
let intent = self.createMessageIntent(with: sender, meta: metaCopy, body: content.body)
|
content.categoryIdentifier = "CHAT_MESSAGE"
|
||||||
self.donateInteraction(for: intent)
|
self.contentHandler?(content)
|
||||||
let updatedContent = try? request.content.updating(from: intent)
|
|
||||||
self.contentHandler?(updatedContent ?? content)
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -0,0 +1,15 @@
|
|||||||
|
{
|
||||||
|
"colors" : [
|
||||||
|
{
|
||||||
|
"color" : {
|
||||||
|
"platform" : "universal",
|
||||||
|
"reference" : "systemIndigoColor"
|
||||||
|
},
|
||||||
|
"idiom" : "universal"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"images" : [
|
||||||
|
{
|
||||||
|
"filename" : "Icon-App-1024x1024@1x.png",
|
||||||
|
"idiom" : "universal",
|
||||||
|
"platform" : "watchos",
|
||||||
|
"size" : "1024x1024"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
|
After Width: | Height: | Size: 48 KiB |
6
ios/WatchRunner Watch App/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
{
|
||||||
|
"info" : {
|
||||||
|
"author" : "xcode",
|
||||||
|
"version" : 1
|
||||||
|
}
|
||||||
|
}
|
||||||
50
ios/WatchRunner Watch App/ContentView.swift
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
//
|
||||||
|
// ContentView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// The root view of the app.
|
||||||
|
struct ContentView: View {
|
||||||
|
@StateObject private var appState = AppState()
|
||||||
|
@State private var selection: Panel? = .explore
|
||||||
|
|
||||||
|
enum Panel: Hashable {
|
||||||
|
case explore
|
||||||
|
case chat
|
||||||
|
case notifications
|
||||||
|
case account
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationSplitView {
|
||||||
|
List(selection: $selection) {
|
||||||
|
Label("Explore", systemImage: "globe").tag(Panel.explore)
|
||||||
|
Label("Chat", systemImage: "message").tag(Panel.chat)
|
||||||
|
Label("Notifications", systemImage: "bell").tag(Panel.notifications)
|
||||||
|
Label("Account", systemImage: "person.circle").tag(Panel.account)
|
||||||
|
}
|
||||||
|
.listStyle(.automatic)
|
||||||
|
} detail: {
|
||||||
|
switch selection {
|
||||||
|
case .explore:
|
||||||
|
ExploreView()
|
||||||
|
.environmentObject(appState)
|
||||||
|
case .chat:
|
||||||
|
ChatView()
|
||||||
|
.environmentObject(appState)
|
||||||
|
case .notifications:
|
||||||
|
NotificationView()
|
||||||
|
.environmentObject(appState)
|
||||||
|
case .account:
|
||||||
|
AccountView()
|
||||||
|
.environmentObject(appState)
|
||||||
|
case .none:
|
||||||
|
Text("Select a panel")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
88
ios/WatchRunner Watch App/Layouts/FlowLayout.swift
Normal file
@@ -0,0 +1,88 @@
|
|||||||
|
//
|
||||||
|
// FlowLayout.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// MARK: - Custom Layouts
|
||||||
|
|
||||||
|
struct FlowLayout: Layout {
|
||||||
|
var alignment: HorizontalAlignment = .leading
|
||||||
|
var spacing: CGFloat = 10
|
||||||
|
|
||||||
|
func sizeThatFits(proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) -> CGSize {
|
||||||
|
let containerWidth = proposal.width ?? 0
|
||||||
|
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
|
||||||
|
|
||||||
|
var currentX: CGFloat = 0
|
||||||
|
var currentY: CGFloat = 0
|
||||||
|
var lineHeight: CGFloat = 0
|
||||||
|
var totalHeight: CGFloat = 0
|
||||||
|
|
||||||
|
for size in sizes {
|
||||||
|
if currentX + size.width > containerWidth {
|
||||||
|
// New line
|
||||||
|
currentX = 0
|
||||||
|
currentY += lineHeight + spacing
|
||||||
|
totalHeight = currentY + size.height
|
||||||
|
lineHeight = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
currentX += size.width + spacing
|
||||||
|
lineHeight = max(lineHeight, size.height)
|
||||||
|
}
|
||||||
|
totalHeight = currentY + lineHeight
|
||||||
|
|
||||||
|
return CGSize(width: containerWidth, height: totalHeight)
|
||||||
|
}
|
||||||
|
|
||||||
|
func placeSubviews(in bounds: CGRect, proposal: ProposedViewSize, subviews: Subviews, cache: inout ()) {
|
||||||
|
let containerWidth = bounds.width
|
||||||
|
let sizes = subviews.map { $0.sizeThatFits(.unspecified) }
|
||||||
|
|
||||||
|
var currentX: CGFloat = 0
|
||||||
|
var currentY: CGFloat = 0
|
||||||
|
var lineHeight: CGFloat = 0
|
||||||
|
var lineElements: [(offset: Int, size: CGSize)] = []
|
||||||
|
|
||||||
|
func placeLine() {
|
||||||
|
let lineWidth = lineElements.map { $0.size.width }.reduce(0, +) + CGFloat(lineElements.count - 1) * spacing
|
||||||
|
var startX: CGFloat = 0
|
||||||
|
switch alignment {
|
||||||
|
case .leading:
|
||||||
|
startX = bounds.minX
|
||||||
|
case .center:
|
||||||
|
startX = bounds.minX + (containerWidth - lineWidth) / 2
|
||||||
|
case .trailing:
|
||||||
|
startX = bounds.maxX - lineWidth
|
||||||
|
default:
|
||||||
|
startX = bounds.minX
|
||||||
|
}
|
||||||
|
|
||||||
|
var xOffset = startX
|
||||||
|
for (offset, size) in lineElements {
|
||||||
|
subviews[offset].place(at: CGPoint(x: xOffset, y: bounds.minY + currentY), proposal: ProposedViewSize(size)) // Use bounds.minY + currentY
|
||||||
|
xOffset += size.width + spacing
|
||||||
|
}
|
||||||
|
lineElements.removeAll() // Clear elements for the next line
|
||||||
|
}
|
||||||
|
|
||||||
|
for (offset, size) in sizes.enumerated() {
|
||||||
|
if currentX + size.width > containerWidth && !lineElements.isEmpty {
|
||||||
|
// New line
|
||||||
|
placeLine()
|
||||||
|
currentX = 0
|
||||||
|
currentY += lineHeight + spacing
|
||||||
|
lineHeight = 0
|
||||||
|
}
|
||||||
|
|
||||||
|
lineElements.append((offset, size))
|
||||||
|
currentX += size.width + spacing
|
||||||
|
lineHeight = max(lineHeight, size.height)
|
||||||
|
}
|
||||||
|
placeLine() // Place the last line
|
||||||
|
}
|
||||||
|
}
|
||||||
365
ios/WatchRunner Watch App/Models/Models.swift
Normal file
@@ -0,0 +1,365 @@
|
|||||||
|
// Models.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// MARK: - Models
|
||||||
|
|
||||||
|
struct AppToken: Codable {
|
||||||
|
let token: String
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnActivity: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let type: String
|
||||||
|
let data: ActivityData?
|
||||||
|
let createdAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
enum ActivityData: Codable {
|
||||||
|
case post(SnPost)
|
||||||
|
case discovery(DiscoveryData)
|
||||||
|
case unknown
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.singleValueContainer()
|
||||||
|
if let post = try? container.decode(SnPost.self) {
|
||||||
|
self = .post(post)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let discoveryData = try? container.decode(DiscoveryData.self) {
|
||||||
|
self = .discovery(discoveryData)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self = .unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(to encoder: Encoder) throws {
|
||||||
|
// Not needed for decoding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnPost: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let title: String?
|
||||||
|
let content: String?
|
||||||
|
let publisher: SnPublisher
|
||||||
|
let attachments: [SnCloudFile]
|
||||||
|
let tags: [SnPostTag]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DiscoveryData: Codable {
|
||||||
|
let items: [DiscoveryItem]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DiscoveryItem: Codable, Identifiable {
|
||||||
|
var id = UUID()
|
||||||
|
let type: String
|
||||||
|
let data: DiscoveryItemData
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case type, data
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
enum DiscoveryItemData: Codable {
|
||||||
|
case realm(SnRealm)
|
||||||
|
case publisher(SnPublisher)
|
||||||
|
case article(SnWebArticle)
|
||||||
|
case unknown
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.singleValueContainer()
|
||||||
|
if let realm = try? container.decode(SnRealm.self) {
|
||||||
|
self = .realm(realm)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let publisher = try? container.decode(SnPublisher.self) {
|
||||||
|
self = .publisher(publisher)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if let article = try? container.decode(SnWebArticle.self) {
|
||||||
|
self = .article(article)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
self = .unknown
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(to encoder: Encoder) throws {
|
||||||
|
// Not needed for decoding
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnRealm: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let name: String
|
||||||
|
let description: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnPublisher: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let name: String
|
||||||
|
let nick: String?
|
||||||
|
let description: String?
|
||||||
|
let picture: SnCloudFile?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnCloudFile: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let mimeType: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnPostTag: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let slug: String
|
||||||
|
let name: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnWebArticle: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let title: String
|
||||||
|
let url: String
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnNotification: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let topic: String
|
||||||
|
let title: String
|
||||||
|
let subtitle: String
|
||||||
|
let content: String
|
||||||
|
let meta: [String: AnyCodable]?
|
||||||
|
let priority: Int
|
||||||
|
let viewedAt: Date?
|
||||||
|
let accountId: String
|
||||||
|
let createdAt: Date
|
||||||
|
let updatedAt: Date
|
||||||
|
let deletedAt: Date?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case id
|
||||||
|
case topic
|
||||||
|
case title
|
||||||
|
case subtitle
|
||||||
|
case content
|
||||||
|
case meta
|
||||||
|
case priority
|
||||||
|
case viewedAt = "viewedAt"
|
||||||
|
case accountId = "accountId"
|
||||||
|
case createdAt = "createdAt"
|
||||||
|
case updatedAt = "updatedAt"
|
||||||
|
case deletedAt = "deletedAt"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct AnyCodable: Codable {
|
||||||
|
let value: Any
|
||||||
|
|
||||||
|
init(_ value: Any) {
|
||||||
|
self.value = value
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.singleValueContainer()
|
||||||
|
if let intValue = try? container.decode(Int.self) {
|
||||||
|
value = intValue
|
||||||
|
} else if let doubleValue = try? container.decode(Double.self) {
|
||||||
|
value = doubleValue
|
||||||
|
} else if let boolValue = try? container.decode(Bool.self) {
|
||||||
|
value = boolValue
|
||||||
|
} else if let stringValue = try? container.decode(String.self) {
|
||||||
|
value = stringValue
|
||||||
|
} else if let arrayValue = try? container.decode([AnyCodable].self) {
|
||||||
|
value = arrayValue
|
||||||
|
} else if let dictValue = try? container.decode([String: AnyCodable].self) {
|
||||||
|
value = dictValue
|
||||||
|
} else {
|
||||||
|
value = NSNull()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func encode(to encoder: Encoder) throws {
|
||||||
|
var container = encoder.singleValueContainer()
|
||||||
|
switch value {
|
||||||
|
case let intValue as Int:
|
||||||
|
try container.encode(intValue)
|
||||||
|
case let doubleValue as Double:
|
||||||
|
try container.encode(doubleValue)
|
||||||
|
case let boolValue as Bool:
|
||||||
|
try container.encode(boolValue)
|
||||||
|
case let stringValue as String:
|
||||||
|
try container.encode(stringValue)
|
||||||
|
case let arrayValue as [AnyCodable]:
|
||||||
|
try container.encode(arrayValue)
|
||||||
|
case let dictValue as [String: AnyCodable]:
|
||||||
|
try container.encode(dictValue)
|
||||||
|
default:
|
||||||
|
try container.encodeNil()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NotificationResponse {
|
||||||
|
let notifications: [SnNotification]
|
||||||
|
let total: Int
|
||||||
|
let hasMore: Bool
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ActivityResponse {
|
||||||
|
let activities: [SnActivity]
|
||||||
|
let hasMore: Bool
|
||||||
|
let nextCursor: String?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnAccount: Codable {
|
||||||
|
let id: String
|
||||||
|
let name: String
|
||||||
|
let nick: String
|
||||||
|
let profile: SnUserProfile
|
||||||
|
let createdAt: Date
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnUserProfile: Codable {
|
||||||
|
let bio: String?
|
||||||
|
let picture: SnCloudFile?
|
||||||
|
let background: SnCloudFile?
|
||||||
|
let level: Int
|
||||||
|
let experience: Int
|
||||||
|
let levelingProgress: Double
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnAccountStatus: Codable {
|
||||||
|
let id: String
|
||||||
|
let attitude: Int
|
||||||
|
let isOnline: Bool
|
||||||
|
let isInvisible: Bool
|
||||||
|
let isNotDisturb: Bool
|
||||||
|
let isCustomized: Bool
|
||||||
|
let label: String
|
||||||
|
let meta: [String: AnyCodable]?
|
||||||
|
let clearedAt: Date?
|
||||||
|
let accountId: String
|
||||||
|
let createdAt: Date
|
||||||
|
let updatedAt: Date
|
||||||
|
let deletedAt: Date?
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Chat Models
|
||||||
|
|
||||||
|
struct SnChatRoom: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let name: String?
|
||||||
|
let description: String?
|
||||||
|
let type: Int
|
||||||
|
let isPublic: Bool
|
||||||
|
let isCommunity: Bool
|
||||||
|
let picture: SnCloudFile?
|
||||||
|
let background: SnCloudFile?
|
||||||
|
let realmId: String?
|
||||||
|
let realm: SnRealm?
|
||||||
|
let createdAt: Date
|
||||||
|
let updatedAt: Date
|
||||||
|
let deletedAt: Date?
|
||||||
|
let members: [SnChatMember]?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnChatMessage: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let type: String
|
||||||
|
let content: String?
|
||||||
|
let nonce: String?
|
||||||
|
let meta: [String: AnyCodable]
|
||||||
|
let membersMentioned: [String]?
|
||||||
|
let editedAt: Date?
|
||||||
|
let attachments: [SnCloudFile]
|
||||||
|
let reactions: [SnChatReaction]
|
||||||
|
let repliedMessageId: String?
|
||||||
|
let forwardedMessageId: String?
|
||||||
|
let senderId: String
|
||||||
|
let sender: SnChatMember
|
||||||
|
let chatRoomId: String
|
||||||
|
let createdAt: Date
|
||||||
|
let updatedAt: Date
|
||||||
|
let deletedAt: Date?
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case id, type, content, nonce, meta, membersMentioned, editedAt, attachments, reactions, repliedMessageId, forwardedMessageId, senderId, sender, chatRoomId, createdAt, updatedAt, deletedAt
|
||||||
|
}
|
||||||
|
|
||||||
|
init(from decoder: Decoder) throws {
|
||||||
|
let container = try decoder.container(keyedBy: CodingKeys.self)
|
||||||
|
id = try container.decode(String.self, forKey: .id)
|
||||||
|
type = try container.decode(String.self, forKey: .type)
|
||||||
|
content = try container.decodeIfPresent(String.self, forKey: .content)
|
||||||
|
nonce = try container.decodeIfPresent(String.self, forKey: .nonce)
|
||||||
|
meta = try container.decode([String: AnyCodable].self, forKey: .meta)
|
||||||
|
membersMentioned = try container.decodeIfPresent([String].self, forKey: .membersMentioned) ?? []
|
||||||
|
editedAt = try container.decodeIfPresent(Date.self, forKey: .editedAt)
|
||||||
|
attachments = try container.decode([SnCloudFile].self, forKey: .attachments)
|
||||||
|
reactions = try container.decode([SnChatReaction].self, forKey: .reactions)
|
||||||
|
repliedMessageId = try container.decodeIfPresent(String.self, forKey: .repliedMessageId)
|
||||||
|
forwardedMessageId = try container.decodeIfPresent(String.self, forKey: .forwardedMessageId)
|
||||||
|
senderId = try container.decode(String.self, forKey: .senderId)
|
||||||
|
sender = try container.decode(SnChatMember.self, forKey: .sender)
|
||||||
|
chatRoomId = try container.decode(String.self, forKey: .chatRoomId)
|
||||||
|
createdAt = try container.decode(Date.self, forKey: .createdAt)
|
||||||
|
updatedAt = try container.decode(Date.self, forKey: .updatedAt)
|
||||||
|
deletedAt = try container.decodeIfPresent(Date.self, forKey: .deletedAt)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnChatReaction: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let messageId: String
|
||||||
|
let senderId: String
|
||||||
|
let sender: SnChatMember
|
||||||
|
let symbol: String
|
||||||
|
let attitude: Int
|
||||||
|
let createdAt: Date
|
||||||
|
let updatedAt: Date
|
||||||
|
let deletedAt: Date?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnChatMember: Codable, Identifiable {
|
||||||
|
let id: String
|
||||||
|
let chatRoomId: String
|
||||||
|
let chatRoom: SnChatRoom?
|
||||||
|
let accountId: String
|
||||||
|
let account: SnAccount
|
||||||
|
let nick: String?
|
||||||
|
let role: Int
|
||||||
|
let notify: Int
|
||||||
|
let joinedAt: Date?
|
||||||
|
let breakUntil: Date?
|
||||||
|
let timeoutUntil: Date?
|
||||||
|
let isBot: Bool
|
||||||
|
let status: SnAccountStatus?
|
||||||
|
let createdAt: Date
|
||||||
|
let updatedAt: Date
|
||||||
|
let deletedAt: Date?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct SnChatSummary: Codable {
|
||||||
|
let unreadCount: Int
|
||||||
|
let lastMessage: SnChatMessage?
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatRoomsResponse {
|
||||||
|
let rooms: [SnChatRoom]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatInvitesResponse {
|
||||||
|
let invites: [SnChatMember]
|
||||||
|
}
|
||||||
|
|
||||||
|
struct MessageSyncResponse: Codable {
|
||||||
|
let messages: [SnChatMessage]
|
||||||
|
let currentTimestamp: Date
|
||||||
|
|
||||||
|
enum CodingKeys: String, CodingKey {
|
||||||
|
case messages
|
||||||
|
case currentTimestamp = "current_timestamp"
|
||||||
|
}
|
||||||
|
}
|
||||||
15
ios/WatchRunner Watch App/Previews/CustomPreviews.swift
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
//
|
||||||
|
// CustomPreviews.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
NavigationStack {
|
||||||
|
ActivityListView(filter: "Preview", mockActivities: SnActivity.mock)
|
||||||
|
.environmentObject(AppState())
|
||||||
|
}
|
||||||
|
}
|
||||||
35
ios/WatchRunner Watch App/Previews/MockData.swift
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// MockData.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
#if DEBUG
|
||||||
|
extension SnActivity {
|
||||||
|
static var mock: [SnActivity] {
|
||||||
|
let mockPublisher = SnPublisher(id: "pub1", name: "Mock Publisher", nick: "mock_nick", description: "A publisher for testing", picture: SnCloudFile(id: "mock_avatar_id", mimeType: "image/png"))
|
||||||
|
let mockTag1 = SnPostTag(id: "tag1", slug: "swiftui", name: "SwiftUI")
|
||||||
|
let mockTag2 = SnPostTag(id: "tag2", slug: "watchos", name: "watchOS")
|
||||||
|
let mockAttachment1 = SnCloudFile(id: "mock_image_id_1", mimeType: "image/jpeg")
|
||||||
|
let mockAttachment2 = SnCloudFile(id: "mock_image_id_2", mimeType: "image/png")
|
||||||
|
|
||||||
|
let post1 = SnPost(id: "1", title: "Hello from a Mock Post!", content: "This is a mock post content. It can be a bit longer to see how it wraps.", publisher: mockPublisher, attachments: [mockAttachment1, mockAttachment2], tags: [mockTag1, mockTag2])
|
||||||
|
let activity1 = SnActivity(id: "1", type: "posts.new", data: .post(post1), createdAt: Date())
|
||||||
|
|
||||||
|
let realm1 = SnRealm(id: "r1", name: "SwiftUI Previews", description: "A place for designing in previews.")
|
||||||
|
let publisher1 = SnPublisher(id: "p1", name: "The Mock Times", nick: "mock_times", description: "All the news that's fit to mock.", picture: nil)
|
||||||
|
let article1 = SnWebArticle(id: "a1", title: "The Art of Mocking Data", url: "https://example.com")
|
||||||
|
|
||||||
|
let discoveryItem1 = DiscoveryItem(type: "realm", data: .realm(realm1))
|
||||||
|
let discoveryItem2 = DiscoveryItem(type: "publisher", data: .publisher(publisher1))
|
||||||
|
let discoveryItem3 = DiscoveryItem(type: "article", data: .article(article1))
|
||||||
|
let discoveryData = DiscoveryData(items: [discoveryItem1, discoveryItem2, discoveryItem3])
|
||||||
|
let activity2 = SnActivity(id: "2", type: "discovery", data: .discovery(discoveryData), createdAt: Date())
|
||||||
|
|
||||||
|
return [activity1, activity2]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
97
ios/WatchRunner Watch App/Services/ImageLoader.swift
Normal file
@@ -0,0 +1,97 @@
|
|||||||
|
//
|
||||||
|
// ImageLoader.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Kingfisher
|
||||||
|
import KingfisherWebP
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
// MARK: - Image Loader
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class ImageLoader: ObservableObject {
|
||||||
|
@Published var image: Image?
|
||||||
|
@Published var errorMessage: String?
|
||||||
|
@Published var isLoading = false
|
||||||
|
|
||||||
|
private var currentTask: DownloadTask?
|
||||||
|
|
||||||
|
init() {}
|
||||||
|
|
||||||
|
deinit {
|
||||||
|
currentTask?.cancel()
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadImage(from initialUrl: URL, token: String) async {
|
||||||
|
isLoading = true
|
||||||
|
errorMessage = nil
|
||||||
|
image = nil
|
||||||
|
|
||||||
|
// Create request modifier for authorization
|
||||||
|
let modifier = AnyModifier { request in
|
||||||
|
var r = request
|
||||||
|
r.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
r.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
return r
|
||||||
|
}
|
||||||
|
|
||||||
|
// Use WebP processor as default since the app seems to handle WebP images
|
||||||
|
let processor = WebPProcessor.default
|
||||||
|
|
||||||
|
// Use KingfisherManager to retrieve image with caching
|
||||||
|
currentTask = KingfisherManager.shared.retrieveImage(
|
||||||
|
with: initialUrl,
|
||||||
|
options: [
|
||||||
|
.requestModifier(modifier),
|
||||||
|
.processor(processor),
|
||||||
|
.cacheOriginalImage, // Cache the original image data
|
||||||
|
.loadDiskFileSynchronously // Load from disk cache synchronously if available
|
||||||
|
]
|
||||||
|
) { [weak self] result in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
Task { @MainActor in
|
||||||
|
switch result {
|
||||||
|
case .success(let value):
|
||||||
|
self.image = Image(uiImage: value.image)
|
||||||
|
print("[watchOS] Image loaded successfully from \(value.cacheType == .none ? "network" : "cache (\(value.cacheType))").")
|
||||||
|
self.isLoading = false
|
||||||
|
case .failure(let error):
|
||||||
|
// If WebP processor fails (likely due to format), try with default processor
|
||||||
|
let defaultProcessor = DefaultImageProcessor.default
|
||||||
|
self.currentTask = KingfisherManager.shared.retrieveImage(
|
||||||
|
with: initialUrl,
|
||||||
|
options: [
|
||||||
|
.requestModifier(modifier),
|
||||||
|
.processor(defaultProcessor),
|
||||||
|
.cacheOriginalImage,
|
||||||
|
.loadDiskFileSynchronously
|
||||||
|
]
|
||||||
|
) { [weak self] fallbackResult in
|
||||||
|
guard let self = self else { return }
|
||||||
|
|
||||||
|
Task { @MainActor in
|
||||||
|
switch fallbackResult {
|
||||||
|
case .success(let value):
|
||||||
|
self.image = Image(uiImage: value.image)
|
||||||
|
print("[watchOS] Image loaded successfully from \(value.cacheType == .none ? "network" : "cache (\(value.cacheType))") using fallback processor.")
|
||||||
|
case .failure(let fallbackError):
|
||||||
|
self.errorMessage = fallbackError.localizedDescription
|
||||||
|
print("[watchOS] Image loading failed: \(fallbackError.localizedDescription)")
|
||||||
|
}
|
||||||
|
self.isLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func cancel() {
|
||||||
|
currentTask?.cancel()
|
||||||
|
}
|
||||||
|
}
|
||||||
399
ios/WatchRunner Watch App/Services/NetworkService.swift
Normal file
@@ -0,0 +1,399 @@
|
|||||||
|
//
|
||||||
|
// NetworkService.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// MARK: - Network Service
|
||||||
|
|
||||||
|
class NetworkService {
|
||||||
|
private let session = URLSession.shared
|
||||||
|
|
||||||
|
func fetchActivities(filter: String, cursor: String? = nil, token: String, serverUrl: String) async throws -> ActivityResponse {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
var components = URLComponents(url: baseURL.appendingPathComponent("/sphere/activities"), resolvingAgainstBaseURL: false)!
|
||||||
|
var queryItems = [URLQueryItem(name: "take", value: "20")]
|
||||||
|
if filter.lowercased() != "explore" {
|
||||||
|
queryItems.append(URLQueryItem(name: "filter", value: filter.lowercased()))
|
||||||
|
}
|
||||||
|
if let cursor = cursor {
|
||||||
|
queryItems.append(URLQueryItem(name: "cursor", value: cursor))
|
||||||
|
}
|
||||||
|
components.queryItems = queryItems
|
||||||
|
|
||||||
|
var request = URLRequest(url: components.url!)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, _) = try await session.data(for: request)
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
let activities = try decoder.decode([SnActivity].self, from: data)
|
||||||
|
|
||||||
|
let hasMore = (activities.first?.type ?? "empty") != "empty"
|
||||||
|
let nextCursor = activities.isEmpty ? nil : activities.map { $0.createdAt }.min()?.ISO8601Format()
|
||||||
|
|
||||||
|
return ActivityResponse(activities: activities, hasMore: hasMore, nextCursor: nextCursor)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createPost(title: String, content: String, token: String, serverUrl: String) async throws {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/sphere/posts")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let body: [String: Any] = ["title": title, "content": content]
|
||||||
|
request.httpBody = try JSONSerialization.data(withJSONObject: body)
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 201 {
|
||||||
|
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||||
|
print("[watchOS] createPost failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||||
|
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchNotifications(offset: Int = 0, take: Int = 20, token: String, serverUrl: String) async throws -> NotificationResponse {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
var components = URLComponents(url: baseURL.appendingPathComponent("/ring/notifications"), resolvingAgainstBaseURL: false)!
|
||||||
|
var queryItems = [URLQueryItem(name: "offset", value: String(offset)), URLQueryItem(name: "take", value: String(take))]
|
||||||
|
components.queryItems = queryItems
|
||||||
|
|
||||||
|
var request = URLRequest(url: components.url!)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
let notifications = try decoder.decode([SnNotification].self, from: data)
|
||||||
|
|
||||||
|
let httpResponse = response as? HTTPURLResponse
|
||||||
|
let total = Int(httpResponse?.value(forHTTPHeaderField: "X-Total") ?? "0") ?? 0
|
||||||
|
let hasMore = offset + notifications.count < total
|
||||||
|
|
||||||
|
return NotificationResponse(notifications: notifications, total: total, hasMore: hasMore)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchUserProfile(token: String, serverUrl: String) async throws -> SnAccount {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/pass/accounts/me")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, _) = try await session.data(for: request)
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
return try decoder.decode(SnAccount.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchAccountStatus(token: String, serverUrl: String) async throws -> SnAccountStatus? {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/pass/accounts/me/statuses")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 404 {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
return try decoder.decode(SnAccountStatus.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createOrUpdateStatus(attitude: Int, isInvisible: Bool, isNotDisturb: Bool, label: String?, token: String, serverUrl: String) async throws -> SnAccountStatus {
|
||||||
|
// Check if there's already a customized status
|
||||||
|
let existingStatus = try? await fetchAccountStatus(token: token, serverUrl: serverUrl)
|
||||||
|
let method = (existingStatus?.isCustomized == true) ? "PATCH" : "POST"
|
||||||
|
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/pass/accounts/me/statuses")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = method
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
var body: [String: Any] = [
|
||||||
|
"attitude": attitude,
|
||||||
|
"is_invisible": isInvisible,
|
||||||
|
"is_not_disturb": isNotDisturb
|
||||||
|
]
|
||||||
|
|
||||||
|
if let label = label, !label.isEmpty {
|
||||||
|
body["label"] = label
|
||||||
|
}
|
||||||
|
|
||||||
|
request.httpBody = try JSONSerialization.data(withJSONObject: body)
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 201 && httpResponse.statusCode != 200 {
|
||||||
|
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||||
|
print("[watchOS] createOrUpdateStatus failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||||
|
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||||
|
}
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
return try decoder.decode(SnAccountStatus.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func clearStatus(token: String, serverUrl: String) async throws {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/pass/accounts/me/statuses")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "DELETE"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 204 {
|
||||||
|
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||||
|
print("[watchOS] clearStatus failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||||
|
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Chat API Methods
|
||||||
|
|
||||||
|
func fetchChatRooms(token: String, serverUrl: String) async throws -> ChatRoomsResponse {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/sphere/chat")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, _) = try await session.data(for: request)
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
let rooms = try decoder.decode([SnChatRoom].self, from: data)
|
||||||
|
return ChatRoomsResponse(rooms: rooms)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchChatRoom(identifier: String, token: String, serverUrl: String) async throws -> SnChatRoom {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/sphere/chat/\(identifier)")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 404 {
|
||||||
|
throw URLError(.resourceUnavailable)
|
||||||
|
}
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
return try decoder.decode(SnChatRoom.self, from: data)
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchChatInvites(token: String, serverUrl: String) async throws -> ChatInvitesResponse {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/sphere/chat/invites")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, _) = try await session.data(for: request)
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
let invites = try decoder.decode([SnChatMember].self, from: data)
|
||||||
|
return ChatInvitesResponse(invites: invites)
|
||||||
|
}
|
||||||
|
|
||||||
|
func acceptChatInvite(chatRoomId: String, token: String, serverUrl: String) async throws {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/sphere/chat/invites/\(chatRoomId)/accept")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
|
||||||
|
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||||
|
print("[watchOS] acceptChatInvite failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||||
|
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func declineChatInvite(chatRoomId: String, token: String, serverUrl: String) async throws {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
let url = baseURL.appendingPathComponent("/sphere/chat/invites/\(chatRoomId)/decline")
|
||||||
|
|
||||||
|
var request = URLRequest(url: url)
|
||||||
|
request.httpMethod = "POST"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode != 200 {
|
||||||
|
let responseBody = String(data: data, encoding: .utf8) ?? ""
|
||||||
|
print("[watchOS] declineChatInvite failed with status code: \(httpResponse.statusCode), body: \(responseBody)")
|
||||||
|
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// MARK: - Message API Methods
|
||||||
|
|
||||||
|
func fetchChatMessages(chatRoomId: String, token: String, serverUrl: String, before: Date? = nil, take: Int = 50) async throws -> [SnChatMessage] {
|
||||||
|
guard let baseURL = URL(string: serverUrl) else {
|
||||||
|
throw URLError(.badURL)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Try a different pattern: /sphere/chat/messages with roomId as query param
|
||||||
|
var components = URLComponents(
|
||||||
|
url: baseURL.appendingPathComponent("/sphere/chat/\(chatRoomId)/messages"),
|
||||||
|
resolvingAgainstBaseURL: false
|
||||||
|
)!
|
||||||
|
var queryItems = [
|
||||||
|
URLQueryItem(name: "take", value: String(take))
|
||||||
|
]
|
||||||
|
if let before = before {
|
||||||
|
queryItems.append(URLQueryItem(name: "before", value: ISO8601DateFormatter().string(from: before)))
|
||||||
|
}
|
||||||
|
components.queryItems = queryItems
|
||||||
|
|
||||||
|
var request = URLRequest(url: components.url!)
|
||||||
|
request.httpMethod = "GET"
|
||||||
|
request.setValue("application/json", forHTTPHeaderField: "Accept")
|
||||||
|
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||||
|
request.setValue("SolianWatch/1.0", forHTTPHeaderField: "User-Agent")
|
||||||
|
|
||||||
|
let (data, response) = try await session.data(for: request)
|
||||||
|
|
||||||
|
if let httpResponse = response as? HTTPURLResponse {
|
||||||
|
_ = String(data: data, encoding: .utf8) ?? "Unable to decode response body"
|
||||||
|
|
||||||
|
if httpResponse.statusCode != 200 {
|
||||||
|
print("[watchOS] fetchChatMessages failed with status \(httpResponse.statusCode)")
|
||||||
|
throw URLError(URLError.Code(rawValue: httpResponse.statusCode))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if data is empty
|
||||||
|
if data.isEmpty {
|
||||||
|
print("[watchOS] fetchChatMessages received empty response data")
|
||||||
|
return []
|
||||||
|
}
|
||||||
|
|
||||||
|
let decoder = JSONDecoder()
|
||||||
|
decoder.dateDecodingStrategy = .iso8601
|
||||||
|
decoder.keyDecodingStrategy = .convertFromSnakeCase
|
||||||
|
|
||||||
|
do {
|
||||||
|
let messages = try decoder.decode([SnChatMessage].self, from: data)
|
||||||
|
print("[watchOS] fetchChatMessages successfully decoded \(messages.count) messages")
|
||||||
|
return messages
|
||||||
|
} catch DecodingError.dataCorrupted(let context) {
|
||||||
|
print(context)
|
||||||
|
return []
|
||||||
|
} catch DecodingError.keyNotFound(let key, let context) {
|
||||||
|
print("Key '\(key)' not found:", context.debugDescription)
|
||||||
|
print("codingPath:", context.codingPath)
|
||||||
|
return []
|
||||||
|
} catch DecodingError.valueNotFound(let value, let context) {
|
||||||
|
print("Value '\(value)' not found:", context.debugDescription)
|
||||||
|
print("codingPath:", context.codingPath)
|
||||||
|
return []
|
||||||
|
} catch DecodingError.typeMismatch(let type, let context) {
|
||||||
|
print("Type '\(type)' mismatch:", context.debugDescription)
|
||||||
|
print("codingPath:", context.codingPath)
|
||||||
|
return []
|
||||||
|
} catch {
|
||||||
|
print("error: ", error)
|
||||||
|
throw error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
39
ios/WatchRunner Watch App/State/AppState.swift
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
//
|
||||||
|
// AppState.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
// MARK: - App State
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class AppState: ObservableObject {
|
||||||
|
@Published var token: String? = nil
|
||||||
|
@Published var serverUrl: String? = nil
|
||||||
|
@Published var isReady = false
|
||||||
|
|
||||||
|
let networkService = NetworkService()
|
||||||
|
private var wcService = WatchConnectivityService()
|
||||||
|
private var cancellables = Set<AnyCancellable>()
|
||||||
|
|
||||||
|
init() {
|
||||||
|
wcService.$token.combineLatest(wcService.$serverUrl)
|
||||||
|
.receive(on: DispatchQueue.main)
|
||||||
|
.sink { [weak self] token, serverUrl in
|
||||||
|
self?.token = token
|
||||||
|
self?.serverUrl = serverUrl
|
||||||
|
if token != nil && serverUrl != nil {
|
||||||
|
self?.isReady = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.store(in: &cancellables)
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestData() {
|
||||||
|
wcService.requestDataFromPhone()
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,84 @@
|
|||||||
|
//
|
||||||
|
// WatchConnectivityService.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import WatchConnectivity
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
// MARK: - Watch Connectivity
|
||||||
|
|
||||||
|
class WatchConnectivityService: NSObject, WCSessionDelegate, ObservableObject {
|
||||||
|
@Published var token: String?
|
||||||
|
@Published var serverUrl: String?
|
||||||
|
|
||||||
|
private let session: WCSession
|
||||||
|
private let userDefaults = UserDefaults.standard
|
||||||
|
private let tokenKey = "token"
|
||||||
|
private let serverUrlKey = "serverUrl"
|
||||||
|
|
||||||
|
override init() {
|
||||||
|
self.session = .default
|
||||||
|
super.init()
|
||||||
|
print("[watchOS] Activating WCSession")
|
||||||
|
self.session.delegate = self
|
||||||
|
self.session.activate()
|
||||||
|
|
||||||
|
// Load cached data
|
||||||
|
self.token = userDefaults.string(forKey: tokenKey)
|
||||||
|
self.serverUrl = userDefaults.string(forKey: serverUrlKey)
|
||||||
|
}
|
||||||
|
|
||||||
|
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
|
||||||
|
if let error = error {
|
||||||
|
print("[watchOS] WCSession activation failed with error: \(error.localizedDescription)")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
print("[watchOS] WCSession activated with state: \(activationState.rawValue)")
|
||||||
|
if activationState == .activated {
|
||||||
|
requestDataFromPhone()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func session(_ session: WCSession, didReceiveMessage message: [String : Any]) {
|
||||||
|
print("[watchOS] Received message: \(message)")
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if let token = message["token"] as? String {
|
||||||
|
self.token = token
|
||||||
|
self.userDefaults.set(token, forKey: self.tokenKey)
|
||||||
|
}
|
||||||
|
if let serverUrl = message["serverUrl"] as? String {
|
||||||
|
self.serverUrl = serverUrl
|
||||||
|
self.userDefaults.set(serverUrl, forKey: self.serverUrlKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func requestDataFromPhone() {
|
||||||
|
guard session.isReachable else {
|
||||||
|
print("[watchOS] Phone is not reachable")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
print("[watchOS] Requesting data from phone")
|
||||||
|
session.sendMessage(["request": "data"]) { [weak self] response in
|
||||||
|
guard let self = self else { return }
|
||||||
|
print("[watchOS] Received reply: \(response)")
|
||||||
|
DispatchQueue.main.async {
|
||||||
|
if let token = response["token"] as? String {
|
||||||
|
self.token = token
|
||||||
|
self.userDefaults.set(token, forKey: self.tokenKey)
|
||||||
|
}
|
||||||
|
if let serverUrl = response["serverUrl"] as? String {
|
||||||
|
self.serverUrl = serverUrl
|
||||||
|
self.userDefaults.set(serverUrl, forKey: self.serverUrlKey)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} errorHandler: { error in
|
||||||
|
print("[watchOS] sendMessage failed with error: \(error.localizedDescription)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
20
ios/WatchRunner Watch App/Utils/AttachmentUtils.swift
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
//
|
||||||
|
// AttachmentUtils.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
// MARK: - Helper Functions
|
||||||
|
|
||||||
|
func getAttachmentUrl(for fileId: String, serverUrl: String) -> URL? {
|
||||||
|
let urlString: String
|
||||||
|
if fileId.starts(with: "http") {
|
||||||
|
urlString = fileId
|
||||||
|
} else {
|
||||||
|
urlString = "\(serverUrl)/drive/files/\(fileId)"
|
||||||
|
}
|
||||||
|
return URL(string: urlString)
|
||||||
|
}
|
||||||
73
ios/WatchRunner Watch App/ViewModels/ActivityViewModel.swift
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
//
|
||||||
|
// ActivityViewModel.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
// MARK: - View Models
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class ActivityViewModel: ObservableObject {
|
||||||
|
@Published var activities: [SnActivity] = []
|
||||||
|
@Published var isLoading = false
|
||||||
|
@Published var isLoadingMore = false
|
||||||
|
@Published var errorMessage: String?
|
||||||
|
@Published var hasMore = false
|
||||||
|
|
||||||
|
private let networkService = NetworkService()
|
||||||
|
let filter: String
|
||||||
|
private var isMock = false
|
||||||
|
private var hasFetched = false
|
||||||
|
private var nextCursor: String?
|
||||||
|
|
||||||
|
init(filter: String, mockActivities: [SnActivity]? = nil) {
|
||||||
|
self.filter = filter
|
||||||
|
if let mockActivities = mockActivities {
|
||||||
|
self.activities = mockActivities
|
||||||
|
self.isMock = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func fetchActivities(token: String, serverUrl: String) async {
|
||||||
|
if isMock || hasFetched { return }
|
||||||
|
guard !isLoading else { return }
|
||||||
|
isLoading = true
|
||||||
|
errorMessage = nil
|
||||||
|
hasFetched = true
|
||||||
|
nextCursor = nil
|
||||||
|
|
||||||
|
do {
|
||||||
|
let response = try await networkService.fetchActivities(filter: filter, cursor: nil, token: token, serverUrl: serverUrl)
|
||||||
|
self.activities = response.activities
|
||||||
|
self.hasMore = response.hasMore
|
||||||
|
self.nextCursor = response.nextCursor
|
||||||
|
} catch {
|
||||||
|
self.errorMessage = error.localizedDescription
|
||||||
|
print("[watchOS] fetchActivities failed with error: \(error)")
|
||||||
|
hasFetched = false
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadMoreActivities(token: String, serverUrl: String) async {
|
||||||
|
guard !isLoadingMore && hasMore && nextCursor != nil else { return }
|
||||||
|
isLoadingMore = true
|
||||||
|
|
||||||
|
do {
|
||||||
|
let response = try await networkService.fetchActivities(filter: filter, cursor: nextCursor, token: token, serverUrl: serverUrl)
|
||||||
|
self.activities.append(contentsOf: response.activities)
|
||||||
|
self.hasMore = response.hasMore
|
||||||
|
self.nextCursor = response.nextCursor
|
||||||
|
} catch {
|
||||||
|
self.errorMessage = error.localizedDescription
|
||||||
|
print("[watchOS] loadMoreActivities failed with error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoadingMore = false
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
//
|
||||||
|
// ComposePostViewModel.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class ComposePostViewModel: ObservableObject {
|
||||||
|
@Published var title = ""
|
||||||
|
@Published var content = ""
|
||||||
|
@Published var isPosting = false
|
||||||
|
@Published var errorMessage: String?
|
||||||
|
@Published var didPost = false
|
||||||
|
|
||||||
|
private let networkService = NetworkService()
|
||||||
|
|
||||||
|
func createPost(token: String, serverUrl: String) async {
|
||||||
|
guard !isPosting else { return }
|
||||||
|
isPosting = true
|
||||||
|
errorMessage = nil
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await networkService.createPost(title: title, content: content, token: token, serverUrl: serverUrl)
|
||||||
|
didPost = true
|
||||||
|
} catch {
|
||||||
|
errorMessage = error.localizedDescription
|
||||||
|
}
|
||||||
|
|
||||||
|
isPosting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
284
ios/WatchRunner Watch App/Views/AccountView.swift
Normal file
@@ -0,0 +1,284 @@
|
|||||||
|
//
|
||||||
|
// AccountView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct AccountView: View {
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@State private var user: SnAccount?
|
||||||
|
@State private var status: SnAccountStatus?
|
||||||
|
@State private var isLoading = false
|
||||||
|
@State private var error: Error?
|
||||||
|
@State private var showingClearConfirmation = false
|
||||||
|
|
||||||
|
@StateObject private var profileImageLoader = ImageLoader()
|
||||||
|
@StateObject private var bannerImageLoader = ImageLoader()
|
||||||
|
|
||||||
|
private let networkService = NetworkService()
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
if isLoading {
|
||||||
|
ProgressView()
|
||||||
|
.padding()
|
||||||
|
} else if let error = error {
|
||||||
|
VStack {
|
||||||
|
Text("Failed to load account")
|
||||||
|
.foregroundColor(.red)
|
||||||
|
Text(error.localizedDescription)
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
} else if let user = user {
|
||||||
|
VStack(spacing: 16) {
|
||||||
|
// Banner
|
||||||
|
if user.profile.background != nil {
|
||||||
|
if bannerImageLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
.frame(height: 80)
|
||||||
|
} else if let bannerImage = bannerImageLoader.image {
|
||||||
|
bannerImage
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fill)
|
||||||
|
.frame(height: 80)
|
||||||
|
.clipped()
|
||||||
|
.cornerRadius(8)
|
||||||
|
} else if bannerImageLoader.errorMessage != nil {
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color.gray.opacity(0.3))
|
||||||
|
.frame(height: 80)
|
||||||
|
.cornerRadius(8)
|
||||||
|
} else {
|
||||||
|
Rectangle()
|
||||||
|
.fill(Color.gray.opacity(0.3))
|
||||||
|
.frame(height: 80)
|
||||||
|
.cornerRadius(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Profile Picture
|
||||||
|
HStack(spacing: 16)
|
||||||
|
{
|
||||||
|
if profileImageLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
} else if let profileImage = profileImageLoader.image {
|
||||||
|
profileImage
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else if profileImageLoader.errorMessage != nil {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.red.opacity(0.3))
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
.overlay(
|
||||||
|
Image(systemName: "exclamationmark.triangle")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.foregroundColor(.red)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.gray.opacity(0.3))
|
||||||
|
.frame(width: 60, height: 60)
|
||||||
|
.overlay(
|
||||||
|
Image(systemName: "person.circle.fill")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Username and Handle
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text(user.nick)
|
||||||
|
.font(.headline)
|
||||||
|
Text("@\(user.name)")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Status
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
HStack {
|
||||||
|
Text("Status")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Spacer()
|
||||||
|
if status?.isCustomized == true {
|
||||||
|
Button(action: {
|
||||||
|
showingClearConfirmation = true
|
||||||
|
}) {
|
||||||
|
ZStack {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.red.opacity(0.1))
|
||||||
|
.frame(width: 28, height: 28)
|
||||||
|
Image(systemName: "trash")
|
||||||
|
.foregroundColor(.red)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.frame(width: 28, height: 28)
|
||||||
|
}
|
||||||
|
NavigationLink(
|
||||||
|
destination: StatusCreationView(initialStatus: status?.isCustomized == true ? status : nil)
|
||||||
|
.environmentObject(appState)
|
||||||
|
) {
|
||||||
|
ZStack {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.blue.opacity(0.1))
|
||||||
|
.frame(width: 28, height: 28)
|
||||||
|
Image(systemName: "pencil")
|
||||||
|
.foregroundColor(.blue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
.frame(width: 28, height: 28)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let status = status {
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
HStack {
|
||||||
|
Circle()
|
||||||
|
.fill(status.isOnline ? Color.green : Color.gray)
|
||||||
|
.frame(width: 8, height: 8)
|
||||||
|
Text(status.label.isEmpty ? "No status" : status.label)
|
||||||
|
.font(.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
if status.isInvisible {
|
||||||
|
Text("Invisible")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
if status.isNotDisturb {
|
||||||
|
Text("Do Not Disturb")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
if let clearedAt = status.clearedAt {
|
||||||
|
Text("Clears: \(clearedAt.formatted(date: .abbreviated, time: .shortened))")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text("No status set")
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Level and Progress
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text("Level \(user.profile.level)")
|
||||||
|
.font(.title3)
|
||||||
|
.bold()
|
||||||
|
ProgressView(value: user.profile.levelingProgress)
|
||||||
|
.progressViewStyle(LinearProgressViewStyle())
|
||||||
|
.frame(height: 8)
|
||||||
|
Text("Experience: \(user.profile.experience)")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Bio
|
||||||
|
if let bio = user.profile.bio, !bio.isEmpty {
|
||||||
|
Text(bio)
|
||||||
|
.font(.body)
|
||||||
|
.multilineTextAlignment(.center)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.frame(alignment: .leading)
|
||||||
|
} else {
|
||||||
|
Text("No bio available")
|
||||||
|
.font(.body)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.frame(alignment: .leading)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Member since
|
||||||
|
Text("Joined at \(user.createdAt.formatted(.dateTime.month(.abbreviated).year()))")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.frame(alignment: .leading)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
// Load images when user data is available
|
||||||
|
.task(id: user.profile.picture?.id) {
|
||||||
|
if let serverUrl = appState.serverUrl, let pictureId = user.profile.picture?.id, let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl), let token = appState.token {
|
||||||
|
await profileImageLoader.loadImage(from: imageUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task(id: user.profile.background?.id) {
|
||||||
|
if let serverUrl = appState.serverUrl, let backgroundId = user.profile.background?.id, let imageUrl = getAttachmentUrl(for: backgroundId, serverUrl: serverUrl), let token = appState.token {
|
||||||
|
await bannerImageLoader.loadImage(from: imageUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text("No account data")
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Account")
|
||||||
|
.confirmationDialog("Clear Status", isPresented: $showingClearConfirmation) {
|
||||||
|
Button("Clear Status", role: .destructive) {
|
||||||
|
Task {
|
||||||
|
await clearStatus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
Button("Cancel", role: .cancel) {}
|
||||||
|
} message: {
|
||||||
|
Text("Are you sure you want to clear your status? This action cannot be undone.")
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
Task.detached {
|
||||||
|
await loadUserProfile()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadUserProfile() async {
|
||||||
|
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||||
|
error = NSError(domain: "AccountView", code: 1, userInfo: [NSLocalizedDescriptionKey: "Authentication not available"])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = true
|
||||||
|
error = nil
|
||||||
|
|
||||||
|
do {
|
||||||
|
user = try await networkService.fetchUserProfile(token: token, serverUrl: serverUrl)
|
||||||
|
status = try await networkService.fetchAccountStatus(token: token, serverUrl: serverUrl)
|
||||||
|
} catch {
|
||||||
|
self.error = error
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func clearStatus() async {
|
||||||
|
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||||
|
error = NSError(domain: "AccountView", code: 1, userInfo: [NSLocalizedDescriptionKey: "Authentication not available"])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await networkService.clearStatus(token: token, serverUrl: serverUrl)
|
||||||
|
// Refresh status after clearing
|
||||||
|
status = try await networkService.fetchAccountStatus(token: token, serverUrl: serverUrl)
|
||||||
|
} catch {
|
||||||
|
self.error = error
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
AccountView()
|
||||||
|
.environmentObject(AppState())
|
||||||
|
}
|
||||||
86
ios/WatchRunner Watch App/Views/ActivityListView.swift
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
//
|
||||||
|
// ActivityListView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// MARK: - Views
|
||||||
|
|
||||||
|
struct ActivityListView: View {
|
||||||
|
@StateObject private var viewModel: ActivityViewModel
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
|
||||||
|
init(filter: String, mockActivities: [SnActivity]? = nil) {
|
||||||
|
_viewModel = StateObject(wrappedValue: ActivityViewModel(filter: filter, mockActivities: mockActivities))
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
if viewModel.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
} else if let errorMessage = viewModel.errorMessage {
|
||||||
|
VStack {
|
||||||
|
Text("Error fetching data")
|
||||||
|
.font(.headline)
|
||||||
|
Text(errorMessage)
|
||||||
|
.font(.caption)
|
||||||
|
.lineLimit(nil)
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
} else if viewModel.activities.isEmpty {
|
||||||
|
Text("No activities found.")
|
||||||
|
} else {
|
||||||
|
List {
|
||||||
|
ForEach(viewModel.activities) { activity in
|
||||||
|
switch activity.type {
|
||||||
|
case "posts.new", "posts.new.replies":
|
||||||
|
if case .post(let post) = activity.data {
|
||||||
|
NavigationLink(
|
||||||
|
destination: PostDetailView(post: post).environmentObject(appState)
|
||||||
|
) {
|
||||||
|
PostRowView(post: post)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
case "discovery":
|
||||||
|
if case .discovery(let discoveryData) = activity.data {
|
||||||
|
DiscoveryView(discoveryData: discoveryData)
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
Text("Unknown activity type: \(activity.type)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if viewModel.hasMore {
|
||||||
|
if viewModel.isLoadingMore {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
ProgressView()
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Button("Load More") {
|
||||||
|
Task {
|
||||||
|
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||||
|
await viewModel.loadMoreActivities(token: token, serverUrl: serverUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
if appState.isReady, let token = appState.token, let serverUrl = appState.serverUrl {
|
||||||
|
Task.detached {
|
||||||
|
await viewModel.fetchActivities(token: token, serverUrl: serverUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle(viewModel.filter)
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
}
|
||||||
109
ios/WatchRunner Watch App/Views/AttachmentView.swift
Normal file
@@ -0,0 +1,109 @@
|
|||||||
|
//
|
||||||
|
// AttachmentImageView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import AVKit
|
||||||
|
import AVFoundation
|
||||||
|
|
||||||
|
struct AttachmentView: View {
|
||||||
|
let attachment: SnCloudFile
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@StateObject private var imageLoader = ImageLoader()
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
if let mimeType = attachment.mimeType {
|
||||||
|
if mimeType.starts(with: "image") {
|
||||||
|
if let serverUrl = appState.serverUrl, let imageUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
|
||||||
|
NavigationLink(
|
||||||
|
destination: ImageViewer(imageUrl: imageUrl).environmentObject(appState)
|
||||||
|
) {
|
||||||
|
if imageLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
} else if let image = imageLoader.image {
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.cornerRadius(8)
|
||||||
|
} else if let errorMessage = imageLoader.errorMessage {
|
||||||
|
Text("Failed to load attachment: \(errorMessage)")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.red)
|
||||||
|
.cornerRadius(8)
|
||||||
|
} else {
|
||||||
|
Text("File: \(attachment.id)")
|
||||||
|
.cornerRadius(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
} else {
|
||||||
|
Text("Image URL not available.")
|
||||||
|
}
|
||||||
|
} else if mimeType.starts(with: "video") {
|
||||||
|
if let serverUrl = appState.serverUrl, let videoUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
|
||||||
|
NavigationLink(destination: VideoPlayerView(videoUrl: videoUrl)) {
|
||||||
|
if imageLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
} else if let image = imageLoader.image {
|
||||||
|
ZStack {
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.cornerRadius(8)
|
||||||
|
|
||||||
|
Image(systemName: "play.circle.fill")
|
||||||
|
.resizable()
|
||||||
|
.scaledToFit()
|
||||||
|
.frame(width: 36, height: 36)
|
||||||
|
.foregroundColor(.white)
|
||||||
|
.shadow(color: .black.opacity(0.6), radius: 4, x: 0, y: 2)
|
||||||
|
}
|
||||||
|
} else if imageLoader.errorMessage != nil {
|
||||||
|
Image(systemName: "play.rectangle.fill")
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
.cornerRadius(8)
|
||||||
|
} else {
|
||||||
|
ProgressView()
|
||||||
|
.cornerRadius(8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(PlainButtonStyle())
|
||||||
|
} else {
|
||||||
|
Text("Video URL not available.")
|
||||||
|
}
|
||||||
|
} else if mimeType.starts(with: "audio") {
|
||||||
|
if let serverUrl = appState.serverUrl, let audioUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl) {
|
||||||
|
AudioPlayerView(audioUrl: audioUrl)
|
||||||
|
} else {
|
||||||
|
Text("Cannot play audio: URL not available.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text("Unsupported media type: \(mimeType)")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Text("File: \(attachment.id) (No MIME type)")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task(id: attachment.id) {
|
||||||
|
if let serverUrl = appState.serverUrl, let attachmentUrl = getAttachmentUrl(for: attachment.id, serverUrl: serverUrl), let token = appState.token {
|
||||||
|
if attachment.mimeType?.starts(with: "image") == true {
|
||||||
|
await imageLoader.loadImage(from: attachmentUrl, token: token)
|
||||||
|
}
|
||||||
|
if attachment.mimeType?.starts(with: "video") == true {
|
||||||
|
let thumbnailUrl = attachmentUrl
|
||||||
|
.appending(queryItems: [URLQueryItem(name: "thumbnail", value: "true")]) // Construct thumbnail URL
|
||||||
|
await imageLoader.loadImage(from: thumbnailUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
47
ios/WatchRunner Watch App/Views/AudioPlayerView.swift
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
|
||||||
|
//
|
||||||
|
// AudioPlayerView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import AVFoundation
|
||||||
|
|
||||||
|
struct AudioPlayerView: View {
|
||||||
|
let audioUrl: URL
|
||||||
|
@State private var player: AVPlayer?
|
||||||
|
@State private var isPlaying: Bool = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
if player != nil {
|
||||||
|
Button(action: togglePlayPause) {
|
||||||
|
Image(systemName: isPlaying ? "pause.circle.fill" : "play.circle.fill")
|
||||||
|
.font(.largeTitle)
|
||||||
|
}
|
||||||
|
.buttonStyle(.plain)
|
||||||
|
} else {
|
||||||
|
Text("Loading audio...")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
player = AVPlayer(url: audioUrl)
|
||||||
|
}
|
||||||
|
.onDisappear {
|
||||||
|
player?.pause()
|
||||||
|
player = nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func togglePlayPause() {
|
||||||
|
guard let player = player else { return }
|
||||||
|
if isPlaying {
|
||||||
|
player.pause()
|
||||||
|
} else {
|
||||||
|
player.play()
|
||||||
|
}
|
||||||
|
isPlaying.toggle()
|
||||||
|
}
|
||||||
|
}
|
||||||
551
ios/WatchRunner Watch App/Views/ChatView.swift
Normal file
@@ -0,0 +1,551 @@
|
|||||||
|
//
|
||||||
|
// ChatView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ChatView: View {
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@State private var selectedTab = 0
|
||||||
|
@State private var chatRooms: [SnChatRoom] = []
|
||||||
|
@State private var chatInvites: [SnChatMember] = []
|
||||||
|
@State private var isLoading = false
|
||||||
|
@State private var error: Error?
|
||||||
|
@State private var showingInvites = false
|
||||||
|
|
||||||
|
private let tabs = ["All", "Direct", "Group"]
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
TabView(selection: $selectedTab) {
|
||||||
|
ForEach(0..<tabs.count, id: \.self) { index in
|
||||||
|
VStack {
|
||||||
|
if isLoading {
|
||||||
|
ProgressView()
|
||||||
|
} else if error != nil {
|
||||||
|
VStack {
|
||||||
|
Text("Error loading chats")
|
||||||
|
.font(.caption)
|
||||||
|
Button("Retry") {
|
||||||
|
Task {
|
||||||
|
await loadChatRooms()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.font(.caption2)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ChatRoomListView(
|
||||||
|
chatRooms: filteredChatRooms(for: index),
|
||||||
|
selectedTab: index
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tabItem {
|
||||||
|
Text(tabs[index])
|
||||||
|
}
|
||||||
|
.tag(index)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.tabViewStyle(.page)
|
||||||
|
.navigationTitle("Chat")
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .topBarTrailing) {
|
||||||
|
Button {
|
||||||
|
showingInvites = true
|
||||||
|
} label: {
|
||||||
|
ZStack {
|
||||||
|
Image(systemName: "envelope")
|
||||||
|
if !chatInvites.isEmpty {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.red)
|
||||||
|
.frame(width: 8, height: 8)
|
||||||
|
.offset(x: 8, y: -8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sheet(isPresented: $showingInvites) {
|
||||||
|
ChatInvitesView(invites: $chatInvites, appState: appState)
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
Task.detached {
|
||||||
|
await loadChatRooms()
|
||||||
|
await loadChatInvites()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func filteredChatRooms(for tabIndex: Int) -> [SnChatRoom] {
|
||||||
|
switch tabIndex {
|
||||||
|
case 0: // All
|
||||||
|
return chatRooms
|
||||||
|
case 1: // Direct
|
||||||
|
return chatRooms.filter { $0.type == 1 }
|
||||||
|
case 2: // Group
|
||||||
|
return chatRooms.filter { $0.type != 1 }
|
||||||
|
default:
|
||||||
|
return chatRooms
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadChatRooms() async {
|
||||||
|
guard let token = appState.token, let serverUrl = appState.serverUrl else { return }
|
||||||
|
|
||||||
|
isLoading = true
|
||||||
|
error = nil
|
||||||
|
|
||||||
|
do {
|
||||||
|
let response = try await appState.networkService.fetchChatRooms(token: token, serverUrl: serverUrl)
|
||||||
|
chatRooms = response.rooms
|
||||||
|
} catch {
|
||||||
|
self.error = error
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadChatInvites() async {
|
||||||
|
guard let token = appState.token, let serverUrl = appState.serverUrl else { return }
|
||||||
|
|
||||||
|
do {
|
||||||
|
let response = try await appState.networkService.fetchChatInvites(token: token, serverUrl: serverUrl)
|
||||||
|
chatInvites = response.invites
|
||||||
|
} catch {
|
||||||
|
// Handle error silently for invites
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatRoomListView: View {
|
||||||
|
let chatRooms: [SnChatRoom]
|
||||||
|
let selectedTab: Int
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
if chatRooms.isEmpty {
|
||||||
|
VStack {
|
||||||
|
Image(systemName: "message")
|
||||||
|
.font(.largeTitle)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Text("No chats yet")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List(chatRooms) { room in
|
||||||
|
ChatRoomListItem(room: room)
|
||||||
|
}
|
||||||
|
.listStyle(.plain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatRoomListItem: View {
|
||||||
|
let room: SnChatRoom
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@StateObject private var avatarLoader = ImageLoader()
|
||||||
|
|
||||||
|
private var displayName: String {
|
||||||
|
if room.type == 1, let members = room.members, !members.isEmpty {
|
||||||
|
// For direct messages, show the other member's name
|
||||||
|
return members[0].account.nick
|
||||||
|
} else {
|
||||||
|
// For group chats, show room name or fallback
|
||||||
|
return room.name ?? "Group Chat"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var subtitle: String {
|
||||||
|
if room.type == 1, let members = room.members, members.count > 1 {
|
||||||
|
// For direct messages, show member usernames
|
||||||
|
return members.map { "@\($0.account.name)" }.joined(separator: ", ")
|
||||||
|
} else if let description = room.description {
|
||||||
|
// For group chats with description
|
||||||
|
return description
|
||||||
|
} else {
|
||||||
|
// Fallback
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private var avatarPictureId: String? {
|
||||||
|
if room.type == 1, let members = room.members, !members.isEmpty {
|
||||||
|
// For direct messages, use the other member's avatar
|
||||||
|
return members[0].account.profile.picture?.id
|
||||||
|
} else {
|
||||||
|
// For group chats, use room picture
|
||||||
|
return room.picture?.id
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationLink(
|
||||||
|
destination: ChatRoomView(room: room)
|
||||||
|
.environmentObject(appState)
|
||||||
|
) {
|
||||||
|
HStack {
|
||||||
|
// Avatar using ImageLoader pattern
|
||||||
|
Group {
|
||||||
|
if avatarLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
} else if let image = avatarLoader.image {
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else if let errorMessage = avatarLoader.errorMessage {
|
||||||
|
// Error state - show fallback
|
||||||
|
Circle()
|
||||||
|
.fill(Color.gray.opacity(0.3))
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
.overlay(
|
||||||
|
Text(displayName.prefix(1).uppercased())
|
||||||
|
.font(.system(size: 12, weight: .medium))
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
// No image available - show initial
|
||||||
|
Circle()
|
||||||
|
.fill(Color.gray.opacity(0.3))
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
.overlay(
|
||||||
|
Text(displayName.prefix(1).uppercased())
|
||||||
|
.font(.system(size: 12, weight: .medium))
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task(id: avatarPictureId) {
|
||||||
|
if let serverUrl = appState.serverUrl,
|
||||||
|
let pictureId = avatarPictureId,
|
||||||
|
let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl),
|
||||||
|
let token = appState.token {
|
||||||
|
await avatarLoader.loadImage(from: imageUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
|
Text(displayName)
|
||||||
|
.font(.system(size: 14, weight: .medium))
|
||||||
|
.lineLimit(1)
|
||||||
|
|
||||||
|
if !subtitle.isEmpty {
|
||||||
|
Text(subtitle)
|
||||||
|
.font(.system(size: 12))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
.lineLimit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
|
||||||
|
// Unread count badge placeholder
|
||||||
|
// In a full implementation, this would show unread count
|
||||||
|
}
|
||||||
|
.padding(.vertical, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatRoomView: View {
|
||||||
|
let room: SnChatRoom
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@State private var messages: [SnChatMessage] = []
|
||||||
|
@State private var isLoading = false
|
||||||
|
@State private var error: Error?
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack {
|
||||||
|
if isLoading {
|
||||||
|
ProgressView()
|
||||||
|
} else if error != nil {
|
||||||
|
VStack {
|
||||||
|
Text("Error loading messages")
|
||||||
|
.font(.caption)
|
||||||
|
Button("Retry") {
|
||||||
|
Task {
|
||||||
|
await loadMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.font(.caption2)
|
||||||
|
}
|
||||||
|
} else if messages.isEmpty {
|
||||||
|
VStack {
|
||||||
|
Image(systemName: "bubble.left")
|
||||||
|
.font(.largeTitle)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Text("No messages yet")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
ScrollViewReader { scrollView in
|
||||||
|
ScrollView {
|
||||||
|
LazyVStack(alignment: .leading, spacing: 8) {
|
||||||
|
ForEach(messages) { message in
|
||||||
|
ChatMessageItem(message: message)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
// Scroll to bottom when messages load
|
||||||
|
if let lastMessage = messages.last {
|
||||||
|
scrollView.scrollTo(lastMessage.id, anchor: .bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: messages.count) { _ in
|
||||||
|
// Scroll to bottom when new messages arrive
|
||||||
|
if let lastMessage = messages.last {
|
||||||
|
withAnimation {
|
||||||
|
scrollView.scrollTo(lastMessage.id, anchor: .bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle(room.name ?? "Chat")
|
||||||
|
.task {
|
||||||
|
await loadMessages()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private func loadMessages() async {
|
||||||
|
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||||
|
isLoading = false
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
let messages = try await appState.networkService.fetchChatMessages(
|
||||||
|
chatRoomId: room.id,
|
||||||
|
token: token,
|
||||||
|
serverUrl: serverUrl
|
||||||
|
)
|
||||||
|
// Sort with newest messages first (for flipped list, newest will appear at bottom)
|
||||||
|
self.messages = messages.sorted { $0.createdAt < $1.createdAt }
|
||||||
|
} catch {
|
||||||
|
print("[watchOS] Error loading messages: \(error.localizedDescription)")
|
||||||
|
self.error = error
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatMessageItem: View {
|
||||||
|
let message: SnChatMessage
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@StateObject private var avatarLoader = ImageLoader()
|
||||||
|
|
||||||
|
private var avatarPictureId: String? {
|
||||||
|
message.sender.account.profile.picture?.id
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
HStack(alignment: .top, spacing: 8) {
|
||||||
|
// Avatar
|
||||||
|
Group {
|
||||||
|
if avatarLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
} else if let image = avatarLoader.image {
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.gray.opacity(0.3))
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
.overlay(
|
||||||
|
Text(message.sender.account.nick.prefix(1).uppercased())
|
||||||
|
.font(.system(size: 10, weight: .medium))
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task(id: avatarPictureId) {
|
||||||
|
if let serverUrl = appState.serverUrl,
|
||||||
|
let pictureId = avatarPictureId,
|
||||||
|
let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl),
|
||||||
|
let token = appState.token {
|
||||||
|
await avatarLoader.loadImage(from: imageUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
HStack {
|
||||||
|
Text(message.sender.account.nick)
|
||||||
|
.font(.system(size: 12, weight: .medium))
|
||||||
|
Spacer()
|
||||||
|
Text(message.createdAt, style: .time)
|
||||||
|
.font(.system(size: 10))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let content = message.content {
|
||||||
|
Text(content)
|
||||||
|
.font(.system(size: 14))
|
||||||
|
.lineLimit(nil)
|
||||||
|
.fixedSize(horizontal: false, vertical: true)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.vertical, 4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatInvitesView: View {
|
||||||
|
@Binding var invites: [SnChatMember]
|
||||||
|
let appState: AppState
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
@State private var isLoading = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationView {
|
||||||
|
VStack {
|
||||||
|
if invites.isEmpty {
|
||||||
|
VStack {
|
||||||
|
Image(systemName: "envelope.open")
|
||||||
|
.font(.largeTitle)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
Text("No invites")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
List(invites) { invite in
|
||||||
|
ChatInviteItem(invite: invite, appState: appState, invites: $invites)
|
||||||
|
}
|
||||||
|
.listStyle(.plain)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Invites")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ChatInviteItem: View {
|
||||||
|
let invite: SnChatMember
|
||||||
|
let appState: AppState
|
||||||
|
@Binding var invites: [SnChatMember]
|
||||||
|
@State private var isAccepting = false
|
||||||
|
@State private var isDeclining = false
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
HStack {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.gray.opacity(0.3))
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
.overlay(
|
||||||
|
Text((invite.chatRoom?.name ?? "C").prefix(1).uppercased())
|
||||||
|
.font(.system(size: 10, weight: .medium))
|
||||||
|
.foregroundColor(.primary)
|
||||||
|
)
|
||||||
|
|
||||||
|
VStack(alignment: .leading, spacing: 2) {
|
||||||
|
Text(invite.chatRoom?.name ?? "Unknown Chat")
|
||||||
|
.font(.system(size: 14, weight: .medium))
|
||||||
|
.lineLimit(1)
|
||||||
|
|
||||||
|
HStack(spacing: 4) {
|
||||||
|
Text(invite.role == 100 ? "Owner" : invite.role >= 50 ? "Moderator" : "Member")
|
||||||
|
.font(.system(size: 12))
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
|
if invite.chatRoom?.type == 1 {
|
||||||
|
Text("Direct")
|
||||||
|
.font(.system(size: 12))
|
||||||
|
.foregroundColor(.blue)
|
||||||
|
.padding(.horizontal, 4)
|
||||||
|
.padding(.vertical, 2)
|
||||||
|
.background(Color.blue.opacity(0.1))
|
||||||
|
.cornerRadius(4)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
Button {
|
||||||
|
Task {
|
||||||
|
await acceptInvite()
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
if isAccepting {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
} else {
|
||||||
|
Image(systemName: "checkmark")
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(isAccepting || isDeclining)
|
||||||
|
|
||||||
|
Button {
|
||||||
|
Task {
|
||||||
|
await declineInvite()
|
||||||
|
}
|
||||||
|
} label: {
|
||||||
|
if isDeclining {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
} else {
|
||||||
|
Image(systemName: "xmark")
|
||||||
|
.frame(width: 20, height: 20)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.disabled(isAccepting || isDeclining)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func acceptInvite() async {
|
||||||
|
guard let token = appState.token,
|
||||||
|
let serverUrl = appState.serverUrl,
|
||||||
|
let chatRoomId = invite.chatRoom?.id else { return }
|
||||||
|
|
||||||
|
isAccepting = true
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await appState.networkService.acceptChatInvite(chatRoomId: chatRoomId, token: token, serverUrl: serverUrl)
|
||||||
|
// Remove from invites list
|
||||||
|
invites.removeAll { $0.id == invite.id }
|
||||||
|
} catch {
|
||||||
|
// Handle error - could show alert
|
||||||
|
print("Failed to accept invite: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
isAccepting = false
|
||||||
|
}
|
||||||
|
|
||||||
|
private func declineInvite() async {
|
||||||
|
guard let token = appState.token,
|
||||||
|
let serverUrl = appState.serverUrl,
|
||||||
|
let chatRoomId = invite.chatRoom?.id else { return }
|
||||||
|
|
||||||
|
isDeclining = true
|
||||||
|
|
||||||
|
do {
|
||||||
|
try await appState.networkService.declineChatInvite(chatRoomId: chatRoomId, token: token, serverUrl: serverUrl)
|
||||||
|
// Remove from invites list
|
||||||
|
invites.removeAll { $0.id == invite.id }
|
||||||
|
} catch {
|
||||||
|
// Handle error - could show alert
|
||||||
|
print("Failed to decline invite: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
isDeclining = false
|
||||||
|
}
|
||||||
|
}
|
||||||
53
ios/WatchRunner Watch App/Views/ComposePostView.swift
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
//
|
||||||
|
// ComposePostView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ComposePostView: View {
|
||||||
|
@StateObject private var viewModel = ComposePostViewModel()
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.dismiss) private var dismiss
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationStack {
|
||||||
|
Form {
|
||||||
|
TextField("Title", text: $viewModel.title)
|
||||||
|
TextField("Content", text: $viewModel.content)
|
||||||
|
}
|
||||||
|
.navigationTitle("New Post")
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .cancellationAction) {
|
||||||
|
Button("Cancel", systemImage: "xmark") {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
.labelStyle(.iconOnly)
|
||||||
|
}
|
||||||
|
ToolbarItem(placement: .confirmationAction) {
|
||||||
|
Button("Post", systemImage: "square.and.arrow.up") {
|
||||||
|
Task {
|
||||||
|
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||||
|
await viewModel.createPost(token: token, serverUrl: serverUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.labelStyle(.iconOnly)
|
||||||
|
.disabled(viewModel.isPosting)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onChange(of: viewModel.didPost) {
|
||||||
|
if viewModel.didPost {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.alert("Error", isPresented: .constant(viewModel.errorMessage != nil), actions: {
|
||||||
|
Button("OK") { viewModel.errorMessage = nil }
|
||||||
|
}, message: {
|
||||||
|
Text(viewModel.errorMessage ?? "")
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
110
ios/WatchRunner Watch App/Views/DiscoveryViews.swift
Normal file
@@ -0,0 +1,110 @@
|
|||||||
|
//
|
||||||
|
// DiscoveryViews.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct DiscoveryView: View {
|
||||||
|
let discoveryData: DiscoveryData
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationLink(destination: DiscoveryDetailView(discoveryData: discoveryData)) {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
Text("Discovery")
|
||||||
|
.font(.headline)
|
||||||
|
Text("\(discoveryData.items.count) new items to discover")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct DiscoveryDetailView: View {
|
||||||
|
let discoveryData: DiscoveryData
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
List(discoveryData.items) { item in
|
||||||
|
NavigationLink(destination: destinationView(for: item)) {
|
||||||
|
itemView(for: item)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Discovery")
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func itemView(for item: DiscoveryItem) -> some View {
|
||||||
|
VStack(alignment: .leading) {
|
||||||
|
switch item.data {
|
||||||
|
case .realm(let realm):
|
||||||
|
Text("Realm").font(.headline)
|
||||||
|
Text(realm.name).foregroundColor(.secondary)
|
||||||
|
case .publisher(let publisher):
|
||||||
|
Text("Publisher").font(.headline)
|
||||||
|
Text(publisher.name).foregroundColor(.secondary)
|
||||||
|
case .article(let article):
|
||||||
|
Text("Article").font(.headline)
|
||||||
|
Text(article.title).foregroundColor(.secondary)
|
||||||
|
case .unknown:
|
||||||
|
Text("Unknown item")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@ViewBuilder
|
||||||
|
private func destinationView(for item: DiscoveryItem) -> some View {
|
||||||
|
switch item.data {
|
||||||
|
case .realm(let realm):
|
||||||
|
RealmDetailView(realm: realm)
|
||||||
|
case .publisher(let publisher):
|
||||||
|
PublisherDetailView(publisher: publisher)
|
||||||
|
case .article(let article):
|
||||||
|
ArticleDetailView(article: article)
|
||||||
|
case .unknown:
|
||||||
|
Text("Detail view not available")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct RealmDetailView: View {
|
||||||
|
let realm: SnRealm
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text(realm.name).font(.headline)
|
||||||
|
if let description = realm.description {
|
||||||
|
Text(description).font(.body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Realm")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PublisherDetailView: View {
|
||||||
|
let publisher: SnPublisher
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text(publisher.name).font(.headline)
|
||||||
|
if let description = publisher.description {
|
||||||
|
Text(description).font(.body)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Publisher")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct ArticleDetailView: View {
|
||||||
|
let article: SnWebArticle
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text(article.title).font(.headline)
|
||||||
|
Text(article.url).font(.caption).foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
.navigationTitle("Article")
|
||||||
|
}
|
||||||
|
}
|
||||||
62
ios/WatchRunner Watch App/Views/ExploreView.swift
Normal file
@@ -0,0 +1,62 @@
|
|||||||
|
//
|
||||||
|
// ExploreView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
// The main view with the TabView for filtering.
|
||||||
|
struct ExploreView: View {
|
||||||
|
@StateObject private var appState = AppState()
|
||||||
|
@State private var isComposing = false
|
||||||
|
@State private var selectedTab: String = "Explore"
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
NavigationStack {
|
||||||
|
if appState.isReady {
|
||||||
|
TabView(selection: $selectedTab) {
|
||||||
|
ActivityListView(filter: "Explore")
|
||||||
|
.tag("Explore")
|
||||||
|
.tabItem {
|
||||||
|
Label("Explore", systemImage: "safari")
|
||||||
|
}
|
||||||
|
.labelStyle(.titleOnly)
|
||||||
|
|
||||||
|
ActivityListView(filter: "Subscriptions")
|
||||||
|
.tag("Subscriptions")
|
||||||
|
.tabItem {
|
||||||
|
Label("Subscriptions", systemImage: "star")
|
||||||
|
}
|
||||||
|
.labelStyle(.titleOnly)
|
||||||
|
|
||||||
|
ActivityListView(filter: "Friends")
|
||||||
|
.tag("Friends")
|
||||||
|
.tabItem {
|
||||||
|
Label("Friends", systemImage: "person.2")
|
||||||
|
}
|
||||||
|
.labelStyle(.titleOnly)
|
||||||
|
}
|
||||||
|
.navigationTitle(selectedTab)
|
||||||
|
.toolbar {
|
||||||
|
ToolbarItem(placement: .primaryAction) {
|
||||||
|
Button(action: { isComposing = true }) {
|
||||||
|
Label("Compose", systemImage: "plus")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.environmentObject(appState)
|
||||||
|
} else {
|
||||||
|
ProgressView { Text("Connecting to phone...") }
|
||||||
|
.onAppear {
|
||||||
|
appState.requestData()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.sheet(isPresented: $isComposing) {
|
||||||
|
ComposePostView()
|
||||||
|
.environmentObject(appState)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
34
ios/WatchRunner Watch App/Views/ImageViewer.swift
Normal file
@@ -0,0 +1,34 @@
|
|||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct ImageViewer: View {
|
||||||
|
let imageUrl: URL
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@StateObject private var imageLoader = ImageLoader()
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
if imageLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
} else if let image = imageLoader.image {
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.aspectRatio(contentMode: .fit)
|
||||||
|
.frame(maxWidth: .infinity, maxHeight: .infinity)
|
||||||
|
.scaledToFit()
|
||||||
|
} else if let errorMessage = imageLoader.errorMessage {
|
||||||
|
Text("Failed to load image: \(errorMessage)")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.red)
|
||||||
|
} else {
|
||||||
|
Text("Failed to load image.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.task(id: imageUrl) {
|
||||||
|
if let token = appState.token {
|
||||||
|
await imageLoader.loadImage(from: imageUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Image")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
}
|
||||||
198
ios/WatchRunner Watch App/Views/NotificationView.swift
Normal file
@@ -0,0 +1,198 @@
|
|||||||
|
|
||||||
|
//
|
||||||
|
// NotificationView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
import Combine
|
||||||
|
|
||||||
|
@MainActor
|
||||||
|
class NotificationViewModel: ObservableObject {
|
||||||
|
@Published var notifications = [SnNotification]()
|
||||||
|
@Published var isLoading = false
|
||||||
|
@Published var isLoadingMore = false
|
||||||
|
@Published var errorMessage: String?
|
||||||
|
@Published var hasMore = false
|
||||||
|
|
||||||
|
private let networkService = NetworkService()
|
||||||
|
private var hasFetched = false
|
||||||
|
private var offset = 0
|
||||||
|
private let pageSize = 20
|
||||||
|
|
||||||
|
func fetchNotifications(token: String, serverUrl: String) async {
|
||||||
|
if hasFetched { return }
|
||||||
|
guard !isLoading else { return }
|
||||||
|
isLoading = true
|
||||||
|
errorMessage = nil
|
||||||
|
hasFetched = true
|
||||||
|
offset = 0
|
||||||
|
|
||||||
|
do {
|
||||||
|
let response = try await networkService.fetchNotifications(offset: offset, take: pageSize, token: token, serverUrl: serverUrl)
|
||||||
|
self.notifications = response.notifications
|
||||||
|
self.hasMore = response.hasMore
|
||||||
|
offset += response.notifications.count
|
||||||
|
} catch {
|
||||||
|
self.errorMessage = error.localizedDescription
|
||||||
|
print("[watchOS] fetchNotifications failed with error: \(error)")
|
||||||
|
hasFetched = false
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoading = false
|
||||||
|
}
|
||||||
|
|
||||||
|
func loadMoreNotifications(token: String, serverUrl: String) async {
|
||||||
|
guard !isLoadingMore && hasMore else { return }
|
||||||
|
isLoadingMore = true
|
||||||
|
|
||||||
|
do {
|
||||||
|
let response = try await networkService.fetchNotifications(offset: offset, take: pageSize, token: token, serverUrl: serverUrl)
|
||||||
|
self.notifications.append(contentsOf: response.notifications)
|
||||||
|
self.hasMore = response.hasMore
|
||||||
|
offset += response.notifications.count
|
||||||
|
} catch {
|
||||||
|
self.errorMessage = error.localizedDescription
|
||||||
|
print("[watchOS] loadMoreNotifications failed with error: \(error)")
|
||||||
|
}
|
||||||
|
|
||||||
|
isLoadingMore = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NotificationView: View {
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@StateObject private var viewModel = NotificationViewModel()
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
Group {
|
||||||
|
if viewModel.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
} else if let errorMessage = viewModel.errorMessage {
|
||||||
|
VStack {
|
||||||
|
Text("Error")
|
||||||
|
.font(.headline)
|
||||||
|
Text(errorMessage)
|
||||||
|
.font(.caption)
|
||||||
|
Button("Retry") {
|
||||||
|
Task {
|
||||||
|
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||||
|
await viewModel.fetchNotifications(token: token, serverUrl: serverUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
} else if viewModel.notifications.isEmpty {
|
||||||
|
Text("No notifications")
|
||||||
|
} else {
|
||||||
|
List {
|
||||||
|
ForEach(viewModel.notifications) { notification in
|
||||||
|
NavigationLink(destination: NotificationDetailView(notification: notification)) {
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
HStack {
|
||||||
|
Text(notification.title)
|
||||||
|
.font(.headline)
|
||||||
|
Spacer()
|
||||||
|
if notification.viewedAt == nil {
|
||||||
|
Circle()
|
||||||
|
.fill(Color.blue)
|
||||||
|
.frame(width: 8, height: 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !notification.subtitle.isEmpty {
|
||||||
|
Text(notification.subtitle)
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
if notification.content.count > 100 {
|
||||||
|
Text(notification.content.prefix(100) + "...")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
.lineLimit(2)
|
||||||
|
} else {
|
||||||
|
Text(notification.content)
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
.lineLimit(2)
|
||||||
|
}
|
||||||
|
Text(notification.createdAt, style: .relative)
|
||||||
|
.font(.caption2)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
}
|
||||||
|
.padding(.vertical, 8)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if viewModel.hasMore {
|
||||||
|
if viewModel.isLoadingMore {
|
||||||
|
HStack {
|
||||||
|
Spacer()
|
||||||
|
ProgressView()
|
||||||
|
Spacer()
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
Button("Load More") {
|
||||||
|
Task {
|
||||||
|
if let token = appState.token, let serverUrl = appState.serverUrl {
|
||||||
|
await viewModel.loadMoreNotifications(token: token, serverUrl: serverUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.frame(maxWidth: .infinity)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.onAppear {
|
||||||
|
if appState.isReady, let token = appState.token, let serverUrl = appState.serverUrl {
|
||||||
|
Task.detached {
|
||||||
|
await viewModel.fetchNotifications(token: token, serverUrl: serverUrl)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Notifications")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct NotificationDetailView: View {
|
||||||
|
let notification: SnNotification
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
VStack(alignment: .leading, spacing: 16) {
|
||||||
|
Text(notification.title)
|
||||||
|
.font(.headline)
|
||||||
|
|
||||||
|
if !notification.subtitle.isEmpty {
|
||||||
|
Text(notification.subtitle)
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
}
|
||||||
|
|
||||||
|
Text(notification.content)
|
||||||
|
.font(.body)
|
||||||
|
|
||||||
|
HStack {
|
||||||
|
Text(notification.createdAt, style: .date)
|
||||||
|
Text("·")
|
||||||
|
Text(notification.createdAt, style: .time)
|
||||||
|
}
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
|
||||||
|
if notification.viewedAt == nil {
|
||||||
|
Text("Unread")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.blue)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.navigationTitle("Notification")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
}
|
||||||
151
ios/WatchRunner Watch App/Views/PostViews.swift
Normal file
@@ -0,0 +1,151 @@
|
|||||||
|
//
|
||||||
|
// PostViews.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/29.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct PostRowView: View {
|
||||||
|
let post: SnPost
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@StateObject private var imageLoader = ImageLoader() // Instantiate ImageLoader
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VStack(alignment: .leading, spacing: 4) {
|
||||||
|
HStack {
|
||||||
|
if imageLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
} else if let image = imageLoader.image {
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else if let errorMessage = imageLoader.errorMessage {
|
||||||
|
Text("Failed: \(errorMessage)")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.red)
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
} else {
|
||||||
|
// Placeholder if no image and not loading
|
||||||
|
Image(systemName: "person.circle.fill")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 24, height: 24)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
}
|
||||||
|
Text(post.publisher.nick ?? post.publisher.name)
|
||||||
|
.font(.subheadline)
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
|
.task(id: post.publisher.picture?.id) { // Use task(id:) to reload image when pictureId changes
|
||||||
|
if let serverUrl = appState.serverUrl, let pictureId = post.publisher.picture?.id, let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl), let token = appState.token {
|
||||||
|
await imageLoader.loadImage(from: imageUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let title = post.title, !title.isEmpty {
|
||||||
|
Text(title)
|
||||||
|
.font(.headline)
|
||||||
|
}
|
||||||
|
|
||||||
|
if let content = post.content, !content.isEmpty {
|
||||||
|
Text(content)
|
||||||
|
.font(.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !post.attachments.isEmpty {
|
||||||
|
AttachmentView(attachment: post.attachments[0])
|
||||||
|
if post.attachments.count > 1 {
|
||||||
|
HStack(spacing: 8) {
|
||||||
|
Image(systemName: "paperclip.circle.fill")
|
||||||
|
.frame(width: 12, height: 12)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
Text("\(post.attachments.count - 1)+ attachments")
|
||||||
|
.font(.footnote)
|
||||||
|
.foregroundStyle(.gray)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}.padding(.vertical)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
struct PostDetailView: View {
|
||||||
|
let post: SnPost
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@StateObject private var publisherImageLoader = ImageLoader() // Instantiate ImageLoader for publisher avatar
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
HStack {
|
||||||
|
if publisherImageLoader.isLoading {
|
||||||
|
ProgressView()
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
} else if let image = publisherImageLoader.image {
|
||||||
|
image
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
.clipShape(Circle())
|
||||||
|
} else if let errorMessage = publisherImageLoader.errorMessage {
|
||||||
|
Text("Failed: \(errorMessage)")
|
||||||
|
.font(.caption)
|
||||||
|
.foregroundColor(.red)
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
} else {
|
||||||
|
Image(systemName: "person.circle.fill")
|
||||||
|
.resizable()
|
||||||
|
.frame(width: 32, height: 32)
|
||||||
|
.clipShape(Circle())
|
||||||
|
.foregroundColor(.gray)
|
||||||
|
}
|
||||||
|
Text("@\(post.publisher.name)")
|
||||||
|
.font(.headline)
|
||||||
|
}
|
||||||
|
// Use task(id:) to reload image when pictureId changes
|
||||||
|
.task(id: post.publisher.picture?.id) {
|
||||||
|
if let serverUrl = appState.serverUrl, let pictureId = post.publisher.picture?.id, let imageUrl = getAttachmentUrl(for: pictureId, serverUrl: serverUrl), let token = appState.token {
|
||||||
|
await publisherImageLoader.loadImage(from: imageUrl, token: token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if let title = post.title, !title.isEmpty {
|
||||||
|
Text(title)
|
||||||
|
.font(.title2)
|
||||||
|
.bold()
|
||||||
|
}
|
||||||
|
|
||||||
|
if let content = post.content, !content.isEmpty {
|
||||||
|
Text(content)
|
||||||
|
.font(.body)
|
||||||
|
}
|
||||||
|
|
||||||
|
if !post.attachments.isEmpty {
|
||||||
|
Text("Attachments").font(.headline)
|
||||||
|
ForEach(post.attachments) { attachment in
|
||||||
|
AttachmentView(attachment: attachment)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if !post.tags.isEmpty {
|
||||||
|
Text("Tags").font(.headline)
|
||||||
|
FlowLayout(alignment: .leading, spacing: 4) {
|
||||||
|
ForEach(post.tags) { tag in
|
||||||
|
Text("#\(tag.name ?? tag.slug)")
|
||||||
|
.font(.caption)
|
||||||
|
.padding(.horizontal, 8)
|
||||||
|
.padding(.vertical, 3)
|
||||||
|
.background(Capsule().fill(Color.accentColor.opacity(0.2)))
|
||||||
|
.cornerRadius(5)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.padding()
|
||||||
|
}
|
||||||
|
.navigationTitle("Post")
|
||||||
|
}
|
||||||
|
}
|
||||||
132
ios/WatchRunner Watch App/Views/StatusCreationView.swift
Normal file
@@ -0,0 +1,132 @@
|
|||||||
|
//
|
||||||
|
// StatusCreationView.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/30.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
struct StatusCreationView: View {
|
||||||
|
@EnvironmentObject var appState: AppState
|
||||||
|
@Environment(\.dismiss) var dismiss
|
||||||
|
|
||||||
|
let initialStatus: SnAccountStatus?
|
||||||
|
|
||||||
|
@State private var attitude: Int
|
||||||
|
@State private var isInvisible: Bool
|
||||||
|
@State private var isNotDisturb: Bool
|
||||||
|
@State private var label: String
|
||||||
|
@State private var isSubmitting: Bool = false
|
||||||
|
@State private var error: Error? = nil
|
||||||
|
|
||||||
|
private let networkService = NetworkService()
|
||||||
|
|
||||||
|
init(initialStatus: SnAccountStatus? = nil) {
|
||||||
|
self.initialStatus = initialStatus
|
||||||
|
_attitude = State(initialValue: initialStatus?.attitude ?? 1)
|
||||||
|
_isInvisible = State(initialValue: initialStatus?.isInvisible ?? false)
|
||||||
|
_isNotDisturb = State(initialValue: initialStatus?.isNotDisturb ?? false)
|
||||||
|
_label = State(initialValue: initialStatus?.label ?? "")
|
||||||
|
}
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
ScrollView {
|
||||||
|
VStack(spacing: 16) {
|
||||||
|
// Title
|
||||||
|
Text("Set Status")
|
||||||
|
.font(.headline)
|
||||||
|
.padding(.top)
|
||||||
|
|
||||||
|
// Label TextField
|
||||||
|
TextField("Status label", text: $label)
|
||||||
|
.textFieldStyle(.automatic)
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
// Attitude Picker
|
||||||
|
VStack(alignment: .leading, spacing: 8) {
|
||||||
|
Text("Mood")
|
||||||
|
.font(.subheadline)
|
||||||
|
.foregroundColor(.secondary)
|
||||||
|
|
||||||
|
Picker("Attitude", selection: $attitude) {
|
||||||
|
Text("😊 Positive").tag(0)
|
||||||
|
Text("😐 Neutral").tag(1)
|
||||||
|
Text("😢 Negative").tag(2)
|
||||||
|
}
|
||||||
|
.pickerStyle(.wheel)
|
||||||
|
.frame(height: 80)
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
// Toggles
|
||||||
|
VStack(spacing: 12) {
|
||||||
|
Toggle("Invisible", isOn: $isInvisible)
|
||||||
|
.padding(.horizontal)
|
||||||
|
|
||||||
|
Toggle("Do Not Disturb", isOn: $isNotDisturb)
|
||||||
|
.padding(.horizontal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Error message
|
||||||
|
if let error = error {
|
||||||
|
Text("Error: \(error.localizedDescription)")
|
||||||
|
.foregroundColor(.red)
|
||||||
|
.font(.caption)
|
||||||
|
.padding(.horizontal)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Buttons
|
||||||
|
HStack(spacing: 12) {
|
||||||
|
Button("Cancel") {
|
||||||
|
dismiss()
|
||||||
|
}
|
||||||
|
.buttonStyle(.glass)
|
||||||
|
|
||||||
|
Button(isSubmitting ? "Saving..." : "Save") {
|
||||||
|
Task {
|
||||||
|
await submitStatus()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.buttonStyle(.glassProminent)
|
||||||
|
.disabled(isSubmitting)
|
||||||
|
}
|
||||||
|
.padding(.horizontal)
|
||||||
|
.padding(.bottom)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.navigationTitle("Status")
|
||||||
|
.navigationBarTitleDisplayMode(.inline)
|
||||||
|
}
|
||||||
|
|
||||||
|
private func submitStatus() async {
|
||||||
|
guard let token = appState.token, let serverUrl = appState.serverUrl else {
|
||||||
|
error = NSError(domain: "StatusCreationView", code: 1, userInfo: [NSLocalizedDescriptionKey: "Authentication not available"])
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
isSubmitting = true
|
||||||
|
error = nil
|
||||||
|
|
||||||
|
do {
|
||||||
|
_ = try await networkService.createOrUpdateStatus(
|
||||||
|
attitude: attitude,
|
||||||
|
isInvisible: isInvisible,
|
||||||
|
isNotDisturb: isNotDisturb,
|
||||||
|
label: label.isEmpty ? nil : label,
|
||||||
|
token: token,
|
||||||
|
serverUrl: serverUrl
|
||||||
|
)
|
||||||
|
dismiss()
|
||||||
|
} catch {
|
||||||
|
self.error = error
|
||||||
|
}
|
||||||
|
|
||||||
|
isSubmitting = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#Preview {
|
||||||
|
StatusCreationView()
|
||||||
|
.environmentObject(AppState())
|
||||||
|
}
|
||||||
12
ios/WatchRunner Watch App/Views/VideoPlayerView.swift
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import SwiftUI
|
||||||
|
import AVKit
|
||||||
|
import AVFoundation
|
||||||
|
|
||||||
|
struct VideoPlayerView: View {
|
||||||
|
let videoUrl: URL
|
||||||
|
|
||||||
|
var body: some View {
|
||||||
|
VideoPlayer(player: AVPlayer(url: videoUrl))
|
||||||
|
.edgesIgnoringSafeArea(.all) // Make it full screen
|
||||||
|
}
|
||||||
|
}
|
||||||
17
ios/WatchRunner Watch App/WatchRunnerApp.swift
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
//
|
||||||
|
// WatchRunnerApp.swift
|
||||||
|
// WatchRunner Watch App
|
||||||
|
//
|
||||||
|
// Created by LittleSheep on 2025/10/28.
|
||||||
|
//
|
||||||
|
|
||||||
|
import SwiftUI
|
||||||
|
|
||||||
|
@main
|
||||||
|
struct WatchRunner_Watch_AppApp: App {
|
||||||
|
var body: some Scene {
|
||||||
|
WindowGroup {
|
||||||
|
ContentView()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.dart';
|
||||||
import 'package:drift/wasm.dart';
|
import 'package:drift/wasm.dart';
|
||||||
import 'package:island/database/drift_db.dart';
|
import 'package:island/database/drift_db.dart';
|
||||||
|
import 'package:island/talker.dart';
|
||||||
|
|
||||||
AppDatabase constructDb() {
|
AppDatabase constructDb() {
|
||||||
return AppDatabase(connectOnWeb());
|
return AppDatabase(connectOnWeb());
|
||||||
@@ -9,12 +10,17 @@ AppDatabase constructDb() {
|
|||||||
DatabaseConnection connectOnWeb() {
|
DatabaseConnection connectOnWeb() {
|
||||||
return DatabaseConnection.delayed(
|
return DatabaseConnection.delayed(
|
||||||
Future(() async {
|
Future(() async {
|
||||||
|
try {
|
||||||
final result = await WasmDatabase.open(
|
final result = await WasmDatabase.open(
|
||||||
databaseName: 'solar_network_data',
|
databaseName: 'solar_network_data',
|
||||||
sqlite3Uri: Uri.parse('sqlite3.wasm'),
|
sqlite3Uri: Uri.parse('sqlite3.wasm'),
|
||||||
driftWorkerUri: Uri.parse('drift_worker.dart.js'),
|
driftWorkerUri: Uri.parse('drift_worker.dart.js'),
|
||||||
);
|
);
|
||||||
return result.resolvedExecutor;
|
return result.resolvedExecutor;
|
||||||
|
} catch (e, stackTrace) {
|
||||||
|
talker.error('Failed to open WASM database...', e, stackTrace);
|
||||||
|
rethrow;
|
||||||
|
}
|
||||||
}),
|
}),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,8 +2,15 @@ import 'package:drift/drift.dart';
|
|||||||
|
|
||||||
class PostDrafts extends Table {
|
class PostDrafts extends Table {
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get post => text()(); // Store SnPost model as JSON string
|
// Searchable fields stored separately for performance
|
||||||
|
TextColumn get title => text().nullable()();
|
||||||
|
TextColumn get description => text().nullable()();
|
||||||
|
TextColumn get content => text().nullable()();
|
||||||
|
IntColumn get visibility => integer().withDefault(const Constant(0))();
|
||||||
|
IntColumn get type => integer().withDefault(const Constant(0))();
|
||||||
DateTimeColumn get lastModified => dateTime()();
|
DateTimeColumn get lastModified => dateTime()();
|
||||||
|
// Full post data stored as JSON for complete restoration
|
||||||
|
TextColumn get postData => text()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column> get primaryKey => {id};
|
Set<Column> get primaryKey => {id};
|
||||||
|
|||||||
@@ -12,7 +12,7 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
AppDatabase(super.e);
|
AppDatabase(super.e);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
int get schemaVersion => 4;
|
int get schemaVersion => 7;
|
||||||
|
|
||||||
@override
|
@override
|
||||||
MigrationStrategy get migration => MigrationStrategy(
|
MigrationStrategy get migration => MigrationStrategy(
|
||||||
@@ -21,16 +21,97 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
},
|
},
|
||||||
onUpgrade: (Migrator m, int from, int to) async {
|
onUpgrade: (Migrator m, int from, int to) async {
|
||||||
if (from < 2) {
|
if (from < 2) {
|
||||||
// Add isRead column with default value false
|
// Add isDeleted column with default value false
|
||||||
await m.addColumn(chatMessages, chatMessages.isRead);
|
await m.addColumn(chatMessages, chatMessages.isDeleted);
|
||||||
}
|
}
|
||||||
if (from < 4) {
|
if (from < 4) {
|
||||||
// Drop old draft tables if they exist
|
// Drop old draft tables if they exist
|
||||||
await m.createTable(postDrafts);
|
await m.createTable(postDrafts);
|
||||||
}
|
}
|
||||||
|
if (from < 6) {
|
||||||
|
// Migrate from old schema to new schema with separate searchable fields
|
||||||
|
await _migrateToVersion6(m);
|
||||||
|
}
|
||||||
|
if (from < 7) {
|
||||||
|
// Add new columns from SnChatMessage, ignore if they already exist
|
||||||
|
final columnsToAdd = [
|
||||||
|
chatMessages.updatedAt,
|
||||||
|
chatMessages.deletedAt,
|
||||||
|
chatMessages.type,
|
||||||
|
chatMessages.meta,
|
||||||
|
chatMessages.membersMentioned,
|
||||||
|
chatMessages.editedAt,
|
||||||
|
chatMessages.attachments,
|
||||||
|
chatMessages.reactions,
|
||||||
|
chatMessages.repliedMessageId,
|
||||||
|
chatMessages.forwardedMessageId,
|
||||||
|
];
|
||||||
|
|
||||||
|
for (final column in columnsToAdd) {
|
||||||
|
try {
|
||||||
|
await m.addColumn(chatMessages, column);
|
||||||
|
} catch (e) {
|
||||||
|
// Column already exists, skip
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Future<void> _migrateToVersion6(Migrator m) async {
|
||||||
|
// Rename existing table to old if it exists
|
||||||
|
try {
|
||||||
|
await customStatement(
|
||||||
|
'ALTER TABLE post_drafts RENAME TO post_drafts_old',
|
||||||
|
);
|
||||||
|
} catch (e) {
|
||||||
|
// Table might not exist
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop the table
|
||||||
|
await customStatement('DROP TABLE IF EXISTS post_drafts');
|
||||||
|
|
||||||
|
// Create new table
|
||||||
|
await m.createTable(postDrafts);
|
||||||
|
|
||||||
|
// Migrate existing data if any
|
||||||
|
try {
|
||||||
|
final oldDrafts =
|
||||||
|
await customSelect(
|
||||||
|
'SELECT id, post, lastModified FROM post_drafts_old',
|
||||||
|
readsFrom: {postDrafts},
|
||||||
|
).get();
|
||||||
|
|
||||||
|
for (final row in oldDrafts) {
|
||||||
|
final postJson = row.read<String>('post');
|
||||||
|
final id = row.read<String>('id');
|
||||||
|
final lastModified = row.read<DateTime>('lastModified');
|
||||||
|
|
||||||
|
if (postJson.isNotEmpty) {
|
||||||
|
final post = SnPost.fromJson(jsonDecode(postJson));
|
||||||
|
await into(postDrafts).insert(
|
||||||
|
PostDraftsCompanion(
|
||||||
|
id: Value(id),
|
||||||
|
title: Value(post.title),
|
||||||
|
description: Value(post.description),
|
||||||
|
content: Value(post.content),
|
||||||
|
visibility: Value(post.visibility),
|
||||||
|
type: Value(post.type),
|
||||||
|
lastModified: Value(lastModified),
|
||||||
|
postData: Value(postJson),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Drop old table
|
||||||
|
await customStatement('DROP TABLE IF EXISTS post_drafts_old');
|
||||||
|
} catch (e) {
|
||||||
|
// If migration fails, just recreate the table
|
||||||
|
await m.createTable(postDrafts);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Methods for chat messages
|
// Methods for chat messages
|
||||||
Future<List<ChatMessage>> getMessagesForRoom(
|
Future<List<ChatMessage>> getMessagesForRoom(
|
||||||
String roomId, {
|
String roomId, {
|
||||||
@@ -58,28 +139,70 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
)).write(ChatMessagesCompanion(status: Value(status)));
|
)).write(ChatMessagesCompanion(status: Value(status)));
|
||||||
}
|
}
|
||||||
|
|
||||||
Future<int> markMessageAsRead(String id) {
|
|
||||||
return (update(chatMessages)..where(
|
|
||||||
(m) => m.id.equals(id),
|
|
||||||
)).write(ChatMessagesCompanion(isRead: const Value(true)));
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<int> deleteMessage(String id) {
|
Future<int> deleteMessage(String id) {
|
||||||
return (delete(chatMessages)..where((m) => m.id.equals(id))).go();
|
return (delete(chatMessages)..where((m) => m.id.equals(id))).go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<int> getTotalMessagesForRoom(String roomId) {
|
||||||
|
return (select(
|
||||||
|
chatMessages,
|
||||||
|
)..where((m) => m.roomId.equals(roomId))).get().then((list) => list.length);
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<LocalChatMessage>> searchMessages(
|
||||||
|
String roomId,
|
||||||
|
String query, {
|
||||||
|
bool? withAttachments,
|
||||||
|
}) async {
|
||||||
|
var selectStatement = select(chatMessages)
|
||||||
|
..where((m) => m.roomId.equals(roomId));
|
||||||
|
|
||||||
|
if (query.isNotEmpty) {
|
||||||
|
final searchTerm = '%$query%';
|
||||||
|
selectStatement =
|
||||||
|
selectStatement..where(
|
||||||
|
(m) =>
|
||||||
|
m.content.like(searchTerm) |
|
||||||
|
m.meta.like(searchTerm) |
|
||||||
|
m.attachments.like(searchTerm) |
|
||||||
|
m.type.like(searchTerm),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (withAttachments == true) {
|
||||||
|
selectStatement =
|
||||||
|
selectStatement..where((m) => m.attachments.equals('[]').not());
|
||||||
|
}
|
||||||
|
|
||||||
|
final messages =
|
||||||
|
await (selectStatement
|
||||||
|
..orderBy([(m) => OrderingTerm.desc(m.createdAt)]))
|
||||||
|
.get();
|
||||||
|
return messages.map((msg) => companionToMessage(msg)).toList();
|
||||||
|
}
|
||||||
|
|
||||||
// Convert between Drift and model objects
|
// Convert between Drift and model objects
|
||||||
ChatMessagesCompanion messageToCompanion(LocalChatMessage message) {
|
ChatMessagesCompanion messageToCompanion(LocalChatMessage message) {
|
||||||
|
final remote = message.toRemoteMessage();
|
||||||
return ChatMessagesCompanion(
|
return ChatMessagesCompanion(
|
||||||
id: Value(message.id),
|
id: Value(message.id),
|
||||||
roomId: Value(message.roomId),
|
roomId: Value(message.roomId),
|
||||||
senderId: Value(message.senderId),
|
senderId: Value(message.senderId),
|
||||||
content: Value(message.toRemoteMessage().content),
|
content: Value(remote.content),
|
||||||
nonce: Value(message.nonce),
|
nonce: Value(message.nonce),
|
||||||
data: Value(jsonEncode(message.data)),
|
data: Value(jsonEncode(message.data)),
|
||||||
createdAt: Value(message.createdAt),
|
createdAt: Value(message.createdAt),
|
||||||
status: Value(message.status),
|
status: Value(message.status),
|
||||||
isRead: Value(message.isRead),
|
updatedAt: Value(remote.updatedAt),
|
||||||
|
deletedAt: Value(remote.deletedAt),
|
||||||
|
type: Value(remote.type),
|
||||||
|
meta: Value(remote.meta),
|
||||||
|
membersMentioned: Value(remote.membersMentioned),
|
||||||
|
editedAt: Value(remote.editedAt),
|
||||||
|
attachments: Value(remote.attachments.map((e) => e.toJson()).toList()),
|
||||||
|
reactions: Value(remote.reactions.map((e) => e.toJson()).toList()),
|
||||||
|
repliedMessageId: Value(remote.repliedMessageId),
|
||||||
|
forwardedMessageId: Value(remote.forwardedMessageId),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -93,7 +216,18 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
createdAt: dbMessage.createdAt,
|
createdAt: dbMessage.createdAt,
|
||||||
status: dbMessage.status,
|
status: dbMessage.status,
|
||||||
nonce: dbMessage.nonce,
|
nonce: dbMessage.nonce,
|
||||||
isRead: dbMessage.isRead,
|
content: dbMessage.content,
|
||||||
|
isDeleted: dbMessage.isDeleted,
|
||||||
|
updatedAt: dbMessage.updatedAt,
|
||||||
|
deletedAt: dbMessage.deletedAt,
|
||||||
|
type: dbMessage.type,
|
||||||
|
meta: dbMessage.meta,
|
||||||
|
membersMentioned: dbMessage.membersMentioned,
|
||||||
|
editedAt: dbMessage.editedAt,
|
||||||
|
attachments: dbMessage.attachments,
|
||||||
|
reactions: dbMessage.reactions,
|
||||||
|
repliedMessageId: dbMessage.repliedMessageId,
|
||||||
|
forwardedMessageId: dbMessage.forwardedMessageId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -101,10 +235,31 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
Future<List<SnPost>> getAllPostDrafts() async {
|
Future<List<SnPost>> getAllPostDrafts() async {
|
||||||
final drafts = await select(postDrafts).get();
|
final drafts = await select(postDrafts).get();
|
||||||
return drafts
|
return drafts
|
||||||
.map((draft) => SnPost.fromJson(jsonDecode(draft.post)))
|
.map((draft) => SnPost.fromJson(jsonDecode(draft.postData)))
|
||||||
.toList();
|
.toList();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<List<PostDraft>> getAllPostDraftRecords() async {
|
||||||
|
return await select(postDrafts).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<List<PostDraft>> searchPostDrafts(String query) async {
|
||||||
|
if (query.isEmpty) {
|
||||||
|
return await select(postDrafts).get();
|
||||||
|
}
|
||||||
|
|
||||||
|
final searchTerm = '%${query.toLowerCase()}%';
|
||||||
|
return await (select(postDrafts)
|
||||||
|
..where(
|
||||||
|
(draft) =>
|
||||||
|
draft.title.like(searchTerm) |
|
||||||
|
draft.description.like(searchTerm) |
|
||||||
|
draft.content.like(searchTerm),
|
||||||
|
)
|
||||||
|
..orderBy([(draft) => OrderingTerm.desc(draft.lastModified)]))
|
||||||
|
.get();
|
||||||
|
}
|
||||||
|
|
||||||
Future<void> addPostDraft(PostDraftsCompanion entry) async {
|
Future<void> addPostDraft(PostDraftsCompanion entry) async {
|
||||||
await into(postDrafts).insert(entry, mode: InsertMode.replace);
|
await into(postDrafts).insert(entry, mode: InsertMode.replace);
|
||||||
}
|
}
|
||||||
@@ -116,4 +271,9 @@ class AppDatabase extends _$AppDatabase {
|
|||||||
Future<void> clearAllPostDrafts() async {
|
Future<void> clearAllPostDrafts() async {
|
||||||
await delete(postDrafts).go();
|
await delete(postDrafts).go();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<PostDraft?> getPostDraftById(String id) async {
|
||||||
|
return await (select(postDrafts)
|
||||||
|
..where((tbl) => tbl.id.equals(id))).getSingleOrNull();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +1,41 @@
|
|||||||
|
import 'dart:convert';
|
||||||
|
|
||||||
import 'package:drift/drift.dart';
|
import 'package:drift/drift.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';
|
||||||
|
|
||||||
|
class MapConverter extends TypeConverter<Map<String, dynamic>, String> {
|
||||||
|
const MapConverter();
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> fromSql(String fromDb) => json.decode(fromDb);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toSql(Map<String, dynamic> value) => json.encode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListStringConverter extends TypeConverter<List<String>, String> {
|
||||||
|
const ListStringConverter();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<String> fromSql(String fromDb) => List<String>.from(json.decode(fromDb));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toSql(List<String> value) => json.encode(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
class ListMapConverter
|
||||||
|
extends TypeConverter<List<Map<String, dynamic>>, String> {
|
||||||
|
const ListMapConverter();
|
||||||
|
|
||||||
|
@override
|
||||||
|
List<Map<String, dynamic>> fromSql(String fromDb) =>
|
||||||
|
List<Map<String, dynamic>>.from(json.decode(fromDb));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toSql(List<Map<String, dynamic>> value) => json.encode(value);
|
||||||
|
}
|
||||||
|
|
||||||
class ChatMessages extends Table {
|
class ChatMessages extends Table {
|
||||||
TextColumn get id => text()();
|
TextColumn get id => text()();
|
||||||
TextColumn get roomId => text()();
|
TextColumn get roomId => text()();
|
||||||
@@ -11,7 +45,24 @@ class ChatMessages extends Table {
|
|||||||
TextColumn get data => text()();
|
TextColumn get data => text()();
|
||||||
DateTimeColumn get createdAt => dateTime()();
|
DateTimeColumn get createdAt => dateTime()();
|
||||||
IntColumn get status => intEnum<MessageStatus>()();
|
IntColumn get status => intEnum<MessageStatus>()();
|
||||||
BoolColumn get isRead => boolean().withDefault(const Constant(false))();
|
BoolColumn get isDeleted =>
|
||||||
|
boolean().nullable().withDefault(const Constant(false))();
|
||||||
|
DateTimeColumn get updatedAt => dateTime().nullable()();
|
||||||
|
DateTimeColumn get deletedAt => dateTime().nullable()();
|
||||||
|
TextColumn get type => text().withDefault(const Constant('text'))();
|
||||||
|
TextColumn get meta =>
|
||||||
|
text().map(const MapConverter()).withDefault(const Constant('{}'))();
|
||||||
|
TextColumn get membersMentioned =>
|
||||||
|
text()
|
||||||
|
.map(const ListStringConverter())
|
||||||
|
.withDefault(const Constant('[]'))();
|
||||||
|
DateTimeColumn get editedAt => dateTime().nullable()();
|
||||||
|
TextColumn get attachments =>
|
||||||
|
text().map(const ListMapConverter()).withDefault(const Constant('[]'))();
|
||||||
|
TextColumn get reactions =>
|
||||||
|
text().map(const ListMapConverter()).withDefault(const Constant('[]'))();
|
||||||
|
TextColumn get repliedMessageId => text().nullable()();
|
||||||
|
TextColumn get forwardedMessageId => text().nullable()();
|
||||||
|
|
||||||
@override
|
@override
|
||||||
Set<Column> get primaryKey => {id};
|
Set<Column> get primaryKey => {id};
|
||||||
@@ -25,8 +76,19 @@ class LocalChatMessage {
|
|||||||
final DateTime createdAt;
|
final DateTime createdAt;
|
||||||
MessageStatus status;
|
MessageStatus status;
|
||||||
final String? nonce;
|
final String? nonce;
|
||||||
|
final String? content;
|
||||||
|
final bool? isDeleted;
|
||||||
|
final DateTime? updatedAt;
|
||||||
|
final DateTime? deletedAt;
|
||||||
|
final String type;
|
||||||
|
final Map<String, dynamic> meta;
|
||||||
|
final List<String> membersMentioned;
|
||||||
|
final DateTime? editedAt;
|
||||||
|
final List<Map<String, dynamic>> attachments;
|
||||||
|
final List<Map<String, dynamic>> reactions;
|
||||||
|
final String? repliedMessageId;
|
||||||
|
final String? forwardedMessageId;
|
||||||
List<UniversalFile>? localAttachments;
|
List<UniversalFile>? localAttachments;
|
||||||
bool isRead;
|
|
||||||
|
|
||||||
LocalChatMessage({
|
LocalChatMessage({
|
||||||
required this.id,
|
required this.id,
|
||||||
@@ -36,8 +98,19 @@ class LocalChatMessage {
|
|||||||
required this.createdAt,
|
required this.createdAt,
|
||||||
required this.nonce,
|
required this.nonce,
|
||||||
required this.status,
|
required this.status,
|
||||||
|
this.content,
|
||||||
|
this.isDeleted,
|
||||||
|
this.updatedAt,
|
||||||
|
this.deletedAt,
|
||||||
|
required this.type,
|
||||||
|
required this.meta,
|
||||||
|
required this.membersMentioned,
|
||||||
|
this.editedAt,
|
||||||
|
required this.attachments,
|
||||||
|
required this.reactions,
|
||||||
|
this.repliedMessageId,
|
||||||
|
this.forwardedMessageId,
|
||||||
this.localAttachments,
|
this.localAttachments,
|
||||||
this.isRead = false,
|
|
||||||
});
|
});
|
||||||
|
|
||||||
SnChatMessage toRemoteMessage() {
|
SnChatMessage toRemoteMessage() {
|
||||||
@@ -48,7 +121,6 @@ class LocalChatMessage {
|
|||||||
SnChatMessage message,
|
SnChatMessage message,
|
||||||
MessageStatus status, {
|
MessageStatus status, {
|
||||||
String? nonce,
|
String? nonce,
|
||||||
bool isRead = false,
|
|
||||||
}) {
|
}) {
|
||||||
return LocalChatMessage(
|
return LocalChatMessage(
|
||||||
id: message.id,
|
id: message.id,
|
||||||
@@ -58,7 +130,18 @@ class LocalChatMessage {
|
|||||||
createdAt: message.createdAt,
|
createdAt: message.createdAt,
|
||||||
status: status,
|
status: status,
|
||||||
nonce: nonce ?? message.nonce,
|
nonce: nonce ?? message.nonce,
|
||||||
isRead: isRead,
|
content: message.content,
|
||||||
|
isDeleted: false,
|
||||||
|
updatedAt: message.updatedAt,
|
||||||
|
deletedAt: null,
|
||||||
|
type: message.type,
|
||||||
|
meta: message.meta,
|
||||||
|
membersMentioned: message.membersMentioned,
|
||||||
|
editedAt: message.editedAt,
|
||||||
|
attachments: message.attachments.map((e) => e.toJson()).toList(),
|
||||||
|
reactions: message.reactions.map((e) => e.toJson()).toList(),
|
||||||
|
repliedMessageId: message.repliedMessageId,
|
||||||
|
forwardedMessageId: message.forwardedMessageId,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,484 +0,0 @@
|
|||||||
import 'package:dio/dio.dart';
|
|
||||||
import 'package:island/database/drift_db.dart';
|
|
||||||
import 'package:island/database/message.dart';
|
|
||||||
import 'package:island/models/chat.dart';
|
|
||||||
import 'package:island/models/file.dart';
|
|
||||||
import 'package:island/services/file.dart';
|
|
||||||
import 'package:island/widgets/alert.dart';
|
|
||||||
import 'package:uuid/uuid.dart';
|
|
||||||
|
|
||||||
class MessageRepository {
|
|
||||||
final SnChatRoom room;
|
|
||||||
final SnChatMember identity;
|
|
||||||
final Dio _apiClient;
|
|
||||||
final AppDatabase _database;
|
|
||||||
|
|
||||||
final Map<String, LocalChatMessage> pendingMessages = {};
|
|
||||||
final Map<String, Map<int, double>> fileUploadProgress = {};
|
|
||||||
int? _totalCount;
|
|
||||||
|
|
||||||
MessageRepository(this.room, this.identity, this._apiClient, this._database);
|
|
||||||
|
|
||||||
Future<LocalChatMessage?> getLastMessages() async {
|
|
||||||
final dbMessages = await _database.getMessagesForRoom(
|
|
||||||
room.id,
|
|
||||||
offset: 0,
|
|
||||||
limit: 1,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (dbMessages.isEmpty) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return _database.companionToMessage(dbMessages.first);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<bool> syncMessages() async {
|
|
||||||
final lastMessage = await getLastMessages();
|
|
||||||
if (lastMessage == null) return false;
|
|
||||||
try {
|
|
||||||
final resp = await _apiClient.post(
|
|
||||||
'/sphere/chat/${room.id}/sync',
|
|
||||||
data: {
|
|
||||||
'last_sync_timestamp':
|
|
||||||
lastMessage.toRemoteMessage().updatedAt.millisecondsSinceEpoch,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
final response = MessageSyncResponse.fromJson(resp.data);
|
|
||||||
for (final change in response.changes) {
|
|
||||||
switch (change.action) {
|
|
||||||
case MessageChangeAction.create:
|
|
||||||
await receiveMessage(change.message!);
|
|
||||||
break;
|
|
||||||
case MessageChangeAction.update:
|
|
||||||
await receiveMessageUpdate(change.message!);
|
|
||||||
break;
|
|
||||||
case MessageChangeAction.delete:
|
|
||||||
await receiveMessageDeletion(change.messageId.toString());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} catch (err) {
|
|
||||||
showErrorAlert(err);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> listMessages({
|
|
||||||
int offset = 0,
|
|
||||||
int take = 20,
|
|
||||||
bool synced = false,
|
|
||||||
}) async {
|
|
||||||
try {
|
|
||||||
// For initial load, fetch latest messages in the background to sync.
|
|
||||||
if (offset == 0 && !synced) {
|
|
||||||
// Not awaiting this is intentional, for a quicker UI response.
|
|
||||||
// The UI should rely on a stream from the database to get updates.
|
|
||||||
_fetchAndCacheMessages(room.id, offset: 0, take: take).catchError((_) {
|
|
||||||
// Best effort, errors will be handled by later fetches.
|
|
||||||
return <LocalChatMessage>[];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
final localMessages = await _getCachedMessages(
|
|
||||||
room.id,
|
|
||||||
offset: offset,
|
|
||||||
take: take,
|
|
||||||
);
|
|
||||||
|
|
||||||
// If local cache has messages, return them. This is the common case for scrolling up.
|
|
||||||
if (localMessages.isNotEmpty) {
|
|
||||||
return localMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
// If local cache is empty, we've probably reached the end of cached history.
|
|
||||||
// Fetch from remote. This will also be hit on first load if cache is empty.
|
|
||||||
return await _fetchAndCacheMessages(room.id, offset: offset, take: take);
|
|
||||||
} catch (e) {
|
|
||||||
// Final fallback to cache in case of network errors during fetch.
|
|
||||||
final localMessages = await _getCachedMessages(
|
|
||||||
room.id,
|
|
||||||
offset: offset,
|
|
||||||
take: take,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (localMessages.isNotEmpty) {
|
|
||||||
return localMessages;
|
|
||||||
}
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> _getCachedMessages(
|
|
||||||
String roomId, {
|
|
||||||
int offset = 0,
|
|
||||||
int take = 20,
|
|
||||||
}) async {
|
|
||||||
// Get messages from local database
|
|
||||||
final dbMessages = await _database.getMessagesForRoom(
|
|
||||||
roomId,
|
|
||||||
offset: offset,
|
|
||||||
limit: take,
|
|
||||||
);
|
|
||||||
final dbLocalMessages =
|
|
||||||
dbMessages.map(_database.companionToMessage).toList();
|
|
||||||
|
|
||||||
// Combine with pending messages for the first page
|
|
||||||
if (offset == 0) {
|
|
||||||
final pendingForRoom =
|
|
||||||
pendingMessages.values.where((msg) => msg.roomId == roomId).toList();
|
|
||||||
|
|
||||||
final allMessages = [...pendingForRoom, ...dbLocalMessages];
|
|
||||||
allMessages.sort((a, b) => b.createdAt.compareTo(a.createdAt));
|
|
||||||
|
|
||||||
// Remove duplicates by ID, preserving the order
|
|
||||||
final uniqueMessages = <LocalChatMessage>[];
|
|
||||||
final seenIds = <String>{};
|
|
||||||
for (final message in allMessages) {
|
|
||||||
if (seenIds.add(message.id)) {
|
|
||||||
uniqueMessages.add(message);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return uniqueMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
return dbLocalMessages;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<List<LocalChatMessage>> _fetchAndCacheMessages(
|
|
||||||
String roomId, {
|
|
||||||
int offset = 0,
|
|
||||||
int take = 20,
|
|
||||||
}) async {
|
|
||||||
// Use cached total count if available, otherwise fetch it
|
|
||||||
if (_totalCount == null) {
|
|
||||||
final response = await _apiClient.get(
|
|
||||||
'/sphere/chat/$roomId/messages',
|
|
||||||
queryParameters: {'offset': 0, 'take': 1},
|
|
||||||
);
|
|
||||||
_totalCount = int.parse(response.headers['x-total']?.firstOrNull ?? '0');
|
|
||||||
}
|
|
||||||
|
|
||||||
if (offset >= _totalCount!) {
|
|
||||||
return [];
|
|
||||||
}
|
|
||||||
|
|
||||||
final response = await _apiClient.get(
|
|
||||||
'/sphere/chat/$roomId/messages',
|
|
||||||
queryParameters: {'offset': offset, 'take': take},
|
|
||||||
);
|
|
||||||
|
|
||||||
final List<dynamic> data = response.data;
|
|
||||||
// Update total count from response headers
|
|
||||||
_totalCount = int.parse(response.headers['x-total']?.firstOrNull ?? '0');
|
|
||||||
|
|
||||||
final messages =
|
|
||||||
data.map((json) {
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(json);
|
|
||||||
return LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
}).toList();
|
|
||||||
|
|
||||||
for (final message in messages) {
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(message));
|
|
||||||
if (message.nonce != null) {
|
|
||||||
pendingMessages.removeWhere(
|
|
||||||
(_, pendingMsg) => pendingMsg.nonce == message.nonce,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return messages;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> sendMessage(
|
|
||||||
String token,
|
|
||||||
String baseUrl,
|
|
||||||
String roomId,
|
|
||||||
String content,
|
|
||||||
String nonce, {
|
|
||||||
required List<UniversalFile> attachments,
|
|
||||||
Map<String, dynamic>? meta,
|
|
||||||
SnChatMessage? replyingTo,
|
|
||||||
SnChatMessage? forwardingTo,
|
|
||||||
SnChatMessage? editingTo,
|
|
||||||
Function(LocalChatMessage)? onPending,
|
|
||||||
Function(String, Map<int, double>)? onProgress,
|
|
||||||
}) async {
|
|
||||||
// Generate a unique nonce for this message
|
|
||||||
final nonce = const Uuid().v4();
|
|
||||||
|
|
||||||
// Create a local message with pending status
|
|
||||||
final mockMessage = SnChatMessage(
|
|
||||||
id: 'pending_$nonce',
|
|
||||||
chatRoomId: roomId,
|
|
||||||
senderId: identity.id,
|
|
||||||
content: content,
|
|
||||||
createdAt: DateTime.now(),
|
|
||||||
updatedAt: DateTime.now(),
|
|
||||||
nonce: nonce,
|
|
||||||
sender: identity,
|
|
||||||
);
|
|
||||||
|
|
||||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
mockMessage,
|
|
||||||
MessageStatus.pending,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Store in memory and database
|
|
||||||
pendingMessages[localMessage.id] = localMessage;
|
|
||||||
fileUploadProgress[localMessage.id] = {};
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(localMessage));
|
|
||||||
onPending?.call(localMessage);
|
|
||||||
|
|
||||||
try {
|
|
||||||
var cloudAttachments = List.empty(growable: true);
|
|
||||||
// Upload files
|
|
||||||
for (var idx = 0; idx < attachments.length; idx++) {
|
|
||||||
final cloudFile =
|
|
||||||
await putMediaToCloud(
|
|
||||||
fileData: attachments[idx],
|
|
||||||
atk: token,
|
|
||||||
baseUrl: baseUrl,
|
|
||||||
filename: attachments[idx].data.name ?? 'Post media',
|
|
||||||
mimetype:
|
|
||||||
attachments[idx].data.mimeType ??
|
|
||||||
switch (attachments[idx].type) {
|
|
||||||
UniversalFileType.image => 'image/unknown',
|
|
||||||
UniversalFileType.video => 'video/unknown',
|
|
||||||
UniversalFileType.audio => 'audio/unknown',
|
|
||||||
UniversalFileType.file => 'application/octet-stream',
|
|
||||||
},
|
|
||||||
onProgress: (progress, _) {
|
|
||||||
fileUploadProgress[localMessage.id]?[idx] = progress;
|
|
||||||
onProgress?.call(
|
|
||||||
localMessage.id,
|
|
||||||
fileUploadProgress[localMessage.id] ?? {},
|
|
||||||
);
|
|
||||||
},
|
|
||||||
).future;
|
|
||||||
if (cloudFile == null) {
|
|
||||||
throw ArgumentError('Failed to upload the file...');
|
|
||||||
}
|
|
||||||
cloudAttachments.add(cloudFile);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Send to server
|
|
||||||
final response = await _apiClient.request(
|
|
||||||
editingTo == null
|
|
||||||
? '/sphere/chat/$roomId/messages'
|
|
||||||
: '/sphere/chat/$roomId/messages/${editingTo.id}',
|
|
||||||
data: {
|
|
||||||
'content': content,
|
|
||||||
'attachments_id': cloudAttachments.map((e) => e.id).toList(),
|
|
||||||
'replied_message_id': replyingTo?.id,
|
|
||||||
'forwarded_message_id': forwardingTo?.id,
|
|
||||||
'meta': meta,
|
|
||||||
'nonce': nonce,
|
|
||||||
},
|
|
||||||
options: Options(method: editingTo == null ? 'POST' : 'PATCH'),
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update with server response
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove from pending and update in database
|
|
||||||
pendingMessages.remove(localMessage.id);
|
|
||||||
await _database.deleteMessage(localMessage.id);
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(updatedMessage));
|
|
||||||
|
|
||||||
return updatedMessage;
|
|
||||||
} catch (e) {
|
|
||||||
// Update status to failed
|
|
||||||
localMessage.status = MessageStatus.failed;
|
|
||||||
pendingMessages[localMessage.id] = localMessage;
|
|
||||||
await _database.updateMessageStatus(
|
|
||||||
localMessage.id,
|
|
||||||
MessageStatus.failed,
|
|
||||||
);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> retryMessage(String pendingMessageId) async {
|
|
||||||
final message = await getMessageById(pendingMessageId);
|
|
||||||
if (message == null) {
|
|
||||||
throw Exception('Message not found');
|
|
||||||
}
|
|
||||||
|
|
||||||
// Update status back to pending
|
|
||||||
message.status = MessageStatus.pending;
|
|
||||||
pendingMessages[pendingMessageId] = message;
|
|
||||||
await _database.updateMessageStatus(
|
|
||||||
pendingMessageId,
|
|
||||||
MessageStatus.pending,
|
|
||||||
);
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Send to server
|
|
||||||
var remoteMessage = message.toRemoteMessage();
|
|
||||||
final response = await _apiClient.post(
|
|
||||||
'/sphere/chat/${message.roomId}/messages',
|
|
||||||
data: {
|
|
||||||
'content': remoteMessage.content,
|
|
||||||
'attachments_id': remoteMessage.attachments,
|
|
||||||
'meta': remoteMessage.meta,
|
|
||||||
'nonce': message.nonce,
|
|
||||||
},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update with server response
|
|
||||||
remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Remove from pending and update in database
|
|
||||||
pendingMessages.remove(pendingMessageId);
|
|
||||||
await _database.deleteMessage(pendingMessageId);
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(updatedMessage));
|
|
||||||
|
|
||||||
return updatedMessage;
|
|
||||||
} catch (e) {
|
|
||||||
// Update status to failed
|
|
||||||
message.status = MessageStatus.failed;
|
|
||||||
pendingMessages[pendingMessageId] = message;
|
|
||||||
await _database.updateMessageStatus(
|
|
||||||
pendingMessageId,
|
|
||||||
MessageStatus.failed,
|
|
||||||
);
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> receiveMessage(SnChatMessage remoteMessage) async {
|
|
||||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
if (remoteMessage.nonce != null) {
|
|
||||||
pendingMessages.removeWhere(
|
|
||||||
(_, pendingMsg) => pendingMsg.nonce == remoteMessage.nonce,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(localMessage));
|
|
||||||
return localMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> receiveMessageUpdate(
|
|
||||||
SnChatMessage remoteMessage,
|
|
||||||
) async {
|
|
||||||
final localMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
await _database.updateMessage(_database.messageToCompanion(localMessage));
|
|
||||||
return localMessage;
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> receiveMessageDeletion(String messageId) async {
|
|
||||||
// Remove from pending messages if exists
|
|
||||||
pendingMessages.remove(messageId);
|
|
||||||
|
|
||||||
// Delete from local database
|
|
||||||
await _database.deleteMessage(messageId);
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage> updateMessage(
|
|
||||||
String messageId,
|
|
||||||
String content, {
|
|
||||||
List<SnCloudFile>? attachments,
|
|
||||||
Map<String, dynamic>? meta,
|
|
||||||
}) async {
|
|
||||||
final message = pendingMessages[messageId];
|
|
||||||
if (message != null) {
|
|
||||||
// Update pending message
|
|
||||||
final rmMessage = message.toRemoteMessage();
|
|
||||||
final updatedRemoteMessage = rmMessage.copyWith(
|
|
||||||
content: content,
|
|
||||||
meta: meta ?? rmMessage.meta,
|
|
||||||
);
|
|
||||||
final updatedLocalMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
updatedRemoteMessage,
|
|
||||||
MessageStatus.pending,
|
|
||||||
);
|
|
||||||
pendingMessages[messageId] = updatedLocalMessage;
|
|
||||||
await _database.updateMessage(
|
|
||||||
_database.messageToCompanion(updatedLocalMessage),
|
|
||||||
);
|
|
||||||
return message;
|
|
||||||
}
|
|
||||||
|
|
||||||
try {
|
|
||||||
// Update on server
|
|
||||||
final response = await _apiClient.put(
|
|
||||||
'/sphere/chat/${room.id}/messages/$messageId',
|
|
||||||
data: {'content': content, 'attachments': attachments, 'meta': meta},
|
|
||||||
);
|
|
||||||
|
|
||||||
// Update local copy
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final updatedMessage = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
await _database.updateMessage(
|
|
||||||
_database.messageToCompanion(updatedMessage),
|
|
||||||
);
|
|
||||||
return updatedMessage;
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<void> deleteMessage(String messageId) async {
|
|
||||||
try {
|
|
||||||
await _apiClient.delete('/sphere/chat/${room.id}/messages/$messageId');
|
|
||||||
pendingMessages.remove(messageId);
|
|
||||||
await _database.deleteMessage(messageId);
|
|
||||||
} catch (e) {
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Future<LocalChatMessage?> getMessageById(String messageId) async {
|
|
||||||
try {
|
|
||||||
// Attempt to get the message from the local database
|
|
||||||
final localMessage =
|
|
||||||
await (_database.select(_database.chatMessages)
|
|
||||||
..where((tbl) => tbl.id.equals(messageId))).getSingleOrNull();
|
|
||||||
if (localMessage != null) {
|
|
||||||
return _database.companionToMessage(localMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
// If not found locally, fetch from the server
|
|
||||||
final response = await _apiClient.get(
|
|
||||||
'/sphere/chat/${room.id}/messages/$messageId',
|
|
||||||
);
|
|
||||||
final remoteMessage = SnChatMessage.fromJson(response.data);
|
|
||||||
final message = LocalChatMessage.fromRemoteMessage(
|
|
||||||
remoteMessage,
|
|
||||||
MessageStatus.sent,
|
|
||||||
);
|
|
||||||
|
|
||||||
// Save the fetched message to the local database
|
|
||||||
await _database.saveMessage(_database.messageToCompanion(message));
|
|
||||||
return message;
|
|
||||||
} catch (e) {
|
|
||||||
if (e is DioException) return null;
|
|
||||||
// Handle errors
|
|
||||||
rethrow;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
150
lib/main.dart
@@ -1,6 +1,4 @@
|
|||||||
import 'dart:developer';
|
|
||||||
import 'dart:io';
|
import 'dart:io';
|
||||||
|
|
||||||
import 'package:croppy/croppy.dart';
|
import 'package:croppy/croppy.dart';
|
||||||
import 'package:easy_localization/easy_localization.dart' hide TextDirection;
|
import 'package:easy_localization/easy_localization.dart' hide TextDirection;
|
||||||
import 'package:firebase_core/firebase_core.dart';
|
import 'package:firebase_core/firebase_core.dart';
|
||||||
@@ -8,16 +6,15 @@ import 'package:firebase_crashlytics/firebase_crashlytics.dart';
|
|||||||
import 'package:firebase_messaging/firebase_messaging.dart';
|
import 'package:firebase_messaging/firebase_messaging.dart';
|
||||||
import 'package:flutter/foundation.dart';
|
import 'package:flutter/foundation.dart';
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter/services.dart';
|
|
||||||
import 'package:flutter_hooks/flutter_hooks.dart';
|
import 'package:flutter_hooks/flutter_hooks.dart';
|
||||||
import 'package:go_router/go_router.dart';
|
import 'package:go_router/go_router.dart';
|
||||||
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
import 'package:hooks_riverpod/hooks_riverpod.dart';
|
||||||
import 'package:image_picker_android/image_picker_android.dart';
|
import 'package:image_picker_android/image_picker_android.dart';
|
||||||
|
import 'package:island/talker.dart';
|
||||||
import 'package:island/firebase_options.dart';
|
import 'package:island/firebase_options.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/theme.dart';
|
import 'package:island/pods/theme.dart';
|
||||||
import 'package:bitsdojo_window/bitsdojo_window.dart';
|
|
||||||
import 'package:island/pods/userinfo.dart';
|
import 'package:island/pods/userinfo.dart';
|
||||||
import 'package:island/pods/websocket.dart';
|
import 'package:island/pods/websocket.dart';
|
||||||
import 'package:island/route.dart';
|
import 'package:island/route.dart';
|
||||||
@@ -29,19 +26,21 @@ import 'package:relative_time/relative_time.dart';
|
|||||||
import 'package:shared_preferences/shared_preferences.dart';
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
import 'package:image_picker_platform_interface/image_picker_platform_interface.dart';
|
||||||
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
import 'package:flutter_native_splash/flutter_native_splash.dart';
|
||||||
|
import 'package:talker_flutter/talker_flutter.dart';
|
||||||
|
import 'package:talker_riverpod_logger/talker_riverpod_logger.dart';
|
||||||
import 'package:url_launcher/url_launcher_string.dart';
|
import 'package:url_launcher/url_launcher_string.dart';
|
||||||
import 'package:flutter_langdetect/flutter_langdetect.dart' as langdetect;
|
import 'package:window_manager/window_manager.dart';
|
||||||
|
|
||||||
@pragma('vm:entry-point')
|
@pragma('vm:entry-point')
|
||||||
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
Future<void> _firebaseMessagingBackgroundHandler(RemoteMessage message) async {
|
||||||
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
await Firebase.initializeApp(options: DefaultFirebaseOptions.currentPlatform);
|
||||||
log('Handling a background message: ${message.messageId}');
|
talker.info('Handling a background message: ${message.messageId}');
|
||||||
}
|
}
|
||||||
|
|
||||||
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(
|
talker.info(
|
||||||
"[SplashScreen] Keeping the flash screen to loading other resources...",
|
"[SplashScreen] Keeping the flash screen to loading other resources...",
|
||||||
);
|
);
|
||||||
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
FlutterNativeSplash.preserve(widgetsBinding: widgetsBinding);
|
||||||
@@ -52,7 +51,6 @@ void main() async {
|
|||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
await langdetect.initLangDetect();
|
|
||||||
await EasyLocalization.ensureInitialized();
|
await EasyLocalization.ensureInitialized();
|
||||||
|
|
||||||
if (kIsWeb || !Platform.isLinux) {
|
if (kIsWeb || !Platform.isLinux) {
|
||||||
@@ -75,23 +73,24 @@ void main() async {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
log("[SplashScreen] Firebase is ready!");
|
talker.info("[SplashScreen] Firebase is ready!");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
showErrorAlert(err);
|
showErrorAlert(err);
|
||||||
}
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
log("[SplashScreen] Loading timezone database...");
|
talker.info("[SplashScreen] Loading timezone database...");
|
||||||
await initializeTzdb();
|
await initializeTzdb();
|
||||||
log("[SplashScreen] Time zone database was loaded!");
|
talker.info("[SplashScreen] Time zone database was loaded!");
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
log("[SplashScreen] Failed to load timezone database... $err");
|
talker.error("[SplashScreen] Failed to load timezone database... $err");
|
||||||
}
|
}
|
||||||
|
|
||||||
final prefs = await SharedPreferences.getInstance();
|
final prefs = await SharedPreferences.getInstance();
|
||||||
|
|
||||||
if (!kIsWeb && (Platform.isMacOS || Platform.isLinux || Platform.isWindows)) {
|
if (!kIsWeb && (Platform.isMacOS || Platform.isLinux || Platform.isWindows)) {
|
||||||
doWhenWindowReady(() {
|
await windowManager.ensureInitialized();
|
||||||
|
|
||||||
const defaultSize = Size(360, 640);
|
const defaultSize = Size(360, 640);
|
||||||
|
|
||||||
// Get saved window size from preferences
|
// Get saved window size from preferences
|
||||||
@@ -107,17 +106,38 @@ void main() async {
|
|||||||
initialSize = Size(width, height);
|
initialSize = Size(width, height);
|
||||||
}
|
}
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log("[SplashScreen] Failed to parse saved window size: $e");
|
talker.error("[SplashScreen] Failed to parse saved window size: $e");
|
||||||
initialSize = defaultSize;
|
initialSize = defaultSize;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
appWindow.minSize = defaultSize;
|
WindowOptions windowOptions = WindowOptions(
|
||||||
appWindow.size = initialSize;
|
size: initialSize,
|
||||||
appWindow.alignment = Alignment.center;
|
center: true,
|
||||||
appWindow.show();
|
backgroundColor: Colors.transparent,
|
||||||
log(
|
skipTaskbar: false,
|
||||||
"[SplashScreen] Desktop window is ready with size: ${initialSize.width}x${initialSize.height}",
|
titleBarStyle: TitleBarStyle.hidden,
|
||||||
|
windowButtonVisibility: true,
|
||||||
|
);
|
||||||
|
windowManager.waitUntilReadyToShow(windowOptions, () async {
|
||||||
|
final env = Platform.environment;
|
||||||
|
final isWayland = env.containsKey('WAYLAND_DISPLAY');
|
||||||
|
|
||||||
|
if (isWayland) {
|
||||||
|
try {
|
||||||
|
await windowManager.setAsFrameless();
|
||||||
|
} catch (e) {
|
||||||
|
debugPrint('[Wayland] setAsFrameless failed: $e');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await windowManager.setMinimumSize(defaultSize);
|
||||||
|
await windowManager.show();
|
||||||
|
await windowManager.focus();
|
||||||
|
final opacity = prefs.getDouble(kAppWindowOpacity) ?? 1.0;
|
||||||
|
await windowManager.setOpacity(opacity);
|
||||||
|
talker.info(
|
||||||
|
"[SplashScreen] Desktop window is ready with size: ${initialSize.width}x${initialSize.height}"
|
||||||
|
"${isWayland ? " (Wayland frameless fix applied)" : ""}",
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -128,16 +148,27 @@ void main() async {
|
|||||||
if (imagePickerImplementation is ImagePickerAndroid) {
|
if (imagePickerImplementation is ImagePickerAndroid) {
|
||||||
imagePickerImplementation.useAndroidPhotoPicker = true;
|
imagePickerImplementation.useAndroidPhotoPicker = true;
|
||||||
}
|
}
|
||||||
log("[SplashScreen] Android image picker is ready!");
|
talker.info("[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...");
|
talker.info("[SplashScreen] Now hiding the splash screen...");
|
||||||
}
|
}
|
||||||
|
|
||||||
runApp(
|
runApp(
|
||||||
ProviderScope(
|
ProviderScope(
|
||||||
|
observers: [
|
||||||
|
TalkerRiverpodObserver(
|
||||||
|
talker: talker,
|
||||||
|
settings: TalkerRiverpodLoggerSettings(
|
||||||
|
printProviderAdded: false,
|
||||||
|
printProviderDisposed: false,
|
||||||
|
printProviderUpdated: false,
|
||||||
|
printStateFullData: false,
|
||||||
|
),
|
||||||
|
),
|
||||||
|
],
|
||||||
overrides: [sharedPreferencesProvider.overrideWithValue(prefs)],
|
overrides: [sharedPreferencesProvider.overrideWithValue(prefs)],
|
||||||
child: Directionality(
|
child: Directionality(
|
||||||
textDirection: TextDirection.ltr,
|
textDirection: TextDirection.ltr,
|
||||||
@@ -146,6 +177,10 @@ void main() async {
|
|||||||
Locale('en', 'US'),
|
Locale('en', 'US'),
|
||||||
Locale('zh', 'CN'),
|
Locale('zh', 'CN'),
|
||||||
Locale('zh', 'TW'),
|
Locale('zh', 'TW'),
|
||||||
|
Locale('zh', 'OG'),
|
||||||
|
Locale('ja', 'JP'),
|
||||||
|
Locale('ko', 'KR'),
|
||||||
|
Locale('es', 'ES'),
|
||||||
],
|
],
|
||||||
path: 'assets/i18n',
|
path: 'assets/i18n',
|
||||||
fallbackLocale: Locale('en', 'US'),
|
fallbackLocale: Locale('en', 'US'),
|
||||||
@@ -167,14 +202,29 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
@override
|
@override
|
||||||
Widget build(BuildContext context, WidgetRef ref) {
|
Widget build(BuildContext context, WidgetRef ref) {
|
||||||
final theme = ref.watch(themeProvider);
|
final theme = ref.watch(themeProvider);
|
||||||
|
final settings = ref.watch(appSettingsNotifierProvider);
|
||||||
|
|
||||||
|
// Convert string theme mode to ThemeMode enum
|
||||||
|
ThemeMode getThemeMode() {
|
||||||
|
final themeMode = settings.themeMode ?? 'system';
|
||||||
|
switch (themeMode) {
|
||||||
|
case 'light':
|
||||||
|
return ThemeMode.light;
|
||||||
|
case 'dark':
|
||||||
|
return ThemeMode.dark;
|
||||||
|
case 'system':
|
||||||
|
default:
|
||||||
|
return ThemeMode.system;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void handleMessage(RemoteMessage notification) {
|
void handleMessage(RemoteMessage notification) {
|
||||||
if (notification.data['action_uri'] != null) {
|
if (notification.data['meta']?['action_uri'] != null) {
|
||||||
var uri = notification.data['action_uri'] as String;
|
var uri = notification.data['meta']['action_uri'] as String;
|
||||||
if (uri.startsWith('/')) {
|
if (uri.startsWith('/')) {
|
||||||
// In-app routes
|
// In-app routes
|
||||||
final router = ref.read(routerProvider);
|
final router = ref.read(routerProvider);
|
||||||
router.go(notification.data['action_uri']);
|
router.push(notification.data['meta']['action_uri']);
|
||||||
} else {
|
} else {
|
||||||
// External links
|
// External links
|
||||||
launchUrlString(uri);
|
launchUrlString(uri);
|
||||||
@@ -183,30 +233,9 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
}
|
}
|
||||||
|
|
||||||
useEffect(() {
|
useEffect(() {
|
||||||
if (!kIsWeb && Platform.isLinux) {
|
if (!kIsWeb && (Platform.isLinux || Platform.isWindows)) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
const channel = MethodChannel('dev.solsynth.solian/notifications');
|
|
||||||
|
|
||||||
Future<void> handleInitialLink() async {
|
|
||||||
final String? link = await channel.invokeMethod('initialLink');
|
|
||||||
if (link != null) {
|
|
||||||
final router = ref.read(routerProvider);
|
|
||||||
router.go(link);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!kIsWeb && Platform.isAndroid) {
|
|
||||||
handleInitialLink();
|
|
||||||
}
|
|
||||||
|
|
||||||
channel.setMethodCallHandler((call) async {
|
|
||||||
if (call.method == 'newLink') {
|
|
||||||
final String link = call.arguments;
|
|
||||||
final router = ref.read(routerProvider);
|
|
||||||
router.go(link);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
// When the app is opened from a terminated state.
|
// When the app is opened from a terminated state.
|
||||||
FirebaseMessaging.instance.getInitialMessage().then((message) {
|
FirebaseMessaging.instance.getInitialMessage().then((message) {
|
||||||
@@ -224,7 +253,9 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
final onMessageSubscription = FirebaseMessaging.onMessage.listen((
|
final onMessageSubscription = FirebaseMessaging.onMessage.listen((
|
||||||
message,
|
message,
|
||||||
) {
|
) {
|
||||||
log('Foreground message received: ${message.messageId}');
|
talker.info(
|
||||||
|
'[Notification] foreground message received: ${message.messageId}',
|
||||||
|
);
|
||||||
handleMessage(message);
|
handleMessage(message);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -238,7 +269,7 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
// Load userinfo
|
// Load userinfo
|
||||||
final userNotifier = ref.read(userInfoProvider.notifier);
|
final userNotifier = ref.read(userInfoProvider.notifier);
|
||||||
ref.listen(websocketStateProvider, (_, state) {
|
ref.listen(websocketStateProvider, (_, state) {
|
||||||
log('[WebSocket] $state');
|
talker.info('[WebSocket] $state');
|
||||||
});
|
});
|
||||||
Future(() {
|
Future(() {
|
||||||
userNotifier.fetchUser().then((_) {
|
userNotifier.fetchUser().then((_) {
|
||||||
@@ -246,6 +277,7 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
if (user.value != null) {
|
if (user.value != null) {
|
||||||
final apiClient = ref.read(apiClientProvider);
|
final apiClient = ref.read(apiClientProvider);
|
||||||
subscribePushNotification(apiClient);
|
subscribePushNotification(apiClient);
|
||||||
|
initializeLocalNotifications();
|
||||||
final wsNotifier = ref.read(websocketStateProvider.notifier);
|
final wsNotifier = ref.read(websocketStateProvider.notifier);
|
||||||
wsNotifier.connect();
|
wsNotifier.connect();
|
||||||
}
|
}
|
||||||
@@ -257,11 +289,13 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
final router = ref.watch(routerProvider);
|
final router = ref.watch(routerProvider);
|
||||||
|
|
||||||
return MaterialApp.router(
|
return MaterialApp.router(
|
||||||
theme: theme?.light,
|
color: Colors.transparent,
|
||||||
darkTheme: theme?.dark,
|
theme: theme.light,
|
||||||
themeMode: ThemeMode.system,
|
darkTheme: theme.dark,
|
||||||
|
themeMode: getThemeMode(),
|
||||||
routerConfig: router,
|
routerConfig: router,
|
||||||
supportedLocales: context.supportedLocales,
|
supportedLocales: context.supportedLocales,
|
||||||
|
scrollBehavior: AppScrollBehavior(),
|
||||||
localizationsDelegates: [
|
localizationsDelegates: [
|
||||||
...context.localizationDelegates,
|
...context.localizationDelegates,
|
||||||
CroppyLocalizations.delegate,
|
CroppyLocalizations.delegate,
|
||||||
@@ -273,9 +307,15 @@ class IslandApp extends HookConsumerWidget {
|
|||||||
key: globalOverlay,
|
key: globalOverlay,
|
||||||
initialEntries: [
|
initialEntries: [
|
||||||
OverlayEntry(
|
OverlayEntry(
|
||||||
builder:
|
builder: (_) {
|
||||||
(_) =>
|
return TalkerWrapper(
|
||||||
WindowScaffold(child: child ?? const SizedBox.shrink()),
|
talker: talker,
|
||||||
|
options: const TalkerWrapperOptions(enableErrorAlerts: true),
|
||||||
|
child: WindowScaffold(
|
||||||
|
child: child ?? const SizedBox.shrink(),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -13,10 +13,13 @@ sealed class SnAccount with _$SnAccount {
|
|||||||
required String name,
|
required String name,
|
||||||
required String nick,
|
required String nick,
|
||||||
required String language,
|
required String language,
|
||||||
|
@Default("") String region,
|
||||||
required bool isSuperuser,
|
required bool isSuperuser,
|
||||||
|
required String? automatedId,
|
||||||
required SnAccountProfile profile,
|
required SnAccountProfile profile,
|
||||||
required SnWalletSubscriptionRef? perkSubscription,
|
required SnWalletSubscriptionRef? perkSubscription,
|
||||||
@Default([]) List<SnAccountBadge> badges,
|
@Default([]) List<SnAccountBadge> badges,
|
||||||
|
@Default([]) List<SnContactMethod> contacts,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
@@ -52,6 +55,19 @@ class ProfileLinkConverter
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class UsernameColor with _$UsernameColor {
|
||||||
|
const factory UsernameColor({
|
||||||
|
@Default('plain') String type,
|
||||||
|
String? value,
|
||||||
|
String? direction,
|
||||||
|
List<String>? colors,
|
||||||
|
}) = _UsernameColor;
|
||||||
|
|
||||||
|
factory UsernameColor.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$UsernameColorFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class SnAccountProfile with _$SnAccountProfile {
|
sealed class SnAccountProfile with _$SnAccountProfile {
|
||||||
const factory SnAccountProfile({
|
const factory SnAccountProfile({
|
||||||
@@ -70,10 +86,13 @@ sealed class SnAccountProfile with _$SnAccountProfile {
|
|||||||
SnAccountBadge? activeBadge,
|
SnAccountBadge? activeBadge,
|
||||||
required int experience,
|
required int experience,
|
||||||
required int level,
|
required int level,
|
||||||
|
@Default(100) double socialCredits,
|
||||||
|
@Default(0) int socialCreditsLevel,
|
||||||
required double levelingProgress,
|
required double levelingProgress,
|
||||||
required SnCloudFile? picture,
|
required SnCloudFile? picture,
|
||||||
required SnCloudFile? background,
|
required SnCloudFile? background,
|
||||||
required SnVerificationMark? verification,
|
required SnVerificationMark? verification,
|
||||||
|
UsernameColor? usernameColor,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
required DateTime? deletedAt,
|
required DateTime? deletedAt,
|
||||||
@@ -93,6 +112,7 @@ sealed class SnAccountStatus with _$SnAccountStatus {
|
|||||||
required bool isNotDisturb,
|
required bool isNotDisturb,
|
||||||
required bool isCustomized,
|
required bool isCustomized,
|
||||||
@Default("") String label,
|
@Default("") String label,
|
||||||
|
required Map<String, dynamic>? meta,
|
||||||
required DateTime? clearedAt,
|
required DateTime? clearedAt,
|
||||||
required String accountId,
|
required String accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
@@ -131,6 +151,7 @@ sealed class SnContactMethod with _$SnContactMethod {
|
|||||||
required int type,
|
required int type,
|
||||||
required DateTime? verifiedAt,
|
required DateTime? verifiedAt,
|
||||||
required bool isPrimary,
|
required bool isPrimary,
|
||||||
|
required bool isPublic,
|
||||||
required String content,
|
required String content,
|
||||||
required String accountId,
|
required String accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
@@ -208,3 +229,37 @@ sealed class SnAuthDeviceWithChallenge with _$SnAuthDeviceWithChallenge {
|
|||||||
factory SnAuthDeviceWithChallenge.fromJson(Map<String, dynamic> json) =>
|
factory SnAuthDeviceWithChallenge.fromJson(Map<String, dynamic> json) =>
|
||||||
_$SnAuthDeviceWithChallengeFromJson(json);
|
_$SnAuthDeviceWithChallengeFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnExperienceRecord with _$SnExperienceRecord {
|
||||||
|
const factory SnExperienceRecord({
|
||||||
|
required String id,
|
||||||
|
required int delta,
|
||||||
|
required String reasonType,
|
||||||
|
required String reason,
|
||||||
|
@Default(1.0) double? bonusMultiplier,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
required DateTime? deletedAt,
|
||||||
|
}) = _SnExperienceRecord;
|
||||||
|
|
||||||
|
factory SnExperienceRecord.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnExperienceRecordFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnSocialCreditRecord with _$SnSocialCreditRecord {
|
||||||
|
const factory SnSocialCreditRecord({
|
||||||
|
required String id,
|
||||||
|
required double delta,
|
||||||
|
required String reasonType,
|
||||||
|
required String reason,
|
||||||
|
required DateTime? expiredAt,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
required DateTime? deletedAt,
|
||||||
|
}) = _SnSocialCreditRecord;
|
||||||
|
|
||||||
|
factory SnSocialCreditRecord.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnSocialCreditRecordFromJson(json);
|
||||||
|
}
|
||||||
|
|||||||
@@ -11,7 +11,9 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
|||||||
name: json['name'] as String,
|
name: json['name'] as String,
|
||||||
nick: json['nick'] as String,
|
nick: json['nick'] as String,
|
||||||
language: json['language'] as String,
|
language: json['language'] as String,
|
||||||
|
region: json['region'] as String? ?? "",
|
||||||
isSuperuser: json['is_superuser'] as bool,
|
isSuperuser: json['is_superuser'] as bool,
|
||||||
|
automatedId: json['automated_id'] as String?,
|
||||||
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
profile: SnAccountProfile.fromJson(json['profile'] as Map<String, dynamic>),
|
||||||
perkSubscription:
|
perkSubscription:
|
||||||
json['perk_subscription'] == null
|
json['perk_subscription'] == null
|
||||||
@@ -24,6 +26,11 @@ _SnAccount _$SnAccountFromJson(Map<String, dynamic> json) => _SnAccount(
|
|||||||
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnAccountBadge.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
|
contacts:
|
||||||
|
(json['contacts'] as List<dynamic>?)
|
||||||
|
?.map((e) => SnContactMethod.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
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:
|
||||||
@@ -38,10 +45,13 @@ Map<String, dynamic> _$SnAccountToJson(_SnAccount instance) =>
|
|||||||
'name': instance.name,
|
'name': instance.name,
|
||||||
'nick': instance.nick,
|
'nick': instance.nick,
|
||||||
'language': instance.language,
|
'language': instance.language,
|
||||||
|
'region': instance.region,
|
||||||
'is_superuser': instance.isSuperuser,
|
'is_superuser': instance.isSuperuser,
|
||||||
|
'automated_id': instance.automatedId,
|
||||||
'profile': instance.profile.toJson(),
|
'profile': instance.profile.toJson(),
|
||||||
'perk_subscription': instance.perkSubscription?.toJson(),
|
'perk_subscription': instance.perkSubscription?.toJson(),
|
||||||
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
'badges': instance.badges.map((e) => e.toJson()).toList(),
|
||||||
|
'contacts': instance.contacts.map((e) => e.toJson()).toList(),
|
||||||
'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(),
|
||||||
@@ -53,6 +63,23 @@ _ProfileLink _$ProfileLinkFromJson(Map<String, dynamic> json) =>
|
|||||||
Map<String, dynamic> _$ProfileLinkToJson(_ProfileLink instance) =>
|
Map<String, dynamic> _$ProfileLinkToJson(_ProfileLink instance) =>
|
||||||
<String, dynamic>{'name': instance.name, 'url': instance.url};
|
<String, dynamic>{'name': instance.name, 'url': instance.url};
|
||||||
|
|
||||||
|
_UsernameColor _$UsernameColorFromJson(Map<String, dynamic> json) =>
|
||||||
|
_UsernameColor(
|
||||||
|
type: json['type'] as String? ?? 'plain',
|
||||||
|
value: json['value'] as String?,
|
||||||
|
direction: json['direction'] as String?,
|
||||||
|
colors:
|
||||||
|
(json['colors'] as List<dynamic>?)?.map((e) => e as String).toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$UsernameColorToJson(_UsernameColor instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'type': instance.type,
|
||||||
|
'value': instance.value,
|
||||||
|
'direction': instance.direction,
|
||||||
|
'colors': instance.colors,
|
||||||
|
};
|
||||||
|
|
||||||
_SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
_SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
||||||
_SnAccountProfile(
|
_SnAccountProfile(
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
@@ -84,6 +111,8 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
|||||||
),
|
),
|
||||||
experience: (json['experience'] as num).toInt(),
|
experience: (json['experience'] as num).toInt(),
|
||||||
level: (json['level'] as num).toInt(),
|
level: (json['level'] as num).toInt(),
|
||||||
|
socialCredits: (json['social_credits'] as num?)?.toDouble() ?? 100,
|
||||||
|
socialCreditsLevel: (json['social_credits_level'] as num?)?.toInt() ?? 0,
|
||||||
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
levelingProgress: (json['leveling_progress'] as num).toDouble(),
|
||||||
picture:
|
picture:
|
||||||
json['picture'] == null
|
json['picture'] == null
|
||||||
@@ -101,6 +130,12 @@ _SnAccountProfile _$SnAccountProfileFromJson(Map<String, dynamic> json) =>
|
|||||||
: SnVerificationMark.fromJson(
|
: SnVerificationMark.fromJson(
|
||||||
json['verification'] as Map<String, dynamic>,
|
json['verification'] as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
|
usernameColor:
|
||||||
|
json['username_color'] == null
|
||||||
|
? null
|
||||||
|
: UsernameColor.fromJson(
|
||||||
|
json['username_color'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
createdAt: DateTime.parse(json['created_at'] as String),
|
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:
|
||||||
@@ -126,10 +161,13 @@ Map<String, dynamic> _$SnAccountProfileToJson(_SnAccountProfile instance) =>
|
|||||||
'active_badge': instance.activeBadge?.toJson(),
|
'active_badge': instance.activeBadge?.toJson(),
|
||||||
'experience': instance.experience,
|
'experience': instance.experience,
|
||||||
'level': instance.level,
|
'level': instance.level,
|
||||||
|
'social_credits': instance.socialCredits,
|
||||||
|
'social_credits_level': instance.socialCreditsLevel,
|
||||||
'leveling_progress': instance.levelingProgress,
|
'leveling_progress': instance.levelingProgress,
|
||||||
'picture': instance.picture?.toJson(),
|
'picture': instance.picture?.toJson(),
|
||||||
'background': instance.background?.toJson(),
|
'background': instance.background?.toJson(),
|
||||||
'verification': instance.verification?.toJson(),
|
'verification': instance.verification?.toJson(),
|
||||||
|
'username_color': instance.usernameColor?.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(),
|
||||||
@@ -144,6 +182,7 @@ _SnAccountStatus _$SnAccountStatusFromJson(Map<String, dynamic> json) =>
|
|||||||
isNotDisturb: json['is_not_disturb'] as bool,
|
isNotDisturb: json['is_not_disturb'] as bool,
|
||||||
isCustomized: json['is_customized'] as bool,
|
isCustomized: json['is_customized'] as bool,
|
||||||
label: json['label'] as String? ?? "",
|
label: json['label'] as String? ?? "",
|
||||||
|
meta: json['meta'] as Map<String, dynamic>?,
|
||||||
clearedAt:
|
clearedAt:
|
||||||
json['cleared_at'] == null
|
json['cleared_at'] == null
|
||||||
? null
|
? null
|
||||||
@@ -166,6 +205,7 @@ Map<String, dynamic> _$SnAccountStatusToJson(_SnAccountStatus instance) =>
|
|||||||
'is_not_disturb': instance.isNotDisturb,
|
'is_not_disturb': instance.isNotDisturb,
|
||||||
'is_customized': instance.isCustomized,
|
'is_customized': instance.isCustomized,
|
||||||
'label': instance.label,
|
'label': instance.label,
|
||||||
|
'meta': instance.meta,
|
||||||
'cleared_at': instance.clearedAt?.toIso8601String(),
|
'cleared_at': instance.clearedAt?.toIso8601String(),
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
@@ -221,6 +261,7 @@ _SnContactMethod _$SnContactMethodFromJson(Map<String, dynamic> json) =>
|
|||||||
? null
|
? null
|
||||||
: DateTime.parse(json['verified_at'] as String),
|
: DateTime.parse(json['verified_at'] as String),
|
||||||
isPrimary: json['is_primary'] as bool,
|
isPrimary: json['is_primary'] as bool,
|
||||||
|
isPublic: json['is_public'] as bool,
|
||||||
content: json['content'] as String,
|
content: json['content'] as String,
|
||||||
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),
|
||||||
@@ -237,6 +278,7 @@ Map<String, dynamic> _$SnContactMethodToJson(_SnContactMethod instance) =>
|
|||||||
'type': instance.type,
|
'type': instance.type,
|
||||||
'verified_at': instance.verifiedAt?.toIso8601String(),
|
'verified_at': instance.verifiedAt?.toIso8601String(),
|
||||||
'is_primary': instance.isPrimary,
|
'is_primary': instance.isPrimary,
|
||||||
|
'is_public': instance.isPublic,
|
||||||
'content': instance.content,
|
'content': instance.content,
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
'created_at': instance.createdAt.toIso8601String(),
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
@@ -348,3 +390,62 @@ Map<String, dynamic> _$SnAuthDeviceWithChallengeeToJson(
|
|||||||
'challenges': instance.challenges.map((e) => e.toJson()).toList(),
|
'challenges': instance.challenges.map((e) => e.toJson()).toList(),
|
||||||
'is_current': instance.isCurrent,
|
'is_current': instance.isCurrent,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_SnExperienceRecord _$SnExperienceRecordFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnExperienceRecord(
|
||||||
|
id: json['id'] as String,
|
||||||
|
delta: (json['delta'] as num).toInt(),
|
||||||
|
reasonType: json['reason_type'] as String,
|
||||||
|
reason: json['reason'] as String,
|
||||||
|
bonusMultiplier: (json['bonus_multiplier'] as num?)?.toDouble() ?? 1.0,
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
deletedAt:
|
||||||
|
json['deleted_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnExperienceRecordToJson(_SnExperienceRecord instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'delta': instance.delta,
|
||||||
|
'reason_type': instance.reasonType,
|
||||||
|
'reason': instance.reason,
|
||||||
|
'bonus_multiplier': instance.bonusMultiplier,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
};
|
||||||
|
|
||||||
|
_SnSocialCreditRecord _$SnSocialCreditRecordFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _SnSocialCreditRecord(
|
||||||
|
id: json['id'] as String,
|
||||||
|
delta: (json['delta'] as num).toDouble(),
|
||||||
|
reasonType: json['reason_type'] as String,
|
||||||
|
reason: json['reason'] as String,
|
||||||
|
expiredAt:
|
||||||
|
json['expired_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['expired_at'] as String),
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
deletedAt:
|
||||||
|
json['deleted_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['deleted_at'] as String),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnSocialCreditRecordToJson(
|
||||||
|
_SnSocialCreditRecord instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'delta': instance.delta,
|
||||||
|
'reason_type': instance.reasonType,
|
||||||
|
'reason': instance.reason,
|
||||||
|
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'deleted_at': instance.deletedAt?.toIso8601String(),
|
||||||
|
};
|
||||||
|
|||||||
@@ -4,6 +4,20 @@ import 'package:island/models/account.dart';
|
|||||||
part 'activity.freezed.dart';
|
part 'activity.freezed.dart';
|
||||||
part 'activity.g.dart';
|
part 'activity.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnNotableDay with _$SnNotableDay {
|
||||||
|
const factory SnNotableDay({
|
||||||
|
required DateTime date,
|
||||||
|
required String localName,
|
||||||
|
required String globalName,
|
||||||
|
required String countryCode,
|
||||||
|
required List<int> holidays,
|
||||||
|
}) = _SnNotableDay;
|
||||||
|
|
||||||
|
factory SnNotableDay.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnNotableDayFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class SnActivity with _$SnActivity {
|
sealed class SnActivity with _$SnActivity {
|
||||||
const factory SnActivity({
|
const factory SnActivity({
|
||||||
@@ -54,7 +68,7 @@ sealed class SnEventCalendarEntry with _$SnEventCalendarEntry {
|
|||||||
const factory SnEventCalendarEntry({
|
const factory SnEventCalendarEntry({
|
||||||
required DateTime date,
|
required DateTime date,
|
||||||
required SnCheckInResult? checkInResult,
|
required SnCheckInResult? checkInResult,
|
||||||
required List<dynamic> statuses,
|
required List<SnAccountStatus> statuses,
|
||||||
}) = _SnEventCalendarEntry;
|
}) = _SnEventCalendarEntry;
|
||||||
|
|
||||||
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
|
factory SnEventCalendarEntry.fromJson(Map<String, dynamic> json) =>
|
||||||
|
|||||||
@@ -12,6 +12,281 @@ part of 'activity.dart';
|
|||||||
// dart format off
|
// dart format off
|
||||||
T _$identity<T>(T value) => value;
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnNotableDay {
|
||||||
|
|
||||||
|
DateTime get date; String get localName; String get globalName; String get countryCode; List<int> get holidays;
|
||||||
|
/// Create a copy of SnNotableDay
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnNotableDayCopyWith<SnNotableDay> get copyWith => _$SnNotableDayCopyWithImpl<SnNotableDay>(this as SnNotableDay, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnNotableDay to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnNotableDay&&(identical(other.date, date) || other.date == date)&&(identical(other.localName, localName) || other.localName == localName)&&(identical(other.globalName, globalName) || other.globalName == globalName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&const DeepCollectionEquality().equals(other.holidays, holidays));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,date,localName,globalName,countryCode,const DeepCollectionEquality().hash(holidays));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnNotableDay(date: $date, localName: $localName, globalName: $globalName, countryCode: $countryCode, holidays: $holidays)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnNotableDayCopyWith<$Res> {
|
||||||
|
factory $SnNotableDayCopyWith(SnNotableDay value, $Res Function(SnNotableDay) _then) = _$SnNotableDayCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
DateTime date, String localName, String globalName, String countryCode, List<int> holidays
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnNotableDayCopyWithImpl<$Res>
|
||||||
|
implements $SnNotableDayCopyWith<$Res> {
|
||||||
|
_$SnNotableDayCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnNotableDay _self;
|
||||||
|
final $Res Function(SnNotableDay) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnNotableDay
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? date = null,Object? localName = null,Object? globalName = null,Object? countryCode = null,Object? holidays = null,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,localName: null == localName ? _self.localName : localName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,globalName: null == globalName ? _self.globalName : globalName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,holidays: null == holidays ? _self.holidays : holidays // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<int>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [SnNotableDay].
|
||||||
|
extension SnNotableDayPatterns on SnNotableDay {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SnNotableDay value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnNotableDay() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SnNotableDay value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnNotableDay():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SnNotableDay value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnNotableDay() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, String localName, String globalName, String countryCode, List<int> holidays)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnNotableDay() when $default != null:
|
||||||
|
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, String localName, String globalName, String countryCode, List<int> holidays) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnNotableDay():
|
||||||
|
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, String localName, String globalName, String countryCode, List<int> holidays)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnNotableDay() when $default != null:
|
||||||
|
return $default(_that.date,_that.localName,_that.globalName,_that.countryCode,_that.holidays);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnNotableDay implements SnNotableDay {
|
||||||
|
const _SnNotableDay({required this.date, required this.localName, required this.globalName, required this.countryCode, required final List<int> holidays}): _holidays = holidays;
|
||||||
|
factory _SnNotableDay.fromJson(Map<String, dynamic> json) => _$SnNotableDayFromJson(json);
|
||||||
|
|
||||||
|
@override final DateTime date;
|
||||||
|
@override final String localName;
|
||||||
|
@override final String globalName;
|
||||||
|
@override final String countryCode;
|
||||||
|
final List<int> _holidays;
|
||||||
|
@override List<int> get holidays {
|
||||||
|
if (_holidays is EqualUnmodifiableListView) return _holidays;
|
||||||
|
// ignore: implicit_dynamic_type
|
||||||
|
return EqualUnmodifiableListView(_holidays);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Create a copy of SnNotableDay
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnNotableDayCopyWith<_SnNotableDay> get copyWith => __$SnNotableDayCopyWithImpl<_SnNotableDay>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnNotableDayToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnNotableDay&&(identical(other.date, date) || other.date == date)&&(identical(other.localName, localName) || other.localName == localName)&&(identical(other.globalName, globalName) || other.globalName == globalName)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&const DeepCollectionEquality().equals(other._holidays, _holidays));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,date,localName,globalName,countryCode,const DeepCollectionEquality().hash(_holidays));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnNotableDay(date: $date, localName: $localName, globalName: $globalName, countryCode: $countryCode, holidays: $holidays)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnNotableDayCopyWith<$Res> implements $SnNotableDayCopyWith<$Res> {
|
||||||
|
factory _$SnNotableDayCopyWith(_SnNotableDay value, $Res Function(_SnNotableDay) _then) = __$SnNotableDayCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
DateTime date, String localName, String globalName, String countryCode, List<int> holidays
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnNotableDayCopyWithImpl<$Res>
|
||||||
|
implements _$SnNotableDayCopyWith<$Res> {
|
||||||
|
__$SnNotableDayCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnNotableDay _self;
|
||||||
|
final $Res Function(_SnNotableDay) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnNotableDay
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? date = null,Object? localName = null,Object? globalName = null,Object? countryCode = null,Object? holidays = null,}) {
|
||||||
|
return _then(_SnNotableDay(
|
||||||
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,localName: null == localName ? _self.localName : localName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,globalName: null == globalName ? _self.globalName : globalName // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,countryCode: null == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,holidays: null == holidays ? _self._holidays : holidays // ignore: cast_nullable_to_non_nullable
|
||||||
|
as List<int>,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnActivity {
|
mixin _$SnActivity {
|
||||||
|
|
||||||
@@ -861,7 +1136,7 @@ as String,
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnEventCalendarEntry {
|
mixin _$SnEventCalendarEntry {
|
||||||
|
|
||||||
DateTime get date; SnCheckInResult? get checkInResult; List<dynamic> get statuses;
|
DateTime get date; SnCheckInResult? get checkInResult; List<SnAccountStatus> get statuses;
|
||||||
/// Create a copy of SnEventCalendarEntry
|
/// Create a copy of SnEventCalendarEntry
|
||||||
/// 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)
|
||||||
@@ -894,7 +1169,7 @@ abstract mixin class $SnEventCalendarEntryCopyWith<$Res> {
|
|||||||
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
|
factory $SnEventCalendarEntryCopyWith(SnEventCalendarEntry value, $Res Function(SnEventCalendarEntry) _then) = _$SnEventCalendarEntryCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -916,7 +1191,7 @@ class _$SnEventCalendarEntryCopyWithImpl<$Res>
|
|||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
|
as SnCheckInResult?,statuses: null == statuses ? _self.statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,
|
as List<SnAccountStatus>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnEventCalendarEntry
|
/// Create a copy of SnEventCalendarEntry
|
||||||
@@ -1010,7 +1285,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry() when $default != null:
|
case _SnEventCalendarEntry() when $default != null:
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||||
@@ -1031,7 +1306,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry():
|
case _SnEventCalendarEntry():
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
return $default(_that.date,_that.checkInResult,_that.statuses);}
|
||||||
@@ -1048,7 +1323,7 @@ return $default(_that.date,_that.checkInResult,_that.statuses);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnEventCalendarEntry() when $default != null:
|
case _SnEventCalendarEntry() when $default != null:
|
||||||
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
||||||
@@ -1063,13 +1338,13 @@ return $default(_that.date,_that.checkInResult,_that.statuses);case _:
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnEventCalendarEntry implements SnEventCalendarEntry {
|
class _SnEventCalendarEntry implements SnEventCalendarEntry {
|
||||||
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<dynamic> statuses}): _statuses = statuses;
|
const _SnEventCalendarEntry({required this.date, required this.checkInResult, required final List<SnAccountStatus> statuses}): _statuses = statuses;
|
||||||
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
|
factory _SnEventCalendarEntry.fromJson(Map<String, dynamic> json) => _$SnEventCalendarEntryFromJson(json);
|
||||||
|
|
||||||
@override final DateTime date;
|
@override final DateTime date;
|
||||||
@override final SnCheckInResult? checkInResult;
|
@override final SnCheckInResult? checkInResult;
|
||||||
final List<dynamic> _statuses;
|
final List<SnAccountStatus> _statuses;
|
||||||
@override List<dynamic> get statuses {
|
@override List<SnAccountStatus> get statuses {
|
||||||
if (_statuses is EqualUnmodifiableListView) return _statuses;
|
if (_statuses is EqualUnmodifiableListView) return _statuses;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_statuses);
|
return EqualUnmodifiableListView(_statuses);
|
||||||
@@ -1109,7 +1384,7 @@ abstract mixin class _$SnEventCalendarEntryCopyWith<$Res> implements $SnEventCal
|
|||||||
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
|
factory _$SnEventCalendarEntryCopyWith(_SnEventCalendarEntry value, $Res Function(_SnEventCalendarEntry) _then) = __$SnEventCalendarEntryCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
DateTime date, SnCheckInResult? checkInResult, List<dynamic> statuses
|
DateTime date, SnCheckInResult? checkInResult, List<SnAccountStatus> statuses
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -1131,7 +1406,7 @@ class __$SnEventCalendarEntryCopyWithImpl<$Res>
|
|||||||
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
date: null == date ? _self.date : date // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
as DateTime,checkInResult: freezed == checkInResult ? _self.checkInResult : checkInResult // ignore: cast_nullable_to_non_nullable
|
||||||
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
|
as SnCheckInResult?,statuses: null == statuses ? _self._statuses : statuses // ignore: cast_nullable_to_non_nullable
|
||||||
as List<dynamic>,
|
as List<SnAccountStatus>,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,27 @@ part of 'activity.dart';
|
|||||||
// JsonSerializableGenerator
|
// JsonSerializableGenerator
|
||||||
// **************************************************************************
|
// **************************************************************************
|
||||||
|
|
||||||
|
_SnNotableDay _$SnNotableDayFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnNotableDay(
|
||||||
|
date: DateTime.parse(json['date'] as String),
|
||||||
|
localName: json['local_name'] as String,
|
||||||
|
globalName: json['global_name'] as String,
|
||||||
|
countryCode: json['country_code'] as String,
|
||||||
|
holidays:
|
||||||
|
(json['holidays'] as List<dynamic>)
|
||||||
|
.map((e) => (e as num).toInt())
|
||||||
|
.toList(),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnNotableDayToJson(_SnNotableDay instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'date': instance.date.toIso8601String(),
|
||||||
|
'local_name': instance.localName,
|
||||||
|
'global_name': instance.globalName,
|
||||||
|
'country_code': instance.countryCode,
|
||||||
|
'holidays': instance.holidays,
|
||||||
|
};
|
||||||
|
|
||||||
_SnActivity _$SnActivityFromJson(Map<String, dynamic> json) => _SnActivity(
|
_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,
|
||||||
@@ -87,7 +108,10 @@ _SnEventCalendarEntry _$SnEventCalendarEntryFromJson(
|
|||||||
: SnCheckInResult.fromJson(
|
: SnCheckInResult.fromJson(
|
||||||
json['check_in_result'] as Map<String, dynamic>,
|
json['check_in_result'] as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
statuses: json['statuses'] as List<dynamic>,
|
statuses:
|
||||||
|
(json['statuses'] as List<dynamic>)
|
||||||
|
.map((e) => SnAccountStatus.fromJson(e as Map<String, dynamic>))
|
||||||
|
.toList(),
|
||||||
);
|
);
|
||||||
|
|
||||||
Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
||||||
@@ -95,5 +119,5 @@ Map<String, dynamic> _$SnEventCalendarEntryToJson(
|
|||||||
) => <String, dynamic>{
|
) => <String, dynamic>{
|
||||||
'date': instance.date.toIso8601String(),
|
'date': instance.date.toIso8601String(),
|
||||||
'check_in_result': instance.checkInResult?.toJson(),
|
'check_in_result': instance.checkInResult?.toJson(),
|
||||||
'statuses': instance.statuses,
|
'statuses': instance.statuses.map((e) => e.toJson()).toList(),
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -11,11 +11,25 @@ sealed class AppToken with _$AppToken {
|
|||||||
_$AppTokenFromJson(json);
|
_$AppTokenFromJson(json);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class GeoIpLocation with _$GeoIpLocation {
|
||||||
|
const factory GeoIpLocation({
|
||||||
|
required double? latitude,
|
||||||
|
required double? longitude,
|
||||||
|
required String? countryCode,
|
||||||
|
required String? country,
|
||||||
|
required String? city,
|
||||||
|
}) = _GeoIpLocation;
|
||||||
|
|
||||||
|
factory GeoIpLocation.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$GeoIpLocationFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed 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 failedAttempts,
|
||||||
@@ -26,7 +40,7 @@ sealed class SnAuthChallenge with _$SnAuthChallenge {
|
|||||||
required String ipAddress,
|
required String ipAddress,
|
||||||
required String userAgent,
|
required String userAgent,
|
||||||
required String? nonce,
|
required String? nonce,
|
||||||
required String? location,
|
required GeoIpLocation? location,
|
||||||
required String accountId,
|
required String accountId,
|
||||||
required DateTime createdAt,
|
required DateTime createdAt,
|
||||||
required DateTime updatedAt,
|
required DateTime updatedAt,
|
||||||
@@ -43,7 +57,7 @@ sealed class SnAuthSession with _$SnAuthSession {
|
|||||||
required String id,
|
required String id,
|
||||||
required String? label,
|
required String? label,
|
||||||
required DateTime lastGrantedAt,
|
required DateTime lastGrantedAt,
|
||||||
required DateTime expiredAt,
|
required DateTime? expiredAt,
|
||||||
required String accountId,
|
required String accountId,
|
||||||
required String challengeId,
|
required String challengeId,
|
||||||
required SnAuthChallenge challenge,
|
required SnAuthChallenge challenge,
|
||||||
|
|||||||
@@ -269,10 +269,279 @@ as String,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$GeoIpLocation {
|
||||||
|
|
||||||
|
double? get latitude; double? get longitude; String? get countryCode; String? get country; String? get city;
|
||||||
|
/// Create a copy of GeoIpLocation
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$GeoIpLocationCopyWith<GeoIpLocation> get copyWith => _$GeoIpLocationCopyWithImpl<GeoIpLocation>(this as GeoIpLocation, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this GeoIpLocation to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is GeoIpLocation&&(identical(other.latitude, latitude) || other.latitude == latitude)&&(identical(other.longitude, longitude) || other.longitude == longitude)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.country, country) || other.country == country)&&(identical(other.city, city) || other.city == city));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,latitude,longitude,countryCode,country,city);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'GeoIpLocation(latitude: $latitude, longitude: $longitude, countryCode: $countryCode, country: $country, city: $city)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $GeoIpLocationCopyWith<$Res> {
|
||||||
|
factory $GeoIpLocationCopyWith(GeoIpLocation value, $Res Function(GeoIpLocation) _then) = _$GeoIpLocationCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
double? latitude, double? longitude, String? countryCode, String? country, String? city
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$GeoIpLocationCopyWithImpl<$Res>
|
||||||
|
implements $GeoIpLocationCopyWith<$Res> {
|
||||||
|
_$GeoIpLocationCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final GeoIpLocation _self;
|
||||||
|
final $Res Function(GeoIpLocation) _then;
|
||||||
|
|
||||||
|
/// Create a copy of GeoIpLocation
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? latitude = freezed,Object? longitude = freezed,Object? countryCode = freezed,Object? country = freezed,Object? city = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
latitude: freezed == latitude ? _self.latitude : latitude // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,longitude: freezed == longitude ? _self.longitude : longitude // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,country: freezed == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,city: freezed == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [GeoIpLocation].
|
||||||
|
extension GeoIpLocationPatterns on GeoIpLocation {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _GeoIpLocation value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _GeoIpLocation() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _GeoIpLocation value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _GeoIpLocation():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _GeoIpLocation value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _GeoIpLocation() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( double? latitude, double? longitude, String? countryCode, String? country, String? city)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _GeoIpLocation() when $default != null:
|
||||||
|
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( double? latitude, double? longitude, String? countryCode, String? country, String? city) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _GeoIpLocation():
|
||||||
|
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( double? latitude, double? longitude, String? countryCode, String? country, String? city)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _GeoIpLocation() when $default != null:
|
||||||
|
return $default(_that.latitude,_that.longitude,_that.countryCode,_that.country,_that.city);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _GeoIpLocation implements GeoIpLocation {
|
||||||
|
const _GeoIpLocation({required this.latitude, required this.longitude, required this.countryCode, required this.country, required this.city});
|
||||||
|
factory _GeoIpLocation.fromJson(Map<String, dynamic> json) => _$GeoIpLocationFromJson(json);
|
||||||
|
|
||||||
|
@override final double? latitude;
|
||||||
|
@override final double? longitude;
|
||||||
|
@override final String? countryCode;
|
||||||
|
@override final String? country;
|
||||||
|
@override final String? city;
|
||||||
|
|
||||||
|
/// Create a copy of GeoIpLocation
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$GeoIpLocationCopyWith<_GeoIpLocation> get copyWith => __$GeoIpLocationCopyWithImpl<_GeoIpLocation>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$GeoIpLocationToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _GeoIpLocation&&(identical(other.latitude, latitude) || other.latitude == latitude)&&(identical(other.longitude, longitude) || other.longitude == longitude)&&(identical(other.countryCode, countryCode) || other.countryCode == countryCode)&&(identical(other.country, country) || other.country == country)&&(identical(other.city, city) || other.city == city));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,latitude,longitude,countryCode,country,city);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'GeoIpLocation(latitude: $latitude, longitude: $longitude, countryCode: $countryCode, country: $country, city: $city)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$GeoIpLocationCopyWith<$Res> implements $GeoIpLocationCopyWith<$Res> {
|
||||||
|
factory _$GeoIpLocationCopyWith(_GeoIpLocation value, $Res Function(_GeoIpLocation) _then) = __$GeoIpLocationCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
double? latitude, double? longitude, String? countryCode, String? country, String? city
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$GeoIpLocationCopyWithImpl<$Res>
|
||||||
|
implements _$GeoIpLocationCopyWith<$Res> {
|
||||||
|
__$GeoIpLocationCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _GeoIpLocation _self;
|
||||||
|
final $Res Function(_GeoIpLocation) _then;
|
||||||
|
|
||||||
|
/// Create a copy of GeoIpLocation
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? latitude = freezed,Object? longitude = freezed,Object? countryCode = freezed,Object? country = freezed,Object? city = freezed,}) {
|
||||||
|
return _then(_GeoIpLocation(
|
||||||
|
latitude: freezed == latitude ? _self.latitude : latitude // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,longitude: freezed == longitude ? _self.longitude : longitude // ignore: cast_nullable_to_non_nullable
|
||||||
|
as double?,countryCode: freezed == countryCode ? _self.countryCode : countryCode // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,country: freezed == country ? _self.country : country // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,city: freezed == city ? _self.city : city // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAuthChallenge {
|
mixin _$SnAuthChallenge {
|
||||||
|
|
||||||
String get id; DateTime get expiredAt; int get stepRemain; int get stepTotal; int get failedAttempts; int get type; List<String> get blacklistFactors; List<dynamic> get audiences; List<dynamic> get scopes; String get ipAddress; String get userAgent; String? get nonce; String? get location; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; DateTime? get expiredAt; int get stepRemain; int get stepTotal; int get failedAttempts; int get type; List<String> get blacklistFactors; List<dynamic> get audiences; List<dynamic> get scopes; String get ipAddress; String get userAgent; String? get nonce; GeoIpLocation? get location; String get accountId; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnAuthChallenge
|
/// 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)
|
||||||
@@ -305,11 +574,11 @@ 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, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$GeoIpLocationCopyWith<$Res>? get location;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -322,11 +591,11 @@ 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? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? expiredAt = freezed,Object? stepRemain = null,Object? stepTotal = null,Object? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
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: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,stepRemain: null == stepRemain ? _self.stepRemain : stepRemain // ignore: cast_nullable_to_non_nullable
|
as 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,failedAttempts: null == failedAttempts ? _self.failedAttempts : failedAttempts // ignore: cast_nullable_to_non_nullable
|
||||||
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -337,14 +606,26 @@ as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // i
|
|||||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as GeoIpLocation?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as 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?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
/// Create a copy of SnAuthChallenge
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$GeoIpLocationCopyWith<$Res>? get location {
|
||||||
|
if (_self.location == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $GeoIpLocationCopyWith<$Res>(_self.location!, (value) {
|
||||||
|
return _then(_self.copyWith(location: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -423,7 +704,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthChallenge() when $default != null:
|
case _SnAuthChallenge() when $default != null:
|
||||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
@@ -444,7 +725,7 @@ return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthChallenge():
|
case _SnAuthChallenge():
|
||||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||||
@@ -461,7 +742,7 @@ return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, DateTime expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthChallenge() when $default != null:
|
case _SnAuthChallenge() when $default != null:
|
||||||
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.expiredAt,_that.stepRemain,_that.stepTotal,_that.failedAttempts,_that.type,_that.blacklistFactors,_that.audiences,_that.scopes,_that.ipAddress,_that.userAgent,_that.nonce,_that.location,_that.accountId,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
@@ -480,7 +761,7 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
|||||||
factory _SnAuthChallenge.fromJson(Map<String, dynamic> json) => _$SnAuthChallengeFromJson(json);
|
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 failedAttempts;
|
||||||
@@ -509,7 +790,7 @@ class _SnAuthChallenge implements SnAuthChallenge {
|
|||||||
@override final String ipAddress;
|
@override final String ipAddress;
|
||||||
@override final String userAgent;
|
@override final String userAgent;
|
||||||
@override final String? nonce;
|
@override final String? nonce;
|
||||||
@override final String? location;
|
@override final GeoIpLocation? location;
|
||||||
@override final String accountId;
|
@override final String accountId;
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@override final DateTime updatedAt;
|
@override final DateTime updatedAt;
|
||||||
@@ -548,11 +829,11 @@ 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, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, String? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, DateTime? expiredAt, int stepRemain, int stepTotal, int failedAttempts, int type, List<String> blacklistFactors, List<dynamic> audiences, List<dynamic> scopes, String ipAddress, String userAgent, String? nonce, GeoIpLocation? location, String accountId, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
|
@override $GeoIpLocationCopyWith<$Res>? get location;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -565,11 +846,11 @@ 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? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? expiredAt = freezed,Object? stepRemain = null,Object? stepTotal = null,Object? failedAttempts = null,Object? type = null,Object? blacklistFactors = null,Object? audiences = null,Object? scopes = null,Object? ipAddress = null,Object? userAgent = null,Object? nonce = freezed,Object? location = freezed,Object? accountId = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnAuthChallenge(
|
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: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,stepRemain: null == stepRemain ? _self.stepRemain : stepRemain // ignore: cast_nullable_to_non_nullable
|
as 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,failedAttempts: null == failedAttempts ? _self.failedAttempts : failedAttempts // ignore: cast_nullable_to_non_nullable
|
||||||
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
as int,type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -580,7 +861,7 @@ as List<dynamic>,ipAddress: null == ipAddress ? _self.ipAddress : ipAddress // i
|
|||||||
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
as String,userAgent: null == userAgent ? _self.userAgent : userAgent // ignore: cast_nullable_to_non_nullable
|
||||||
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
as String,nonce: freezed == nonce ? _self.nonce : nonce // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
as String?,location: freezed == location ? _self.location : location // ignore: cast_nullable_to_non_nullable
|
||||||
as String?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as GeoIpLocation?,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
as 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
|
||||||
@@ -588,14 +869,26 @@ as DateTime?,
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Create a copy of SnAuthChallenge
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$GeoIpLocationCopyWith<$Res>? get location {
|
||||||
|
if (_self.location == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $GeoIpLocationCopyWith<$Res>(_self.location!, (value) {
|
||||||
|
return _then(_self.copyWith(location: value));
|
||||||
|
});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnAuthSession {
|
mixin _$SnAuthSession {
|
||||||
|
|
||||||
String get id; String? get label; DateTime get lastGrantedAt; DateTime get expiredAt; String get accountId; String get challengeId; SnAuthChallenge get challenge; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
String get id; String? get label; DateTime get lastGrantedAt; DateTime? get expiredAt; String get accountId; String get challengeId; SnAuthChallenge get challenge; DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt;
|
||||||
/// Create a copy of SnAuthSession
|
/// Create a copy of SnAuthSession
|
||||||
/// 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)
|
||||||
@@ -628,7 +921,7 @@ abstract mixin class $SnAuthSessionCopyWith<$Res> {
|
|||||||
factory $SnAuthSessionCopyWith(SnAuthSession value, $Res Function(SnAuthSession) _then) = _$SnAuthSessionCopyWithImpl;
|
factory $SnAuthSessionCopyWith(SnAuthSession value, $Res Function(SnAuthSession) _then) = _$SnAuthSessionCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -645,13 +938,13 @@ class _$SnAuthSessionCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAuthSession
|
/// Create a copy of SnAuthSession
|
||||||
/// 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? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = null,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = freezed,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
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,label: freezed == label ? _self.label : label // 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 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,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as 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,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 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 SnAuthChallenge,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -748,7 +1041,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthSession() when $default != null:
|
case _SnAuthSession() when $default != null:
|
||||||
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
@@ -769,7 +1062,7 @@ return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.a
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthSession():
|
case _SnAuthSession():
|
||||||
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);}
|
||||||
@@ -786,7 +1079,7 @@ return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.a
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnAuthSession() when $default != null:
|
case _SnAuthSession() when $default != null:
|
||||||
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
return $default(_that.id,_that.label,_that.lastGrantedAt,_that.expiredAt,_that.accountId,_that.challengeId,_that.challenge,_that.createdAt,_that.updatedAt,_that.deletedAt);case _:
|
||||||
@@ -807,7 +1100,7 @@ class _SnAuthSession implements SnAuthSession {
|
|||||||
@override final String id;
|
@override final String id;
|
||||||
@override final String? label;
|
@override final String? label;
|
||||||
@override final DateTime lastGrantedAt;
|
@override final DateTime lastGrantedAt;
|
||||||
@override final DateTime expiredAt;
|
@override final DateTime? expiredAt;
|
||||||
@override final String accountId;
|
@override final String accountId;
|
||||||
@override final String challengeId;
|
@override final String challengeId;
|
||||||
@override final SnAuthChallenge challenge;
|
@override final SnAuthChallenge challenge;
|
||||||
@@ -848,7 +1141,7 @@ abstract mixin class _$SnAuthSessionCopyWith<$Res> implements $SnAuthSessionCopy
|
|||||||
factory _$SnAuthSessionCopyWith(_SnAuthSession value, $Res Function(_SnAuthSession) _then) = __$SnAuthSessionCopyWithImpl;
|
factory _$SnAuthSessionCopyWith(_SnAuthSession value, $Res Function(_SnAuthSession) _then) = __$SnAuthSessionCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
String id, String? label, DateTime lastGrantedAt, DateTime expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
String id, String? label, DateTime lastGrantedAt, DateTime? expiredAt, String accountId, String challengeId, SnAuthChallenge challenge, DateTime createdAt, DateTime updatedAt, DateTime? deletedAt
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -865,13 +1158,13 @@ class __$SnAuthSessionCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnAuthSession
|
/// Create a copy of SnAuthSession
|
||||||
/// 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? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = null,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? label = freezed,Object? lastGrantedAt = null,Object? expiredAt = freezed,Object? accountId = null,Object? challengeId = null,Object? challenge = null,Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,}) {
|
||||||
return _then(_SnAuthSession(
|
return _then(_SnAuthSession(
|
||||||
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,label: freezed == label ? _self.label : label // 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 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,expiredAt: freezed == expiredAt ? _self.expiredAt : expiredAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
as 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,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 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 SnAuthChallenge,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
|||||||
@@ -13,10 +13,31 @@ Map<String, dynamic> _$AppTokenToJson(_AppToken instance) => <String, dynamic>{
|
|||||||
'token': instance.token,
|
'token': instance.token,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
_GeoIpLocation _$GeoIpLocationFromJson(Map<String, dynamic> json) =>
|
||||||
|
_GeoIpLocation(
|
||||||
|
latitude: (json['latitude'] as num?)?.toDouble(),
|
||||||
|
longitude: (json['longitude'] as num?)?.toDouble(),
|
||||||
|
countryCode: json['country_code'] as String?,
|
||||||
|
country: json['country'] as String?,
|
||||||
|
city: json['city'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$GeoIpLocationToJson(_GeoIpLocation instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'latitude': instance.latitude,
|
||||||
|
'longitude': instance.longitude,
|
||||||
|
'country_code': instance.countryCode,
|
||||||
|
'country': instance.country,
|
||||||
|
'city': instance.city,
|
||||||
|
};
|
||||||
|
|
||||||
_SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
_SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
||||||
_SnAuthChallenge(
|
_SnAuthChallenge(
|
||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
expiredAt: DateTime.parse(json['expired_at'] as String),
|
expiredAt:
|
||||||
|
json['expired_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['expired_at'] as String),
|
||||||
stepRemain: (json['step_remain'] as num).toInt(),
|
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(),
|
failedAttempts: (json['failed_attempts'] as num).toInt(),
|
||||||
@@ -30,7 +51,12 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
|||||||
ipAddress: json['ip_address'] as String,
|
ipAddress: json['ip_address'] as String,
|
||||||
userAgent: json['user_agent'] as String,
|
userAgent: json['user_agent'] as String,
|
||||||
nonce: json['nonce'] as String?,
|
nonce: json['nonce'] as String?,
|
||||||
location: json['location'] as String?,
|
location:
|
||||||
|
json['location'] == null
|
||||||
|
? null
|
||||||
|
: GeoIpLocation.fromJson(
|
||||||
|
json['location'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
accountId: json['account_id'] as String,
|
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),
|
||||||
@@ -43,7 +69,7 @@ _SnAuthChallenge _$SnAuthChallengeFromJson(Map<String, dynamic> json) =>
|
|||||||
Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'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,
|
'failed_attempts': instance.failedAttempts,
|
||||||
@@ -54,7 +80,7 @@ Map<String, dynamic> _$SnAuthChallengeToJson(_SnAuthChallenge instance) =>
|
|||||||
'ip_address': instance.ipAddress,
|
'ip_address': instance.ipAddress,
|
||||||
'user_agent': instance.userAgent,
|
'user_agent': instance.userAgent,
|
||||||
'nonce': instance.nonce,
|
'nonce': instance.nonce,
|
||||||
'location': instance.location,
|
'location': instance.location?.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(),
|
||||||
@@ -66,7 +92,10 @@ _SnAuthSession _$SnAuthSessionFromJson(Map<String, dynamic> json) =>
|
|||||||
id: json['id'] as String,
|
id: json['id'] as String,
|
||||||
label: json['label'] as String?,
|
label: json['label'] as String?,
|
||||||
lastGrantedAt: DateTime.parse(json['last_granted_at'] as String),
|
lastGrantedAt: DateTime.parse(json['last_granted_at'] as String),
|
||||||
expiredAt: DateTime.parse(json['expired_at'] as String),
|
expiredAt:
|
||||||
|
json['expired_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['expired_at'] as String),
|
||||||
accountId: json['account_id'] as String,
|
accountId: json['account_id'] as String,
|
||||||
challengeId: json['challenge_id'] as String,
|
challengeId: json['challenge_id'] as String,
|
||||||
challenge: SnAuthChallenge.fromJson(
|
challenge: SnAuthChallenge.fromJson(
|
||||||
@@ -85,7 +114,7 @@ Map<String, dynamic> _$SnAuthSessionToJson(_SnAuthSession instance) =>
|
|||||||
'id': instance.id,
|
'id': instance.id,
|
||||||
'label': instance.label,
|
'label': instance.label,
|
||||||
'last_granted_at': instance.lastGrantedAt.toIso8601String(),
|
'last_granted_at': instance.lastGrantedAt.toIso8601String(),
|
||||||
'expired_at': instance.expiredAt.toIso8601String(),
|
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||||
'account_id': instance.accountId,
|
'account_id': instance.accountId,
|
||||||
'challenge_id': instance.challengeId,
|
'challenge_id': instance.challengeId,
|
||||||
'challenge': instance.challenge.toJson(),
|
'challenge': instance.challenge.toJson(),
|
||||||
|
|||||||
16
lib/models/autocomplete_response.dart
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'autocomplete_response.freezed.dart';
|
||||||
|
part 'autocomplete_response.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class AutocompleteSuggestion with _$AutocompleteSuggestion {
|
||||||
|
const factory AutocompleteSuggestion({
|
||||||
|
required String type,
|
||||||
|
required String keyword,
|
||||||
|
required dynamic data,
|
||||||
|
}) = _AutocompleteSuggestion;
|
||||||
|
|
||||||
|
factory AutocompleteSuggestion.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$AutocompleteSuggestionFromJson(json);
|
||||||
|
}
|
||||||
277
lib/models/autocomplete_response.freezed.dart
Normal file
@@ -0,0 +1,277 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'autocomplete_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$AutocompleteSuggestion {
|
||||||
|
|
||||||
|
String get type; String get keyword; dynamic get data;
|
||||||
|
/// Create a copy of AutocompleteSuggestion
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$AutocompleteSuggestionCopyWith<AutocompleteSuggestion> get copyWith => _$AutocompleteSuggestionCopyWithImpl<AutocompleteSuggestion>(this as AutocompleteSuggestion, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this AutocompleteSuggestion to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is AutocompleteSuggestion&&(identical(other.type, type) || other.type == type)&&(identical(other.keyword, keyword) || other.keyword == keyword)&&const DeepCollectionEquality().equals(other.data, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,type,keyword,const DeepCollectionEquality().hash(data));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AutocompleteSuggestion(type: $type, keyword: $keyword, data: $data)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $AutocompleteSuggestionCopyWith<$Res> {
|
||||||
|
factory $AutocompleteSuggestionCopyWith(AutocompleteSuggestion value, $Res Function(AutocompleteSuggestion) _then) = _$AutocompleteSuggestionCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String type, String keyword, dynamic data
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$AutocompleteSuggestionCopyWithImpl<$Res>
|
||||||
|
implements $AutocompleteSuggestionCopyWith<$Res> {
|
||||||
|
_$AutocompleteSuggestionCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final AutocompleteSuggestion _self;
|
||||||
|
final $Res Function(AutocompleteSuggestion) _then;
|
||||||
|
|
||||||
|
/// Create a copy of AutocompleteSuggestion
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? type = null,Object? keyword = null,Object? data = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,keyword: null == keyword ? _self.keyword : keyword // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||||
|
as dynamic,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [AutocompleteSuggestion].
|
||||||
|
extension AutocompleteSuggestionPatterns on AutocompleteSuggestion {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _AutocompleteSuggestion value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AutocompleteSuggestion() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _AutocompleteSuggestion value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AutocompleteSuggestion():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _AutocompleteSuggestion value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AutocompleteSuggestion() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String type, String keyword, dynamic data)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AutocompleteSuggestion() when $default != null:
|
||||||
|
return $default(_that.type,_that.keyword,_that.data);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String type, String keyword, dynamic data) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AutocompleteSuggestion():
|
||||||
|
return $default(_that.type,_that.keyword,_that.data);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String type, String keyword, dynamic data)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _AutocompleteSuggestion() when $default != null:
|
||||||
|
return $default(_that.type,_that.keyword,_that.data);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _AutocompleteSuggestion implements AutocompleteSuggestion {
|
||||||
|
const _AutocompleteSuggestion({required this.type, required this.keyword, required this.data});
|
||||||
|
factory _AutocompleteSuggestion.fromJson(Map<String, dynamic> json) => _$AutocompleteSuggestionFromJson(json);
|
||||||
|
|
||||||
|
@override final String type;
|
||||||
|
@override final String keyword;
|
||||||
|
@override final dynamic data;
|
||||||
|
|
||||||
|
/// Create a copy of AutocompleteSuggestion
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$AutocompleteSuggestionCopyWith<_AutocompleteSuggestion> get copyWith => __$AutocompleteSuggestionCopyWithImpl<_AutocompleteSuggestion>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$AutocompleteSuggestionToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _AutocompleteSuggestion&&(identical(other.type, type) || other.type == type)&&(identical(other.keyword, keyword) || other.keyword == keyword)&&const DeepCollectionEquality().equals(other.data, data));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,type,keyword,const DeepCollectionEquality().hash(data));
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'AutocompleteSuggestion(type: $type, keyword: $keyword, data: $data)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$AutocompleteSuggestionCopyWith<$Res> implements $AutocompleteSuggestionCopyWith<$Res> {
|
||||||
|
factory _$AutocompleteSuggestionCopyWith(_AutocompleteSuggestion value, $Res Function(_AutocompleteSuggestion) _then) = __$AutocompleteSuggestionCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String type, String keyword, dynamic data
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$AutocompleteSuggestionCopyWithImpl<$Res>
|
||||||
|
implements _$AutocompleteSuggestionCopyWith<$Res> {
|
||||||
|
__$AutocompleteSuggestionCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _AutocompleteSuggestion _self;
|
||||||
|
final $Res Function(_AutocompleteSuggestion) _then;
|
||||||
|
|
||||||
|
/// Create a copy of AutocompleteSuggestion
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? type = null,Object? keyword = null,Object? data = freezed,}) {
|
||||||
|
return _then(_AutocompleteSuggestion(
|
||||||
|
type: null == type ? _self.type : type // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,keyword: null == keyword ? _self.keyword : keyword // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,data: freezed == data ? _self.data : data // ignore: cast_nullable_to_non_nullable
|
||||||
|
as dynamic,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
23
lib/models/autocomplete_response.g.dart
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'autocomplete_response.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_AutocompleteSuggestion _$AutocompleteSuggestionFromJson(
|
||||||
|
Map<String, dynamic> json,
|
||||||
|
) => _AutocompleteSuggestion(
|
||||||
|
type: json['type'] as String,
|
||||||
|
keyword: json['keyword'] as String,
|
||||||
|
data: json['data'],
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$AutocompleteSuggestionToJson(
|
||||||
|
_AutocompleteSuggestion instance,
|
||||||
|
) => <String, dynamic>{
|
||||||
|
'type': instance.type,
|
||||||
|
'keyword': instance.keyword,
|
||||||
|
'data': instance.data,
|
||||||
|
};
|
||||||
63
lib/models/bot.dart
Normal file
@@ -0,0 +1,63 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
import 'package:island/models/account.dart';
|
||||||
|
import 'package:island/models/developer.dart';
|
||||||
|
|
||||||
|
part 'bot.freezed.dart';
|
||||||
|
part 'bot.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class Bot with _$Bot {
|
||||||
|
const factory Bot({
|
||||||
|
required String id,
|
||||||
|
required String slug,
|
||||||
|
required bool isActive,
|
||||||
|
required String projectId,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
required SnAccount account,
|
||||||
|
SnDeveloper? developer,
|
||||||
|
}) = _Bot;
|
||||||
|
|
||||||
|
factory Bot.fromJson(Map<String, dynamic> json) => _$BotFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class BotConfig with _$BotConfig {
|
||||||
|
const factory BotConfig({
|
||||||
|
@Default(false) bool isPublic,
|
||||||
|
@Default(false) bool isInteractive,
|
||||||
|
@Default([]) List<String> allowedRealms,
|
||||||
|
@Default([]) List<String> allowedChatTypes,
|
||||||
|
@Default({}) Map<String, dynamic> metadata,
|
||||||
|
}) = _BotConfig;
|
||||||
|
|
||||||
|
factory BotConfig.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$BotConfigFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class BotLinks with _$BotLinks {
|
||||||
|
const factory BotLinks({
|
||||||
|
String? website,
|
||||||
|
String? documentation,
|
||||||
|
String? privacyPolicy,
|
||||||
|
String? termsOfService,
|
||||||
|
}) = _BotLinks;
|
||||||
|
|
||||||
|
factory BotLinks.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$BotLinksFromJson(json);
|
||||||
|
}
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class BotSecret with _$BotSecret {
|
||||||
|
const factory BotSecret({
|
||||||
|
@Default('') String id,
|
||||||
|
@Default('') String secret,
|
||||||
|
String? description,
|
||||||
|
DateTime? expiredAt,
|
||||||
|
@Default('') String botId,
|
||||||
|
}) = _BotSecret;
|
||||||
|
|
||||||
|
factory BotSecret.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$BotSecretFromJson(json);
|
||||||
|
}
|
||||||
1156
lib/models/bot.freezed.dart
Normal file
91
lib/models/bot.g.dart
Normal file
@@ -0,0 +1,91 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'bot.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_Bot _$BotFromJson(Map<String, dynamic> json) => _Bot(
|
||||||
|
id: json['id'] as String,
|
||||||
|
slug: json['slug'] as String,
|
||||||
|
isActive: json['is_active'] as bool,
|
||||||
|
projectId: json['project_id'] as String,
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
account: SnAccount.fromJson(json['account'] as Map<String, dynamic>),
|
||||||
|
developer:
|
||||||
|
json['developer'] == null
|
||||||
|
? null
|
||||||
|
: SnDeveloper.fromJson(json['developer'] as Map<String, dynamic>),
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$BotToJson(_Bot instance) => <String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'slug': instance.slug,
|
||||||
|
'is_active': instance.isActive,
|
||||||
|
'project_id': instance.projectId,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'account': instance.account.toJson(),
|
||||||
|
'developer': instance.developer?.toJson(),
|
||||||
|
};
|
||||||
|
|
||||||
|
_BotConfig _$BotConfigFromJson(Map<String, dynamic> json) => _BotConfig(
|
||||||
|
isPublic: json['is_public'] as bool? ?? false,
|
||||||
|
isInteractive: json['is_interactive'] as bool? ?? false,
|
||||||
|
allowedRealms:
|
||||||
|
(json['allowed_realms'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
allowedChatTypes:
|
||||||
|
(json['allowed_chat_types'] as List<dynamic>?)
|
||||||
|
?.map((e) => e as String)
|
||||||
|
.toList() ??
|
||||||
|
const [],
|
||||||
|
metadata: json['metadata'] as Map<String, dynamic>? ?? const {},
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$BotConfigToJson(_BotConfig instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'is_public': instance.isPublic,
|
||||||
|
'is_interactive': instance.isInteractive,
|
||||||
|
'allowed_realms': instance.allowedRealms,
|
||||||
|
'allowed_chat_types': instance.allowedChatTypes,
|
||||||
|
'metadata': instance.metadata,
|
||||||
|
};
|
||||||
|
|
||||||
|
_BotLinks _$BotLinksFromJson(Map<String, dynamic> json) => _BotLinks(
|
||||||
|
website: json['website'] as String?,
|
||||||
|
documentation: json['documentation'] as String?,
|
||||||
|
privacyPolicy: json['privacy_policy'] as String?,
|
||||||
|
termsOfService: json['terms_of_service'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$BotLinksToJson(_BotLinks instance) => <String, dynamic>{
|
||||||
|
'website': instance.website,
|
||||||
|
'documentation': instance.documentation,
|
||||||
|
'privacy_policy': instance.privacyPolicy,
|
||||||
|
'terms_of_service': instance.termsOfService,
|
||||||
|
};
|
||||||
|
|
||||||
|
_BotSecret _$BotSecretFromJson(Map<String, dynamic> json) => _BotSecret(
|
||||||
|
id: json['id'] as String? ?? '',
|
||||||
|
secret: json['secret'] as String? ?? '',
|
||||||
|
description: json['description'] as String?,
|
||||||
|
expiredAt:
|
||||||
|
json['expired_at'] == null
|
||||||
|
? null
|
||||||
|
: DateTime.parse(json['expired_at'] as String),
|
||||||
|
botId: json['bot_id'] as String? ?? '',
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$BotSecretToJson(_BotSecret instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'secret': instance.secret,
|
||||||
|
'description': instance.description,
|
||||||
|
'expired_at': instance.expiredAt?.toIso8601String(),
|
||||||
|
'bot_id': instance.botId,
|
||||||
|
};
|
||||||
20
lib/models/bot_key.dart
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'bot_key.freezed.dart';
|
||||||
|
part 'bot_key.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class SnAccountApiKey with _$SnAccountApiKey {
|
||||||
|
const factory SnAccountApiKey({
|
||||||
|
required String id,
|
||||||
|
required String label,
|
||||||
|
required String accountId,
|
||||||
|
required String sessionId,
|
||||||
|
required DateTime createdAt,
|
||||||
|
required DateTime updatedAt,
|
||||||
|
String? key,
|
||||||
|
}) = _SnAccountApiKey;
|
||||||
|
|
||||||
|
factory SnAccountApiKey.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$SnAccountApiKeyFromJson(json);
|
||||||
|
}
|
||||||
289
lib/models/bot_key.freezed.dart
Normal file
@@ -0,0 +1,289 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'bot_key.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$SnAccountApiKey {
|
||||||
|
|
||||||
|
String get id; String get label; String get accountId; String get sessionId; DateTime get createdAt; DateTime get updatedAt; String? get key;
|
||||||
|
/// Create a copy of SnAccountApiKey
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountApiKeyCopyWith<SnAccountApiKey> get copyWith => _$SnAccountApiKeyCopyWithImpl<SnAccountApiKey>(this as SnAccountApiKey, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this SnAccountApiKey to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnAccountApiKey&&(identical(other.id, id) || other.id == id)&&(identical(other.label, label) || other.label == label)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.sessionId, sessionId) || other.sessionId == sessionId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.key, key) || other.key == key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,label,accountId,sessionId,createdAt,updatedAt,key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnAccountApiKey(id: $id, label: $label, accountId: $accountId, sessionId: $sessionId, createdAt: $createdAt, updatedAt: $updatedAt, key: $key)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $SnAccountApiKeyCopyWith<$Res> {
|
||||||
|
factory $SnAccountApiKeyCopyWith(SnAccountApiKey value, $Res Function(SnAccountApiKey) _then) = _$SnAccountApiKeyCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$SnAccountApiKeyCopyWithImpl<$Res>
|
||||||
|
implements $SnAccountApiKeyCopyWith<$Res> {
|
||||||
|
_$SnAccountApiKeyCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final SnAccountApiKey _self;
|
||||||
|
final $Res Function(SnAccountApiKey) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnAccountApiKey
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? label = null,Object? accountId = null,Object? sessionId = null,Object? createdAt = null,Object? updatedAt = null,Object? key = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,sessionId: null == sessionId ? _self.sessionId : sessionId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [SnAccountApiKey].
|
||||||
|
extension SnAccountApiKeyPatterns on SnAccountApiKey {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _SnAccountApiKey value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnAccountApiKey() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _SnAccountApiKey value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnAccountApiKey():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _SnAccountApiKey value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnAccountApiKey() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnAccountApiKey() when $default != null:
|
||||||
|
return $default(_that.id,_that.label,_that.accountId,_that.sessionId,_that.createdAt,_that.updatedAt,_that.key);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnAccountApiKey():
|
||||||
|
return $default(_that.id,_that.label,_that.accountId,_that.sessionId,_that.createdAt,_that.updatedAt,_that.key);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _SnAccountApiKey() when $default != null:
|
||||||
|
return $default(_that.id,_that.label,_that.accountId,_that.sessionId,_that.createdAt,_that.updatedAt,_that.key);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _SnAccountApiKey implements SnAccountApiKey {
|
||||||
|
const _SnAccountApiKey({required this.id, required this.label, required this.accountId, required this.sessionId, required this.createdAt, required this.updatedAt, this.key});
|
||||||
|
factory _SnAccountApiKey.fromJson(Map<String, dynamic> json) => _$SnAccountApiKeyFromJson(json);
|
||||||
|
|
||||||
|
@override final String id;
|
||||||
|
@override final String label;
|
||||||
|
@override final String accountId;
|
||||||
|
@override final String sessionId;
|
||||||
|
@override final DateTime createdAt;
|
||||||
|
@override final DateTime updatedAt;
|
||||||
|
@override final String? key;
|
||||||
|
|
||||||
|
/// Create a copy of SnAccountApiKey
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$SnAccountApiKeyCopyWith<_SnAccountApiKey> get copyWith => __$SnAccountApiKeyCopyWithImpl<_SnAccountApiKey>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$SnAccountApiKeyToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnAccountApiKey&&(identical(other.id, id) || other.id == id)&&(identical(other.label, label) || other.label == label)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.sessionId, sessionId) || other.sessionId == sessionId)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.key, key) || other.key == key));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,label,accountId,sessionId,createdAt,updatedAt,key);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'SnAccountApiKey(id: $id, label: $label, accountId: $accountId, sessionId: $sessionId, createdAt: $createdAt, updatedAt: $updatedAt, key: $key)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$SnAccountApiKeyCopyWith<$Res> implements $SnAccountApiKeyCopyWith<$Res> {
|
||||||
|
factory _$SnAccountApiKeyCopyWith(_SnAccountApiKey value, $Res Function(_SnAccountApiKey) _then) = __$SnAccountApiKeyCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String label, String accountId, String sessionId, DateTime createdAt, DateTime updatedAt, String? key
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$SnAccountApiKeyCopyWithImpl<$Res>
|
||||||
|
implements _$SnAccountApiKeyCopyWith<$Res> {
|
||||||
|
__$SnAccountApiKeyCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _SnAccountApiKey _self;
|
||||||
|
final $Res Function(_SnAccountApiKey) _then;
|
||||||
|
|
||||||
|
/// Create a copy of SnAccountApiKey
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? label = null,Object? accountId = null,Object? sessionId = null,Object? createdAt = null,Object? updatedAt = null,Object? key = freezed,}) {
|
||||||
|
return _then(_SnAccountApiKey(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,label: null == label ? _self.label : label // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,accountId: null == accountId ? _self.accountId : accountId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,sessionId: null == sessionId ? _self.sessionId : sessionId // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,updatedAt: null == updatedAt ? _self.updatedAt : updatedAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,key: freezed == key ? _self.key : key // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
29
lib/models/bot_key.g.dart
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'bot_key.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_SnAccountApiKey _$SnAccountApiKeyFromJson(Map<String, dynamic> json) =>
|
||||||
|
_SnAccountApiKey(
|
||||||
|
id: json['id'] as String,
|
||||||
|
label: json['label'] as String,
|
||||||
|
accountId: json['account_id'] as String,
|
||||||
|
sessionId: json['session_id'] as String,
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
updatedAt: DateTime.parse(json['updated_at'] as String),
|
||||||
|
key: json['key'] as String?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$SnAccountApiKeyToJson(_SnAccountApiKey instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'label': instance.label,
|
||||||
|
'account_id': instance.accountId,
|
||||||
|
'session_id': instance.sessionId,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'updated_at': instance.updatedAt.toIso8601String(),
|
||||||
|
'key': instance.key,
|
||||||
|
};
|
||||||
@@ -40,7 +40,7 @@ sealed class SnChatMessage with _$SnChatMessage {
|
|||||||
String? content,
|
String? content,
|
||||||
String? nonce,
|
String? nonce,
|
||||||
@Default({}) Map<String, dynamic> meta,
|
@Default({}) Map<String, dynamic> meta,
|
||||||
@Default([]) List<String> membersMetioned,
|
@Default([]) List<String> membersMentioned,
|
||||||
DateTime? editedAt,
|
DateTime? editedAt,
|
||||||
@Default([]) List<SnCloudFile> attachments,
|
@Default([]) List<SnCloudFile> attachments,
|
||||||
@Default([]) List<SnChatReaction> reactions,
|
@Default([]) List<SnChatReaction> reactions,
|
||||||
@@ -91,6 +91,7 @@ sealed class SnChatMember with _$SnChatMember {
|
|||||||
required DateTime? breakUntil,
|
required DateTime? breakUntil,
|
||||||
required DateTime? timeoutUntil,
|
required DateTime? timeoutUntil,
|
||||||
required bool isBot,
|
required bool isBot,
|
||||||
|
required SnAccountStatus? status,
|
||||||
// Frontend data
|
// Frontend data
|
||||||
DateTime? lastTyped,
|
DateTime? lastTyped,
|
||||||
}) = _SnChatMember;
|
}) = _SnChatMember;
|
||||||
@@ -103,7 +104,7 @@ sealed class SnChatMember with _$SnChatMember {
|
|||||||
sealed 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,
|
||||||
}) = _SnChatSummary;
|
}) = _SnChatSummary;
|
||||||
|
|
||||||
factory SnChatSummary.fromJson(Map<String, dynamic> json) =>
|
factory SnChatSummary.fromJson(Map<String, dynamic> json) =>
|
||||||
@@ -116,23 +117,10 @@ class MessageChangeAction {
|
|||||||
static const String delete = "delete";
|
static const String delete = "delete";
|
||||||
}
|
}
|
||||||
|
|
||||||
@freezed
|
|
||||||
sealed class MessageChange with _$MessageChange {
|
|
||||||
const factory MessageChange({
|
|
||||||
required String messageId,
|
|
||||||
required String action,
|
|
||||||
SnChatMessage? message,
|
|
||||||
required DateTime timestamp,
|
|
||||||
}) = _MessageChange;
|
|
||||||
|
|
||||||
factory MessageChange.fromJson(Map<String, dynamic> json) =>
|
|
||||||
_$MessageChangeFromJson(json);
|
|
||||||
}
|
|
||||||
|
|
||||||
@freezed
|
@freezed
|
||||||
sealed class MessageSyncResponse with _$MessageSyncResponse {
|
sealed class MessageSyncResponse with _$MessageSyncResponse {
|
||||||
const factory MessageSyncResponse({
|
const factory MessageSyncResponse({
|
||||||
@Default([]) List<MessageChange> changes,
|
@Default([]) List<SnChatMessage> messages,
|
||||||
required DateTime currentTimestamp,
|
required DateTime currentTimestamp,
|
||||||
}) = _MessageSyncResponse;
|
}) = _MessageSyncResponse;
|
||||||
|
|
||||||
|
|||||||
@@ -391,7 +391,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 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;
|
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 membersMentioned; 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)
|
||||||
@@ -404,16 +404,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.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));
|
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.membersMentioned, membersMentioned)&&(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,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);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,type,content,nonce,const DeepCollectionEquality().hash(meta),const DeepCollectionEquality().hash(membersMentioned),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, 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)';
|
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, type: $type, content: $content, nonce: $nonce, meta: $meta, membersMentioned: $membersMentioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -424,7 +424,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 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
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMentioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -441,7 +441,7 @@ 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? 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,}) {
|
@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? membersMentioned = 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
|
||||||
@@ -451,7 +451,7 @@ as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non
|
|||||||
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
|
||||||
as Map<String, dynamic>,membersMetioned: null == membersMetioned ? _self.membersMetioned : membersMetioned // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>,membersMentioned: null == membersMentioned ? _self.membersMentioned : membersMentioned // ignore: cast_nullable_to_non_nullable
|
||||||
as List<String>,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore: cast_nullable_to_non_nullable
|
as List<String>,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as DateTime?,attachments: null == attachments ? _self.attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,reactions: null == reactions ? _self.reactions : reactions // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -551,10 +551,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( 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)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMentioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMessage() when $default != null:
|
case _SnChatMessage() when $default != null:
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.type,_that.content,_that.nonce,_that.meta,_that.membersMetioned,_that.editedAt,_that.attachments,_that.reactions,_that.repliedMessageId,_that.forwardedMessageId,_that.senderId,_that.sender,_that.chatRoomId);case _:
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.type,_that.content,_that.nonce,_that.meta,_that.membersMentioned,_that.editedAt,_that.attachments,_that.reactions,_that.repliedMessageId,_that.forwardedMessageId,_that.senderId,_that.sender,_that.chatRoomId);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -572,10 +572,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.t
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( 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) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMentioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMessage():
|
case _SnChatMessage():
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.type,_that.content,_that.nonce,_that.meta,_that.membersMetioned,_that.editedAt,_that.attachments,_that.reactions,_that.repliedMessageId,_that.forwardedMessageId,_that.senderId,_that.sender,_that.chatRoomId);}
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.type,_that.content,_that.nonce,_that.meta,_that.membersMentioned,_that.editedAt,_that.attachments,_that.reactions,_that.repliedMessageId,_that.forwardedMessageId,_that.senderId,_that.sender,_that.chatRoomId);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -589,10 +589,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.t
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( 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)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMentioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMessage() when $default != null:
|
case _SnChatMessage() when $default != null:
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.type,_that.content,_that.nonce,_that.meta,_that.membersMetioned,_that.editedAt,_that.attachments,_that.reactions,_that.repliedMessageId,_that.forwardedMessageId,_that.senderId,_that.sender,_that.chatRoomId);case _:
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.type,_that.content,_that.nonce,_that.meta,_that.membersMentioned,_that.editedAt,_that.attachments,_that.reactions,_that.repliedMessageId,_that.forwardedMessageId,_that.senderId,_that.sender,_that.chatRoomId);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -604,7 +604,7 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.t
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _SnChatMessage implements SnChatMessage {
|
class _SnChatMessage implements SnChatMessage {
|
||||||
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;
|
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> membersMentioned = 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,_membersMentioned = membersMentioned,_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;
|
||||||
@@ -621,11 +621,11 @@ class _SnChatMessage implements SnChatMessage {
|
|||||||
return EqualUnmodifiableMapView(_meta);
|
return EqualUnmodifiableMapView(_meta);
|
||||||
}
|
}
|
||||||
|
|
||||||
final List<String> _membersMetioned;
|
final List<String> _membersMentioned;
|
||||||
@override@JsonKey() List<String> get membersMetioned {
|
@override@JsonKey() List<String> get membersMentioned {
|
||||||
if (_membersMetioned is EqualUnmodifiableListView) return _membersMetioned;
|
if (_membersMentioned is EqualUnmodifiableListView) return _membersMentioned;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_membersMetioned);
|
return EqualUnmodifiableListView(_membersMentioned);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override final DateTime? editedAt;
|
@override final DateTime? editedAt;
|
||||||
@@ -662,16 +662,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.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));
|
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._membersMentioned, _membersMentioned)&&(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,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);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,type,content,nonce,const DeepCollectionEquality().hash(_meta),const DeepCollectionEquality().hash(_membersMentioned),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, 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)';
|
return 'SnChatMessage(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, type: $type, content: $content, nonce: $nonce, meta: $meta, membersMentioned: $membersMentioned, editedAt: $editedAt, attachments: $attachments, reactions: $reactions, repliedMessageId: $repliedMessageId, forwardedMessageId: $forwardedMessageId, senderId: $senderId, sender: $sender, chatRoomId: $chatRoomId)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -682,7 +682,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 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
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String type, String? content, String? nonce, Map<String, dynamic> meta, List<String> membersMentioned, DateTime? editedAt, List<SnCloudFile> attachments, List<SnChatReaction> reactions, String? repliedMessageId, String? forwardedMessageId, String senderId, SnChatMember sender, String chatRoomId
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -699,7 +699,7 @@ 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? 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,}) {
|
@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? membersMentioned = 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
|
||||||
@@ -709,7 +709,7 @@ as String,type: null == type ? _self.type : type // ignore: cast_nullable_to_non
|
|||||||
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
|
||||||
as Map<String, dynamic>,membersMetioned: null == membersMetioned ? _self._membersMetioned : membersMetioned // ignore: cast_nullable_to_non_nullable
|
as Map<String, dynamic>,membersMentioned: null == membersMentioned ? _self._membersMentioned : membersMentioned // ignore: cast_nullable_to_non_nullable
|
||||||
as List<String>,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore: cast_nullable_to_non_nullable
|
as List<String>,editedAt: freezed == editedAt ? _self.editedAt : editedAt // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
as DateTime?,attachments: null == attachments ? _self._attachments : attachments // ignore: cast_nullable_to_non_nullable
|
||||||
as List<SnCloudFile>,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable
|
as List<SnCloudFile>,reactions: null == reactions ? _self._reactions : reactions // ignore: cast_nullable_to_non_nullable
|
||||||
@@ -1037,7 +1037,7 @@ $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; DateTime? get breakUntil; DateTime? get timeoutUntil; bool get isBot;// Frontend data
|
DateTime get createdAt; DateTime get updatedAt; DateTime? get deletedAt; String get id; String get chatRoomId; SnChatRoom? get chatRoom; String get accountId; SnAccount get account; String? get nick; int get role; int get notify; DateTime? get joinedAt; DateTime? get breakUntil; DateTime? get timeoutUntil; bool get isBot; SnAccountStatus? get status;// Frontend data
|
||||||
DateTime? get lastTyped;
|
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.
|
||||||
@@ -1051,16 +1051,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.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.status, status) || other.status == status)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@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,breakUntil,timeoutUntil,isBot,lastTyped);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,status,lastTyped);
|
||||||
|
|
||||||
@override
|
@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, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, lastTyped: $lastTyped)';
|
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, status: $status, lastTyped: $lastTyped)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1071,11 +1071,11 @@ abstract mixin class $SnChatMemberCopyWith<$Res> {
|
|||||||
factory $SnChatMemberCopyWith(SnChatMember value, $Res Function(SnChatMember) _then) = _$SnChatMemberCopyWithImpl;
|
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, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnChatRoomCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;
|
$SnChatRoomCopyWith<$Res>? get chatRoom;$SnAccountCopyWith<$Res> get account;$SnAccountStatusCopyWith<$Res>? get status;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1088,7 +1088,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? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? lastTyped = freezed,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? status = freezed,Object? lastTyped = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
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
|
||||||
@@ -1105,7 +1105,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
|||||||
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
as DateTime?,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?,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,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
as bool,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAccountStatus?,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -1130,6 +1131,18 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||||
return _then(_self.copyWith(account: value));
|
return _then(_self.copyWith(account: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnChatMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountStatusCopyWith<$Res>? get status {
|
||||||
|
if (_self.status == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1209,10 +1222,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMember() when $default != null:
|
case _SnChatMember() when $default != null:
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);case _:
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1230,10 +1243,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMember():
|
case _SnChatMember():
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);}
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -1247,10 +1260,10 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatMember() when $default != null:
|
case _SnChatMember() when $default != null:
|
||||||
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.lastTyped);case _:
|
return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.chatRoomId,_that.chatRoom,_that.accountId,_that.account,_that.nick,_that.role,_that.notify,_that.joinedAt,_that.breakUntil,_that.timeoutUntil,_that.isBot,_that.status,_that.lastTyped);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -1262,7 +1275,7 @@ return $default(_that.createdAt,_that.updatedAt,_that.deletedAt,_that.id,_that.c
|
|||||||
@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.breakUntil, required this.timeoutUntil, required this.isBot, this.lastTyped});
|
const _SnChatMember({required this.createdAt, required this.updatedAt, required this.deletedAt, required this.id, required this.chatRoomId, required this.chatRoom, required this.accountId, required this.account, required this.nick, required this.role, required this.notify, required this.joinedAt, required this.breakUntil, required this.timeoutUntil, required this.isBot, required this.status, this.lastTyped});
|
||||||
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
factory _SnChatMember.fromJson(Map<String, dynamic> json) => _$SnChatMemberFromJson(json);
|
||||||
|
|
||||||
@override final DateTime createdAt;
|
@override final DateTime createdAt;
|
||||||
@@ -1280,6 +1293,7 @@ class _SnChatMember implements SnChatMember {
|
|||||||
@override final DateTime? breakUntil;
|
@override final DateTime? breakUntil;
|
||||||
@override final DateTime? timeoutUntil;
|
@override final DateTime? timeoutUntil;
|
||||||
@override final bool isBot;
|
@override final bool isBot;
|
||||||
|
@override final SnAccountStatus? status;
|
||||||
// Frontend data
|
// Frontend data
|
||||||
@override final DateTime? lastTyped;
|
@override final DateTime? lastTyped;
|
||||||
|
|
||||||
@@ -1296,16 +1310,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.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _SnChatMember&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.updatedAt, updatedAt) || other.updatedAt == updatedAt)&&(identical(other.deletedAt, deletedAt) || other.deletedAt == deletedAt)&&(identical(other.id, id) || other.id == id)&&(identical(other.chatRoomId, chatRoomId) || other.chatRoomId == chatRoomId)&&(identical(other.chatRoom, chatRoom) || other.chatRoom == chatRoom)&&(identical(other.accountId, accountId) || other.accountId == accountId)&&(identical(other.account, account) || other.account == account)&&(identical(other.nick, nick) || other.nick == nick)&&(identical(other.role, role) || other.role == role)&&(identical(other.notify, notify) || other.notify == notify)&&(identical(other.joinedAt, joinedAt) || other.joinedAt == joinedAt)&&(identical(other.breakUntil, breakUntil) || other.breakUntil == breakUntil)&&(identical(other.timeoutUntil, timeoutUntil) || other.timeoutUntil == timeoutUntil)&&(identical(other.isBot, isBot) || other.isBot == isBot)&&(identical(other.status, status) || other.status == status)&&(identical(other.lastTyped, lastTyped) || other.lastTyped == lastTyped));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@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,breakUntil,timeoutUntil,isBot,lastTyped);
|
int get hashCode => Object.hash(runtimeType,createdAt,updatedAt,deletedAt,id,chatRoomId,chatRoom,accountId,account,nick,role,notify,joinedAt,breakUntil,timeoutUntil,isBot,status,lastTyped);
|
||||||
|
|
||||||
@override
|
@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, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, lastTyped: $lastTyped)';
|
return 'SnChatMember(createdAt: $createdAt, updatedAt: $updatedAt, deletedAt: $deletedAt, id: $id, chatRoomId: $chatRoomId, chatRoom: $chatRoom, accountId: $accountId, account: $account, nick: $nick, role: $role, notify: $notify, joinedAt: $joinedAt, breakUntil: $breakUntil, timeoutUntil: $timeoutUntil, isBot: $isBot, status: $status, lastTyped: $lastTyped)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1316,11 +1330,11 @@ abstract mixin class _$SnChatMemberCopyWith<$Res> implements $SnChatMemberCopyWi
|
|||||||
factory _$SnChatMemberCopyWith(_SnChatMember value, $Res Function(_SnChatMember) _then) = __$SnChatMemberCopyWithImpl;
|
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, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, DateTime? lastTyped
|
DateTime createdAt, DateTime updatedAt, DateTime? deletedAt, String id, String chatRoomId, SnChatRoom? chatRoom, String accountId, SnAccount account, String? nick, int role, int notify, DateTime? joinedAt, DateTime? breakUntil, DateTime? timeoutUntil, bool isBot, SnAccountStatus? status, DateTime? lastTyped
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnChatRoomCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;
|
@override $SnChatRoomCopyWith<$Res>? get chatRoom;@override $SnAccountCopyWith<$Res> get account;@override $SnAccountStatusCopyWith<$Res>? get status;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1333,7 +1347,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? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? lastTyped = freezed,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? createdAt = null,Object? updatedAt = null,Object? deletedAt = freezed,Object? id = null,Object? chatRoomId = null,Object? chatRoom = freezed,Object? accountId = null,Object? account = null,Object? nick = freezed,Object? role = null,Object? notify = null,Object? joinedAt = freezed,Object? breakUntil = freezed,Object? timeoutUntil = freezed,Object? isBot = null,Object? status = freezed,Object? lastTyped = freezed,}) {
|
||||||
return _then(_SnChatMember(
|
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
|
||||||
@@ -1350,7 +1364,8 @@ as int,joinedAt: freezed == joinedAt ? _self.joinedAt : joinedAt // ignore: cast
|
|||||||
as DateTime?,breakUntil: freezed == breakUntil ? _self.breakUntil : breakUntil // ignore: cast_nullable_to_non_nullable
|
as DateTime?,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?,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,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
as bool,status: freezed == status ? _self.status : status // ignore: cast_nullable_to_non_nullable
|
||||||
|
as SnAccountStatus?,lastTyped: freezed == lastTyped ? _self.lastTyped : lastTyped // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime?,
|
as DateTime?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -1376,6 +1391,18 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
return $SnAccountCopyWith<$Res>(_self.account, (value) {
|
||||||
return _then(_self.copyWith(account: value));
|
return _then(_self.copyWith(account: value));
|
||||||
});
|
});
|
||||||
|
}/// Create a copy of SnChatMember
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$SnAccountStatusCopyWith<$Res>? get status {
|
||||||
|
if (_self.status == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $SnAccountStatusCopyWith<$Res>(_self.status!, (value) {
|
||||||
|
return _then(_self.copyWith(status: value));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1383,7 +1410,7 @@ $SnAccountCopyWith<$Res> get account {
|
|||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$SnChatSummary {
|
mixin _$SnChatSummary {
|
||||||
|
|
||||||
int get unreadCount; SnChatMessage get lastMessage;
|
int get unreadCount; SnChatMessage? get lastMessage;
|
||||||
/// Create a copy of SnChatSummary
|
/// Create a copy of SnChatSummary
|
||||||
/// 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)
|
||||||
@@ -1416,11 +1443,11 @@ abstract mixin class $SnChatSummaryCopyWith<$Res> {
|
|||||||
factory $SnChatSummaryCopyWith(SnChatSummary value, $Res Function(SnChatSummary) _then) = _$SnChatSummaryCopyWithImpl;
|
factory $SnChatSummaryCopyWith(SnChatSummary value, $Res Function(SnChatSummary) _then) = _$SnChatSummaryCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
int unreadCount, SnChatMessage lastMessage
|
int unreadCount, SnChatMessage? lastMessage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
$SnChatMessageCopyWith<$Res> get lastMessage;
|
$SnChatMessageCopyWith<$Res>? get lastMessage;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1433,20 +1460,23 @@ class _$SnChatSummaryCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatSummary
|
/// Create a copy of SnChatSummary
|
||||||
/// 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? unreadCount = null,Object? lastMessage = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? unreadCount = null,Object? lastMessage = freezed,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
unreadCount: null == unreadCount ? _self.unreadCount : unreadCount // ignore: cast_nullable_to_non_nullable
|
unreadCount: null == unreadCount ? _self.unreadCount : unreadCount // ignore: cast_nullable_to_non_nullable
|
||||||
as int,lastMessage: null == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
as int,lastMessage: freezed == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
||||||
as SnChatMessage,
|
as SnChatMessage?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
/// Create a copy of SnChatSummary
|
/// Create a copy of SnChatSummary
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
$SnChatMessageCopyWith<$Res> get lastMessage {
|
$SnChatMessageCopyWith<$Res>? get lastMessage {
|
||||||
|
if (_self.lastMessage == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage, (value) {
|
return $SnChatMessageCopyWith<$Res>(_self.lastMessage!, (value) {
|
||||||
return _then(_self.copyWith(lastMessage: value));
|
return _then(_self.copyWith(lastMessage: value));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -1528,7 +1558,7 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage lastMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage? lastMessage)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatSummary() when $default != null:
|
case _SnChatSummary() when $default != null:
|
||||||
return $default(_that.unreadCount,_that.lastMessage);case _:
|
return $default(_that.unreadCount,_that.lastMessage);case _:
|
||||||
@@ -1549,7 +1579,7 @@ return $default(_that.unreadCount,_that.lastMessage);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage lastMessage) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( int unreadCount, SnChatMessage? lastMessage) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatSummary():
|
case _SnChatSummary():
|
||||||
return $default(_that.unreadCount,_that.lastMessage);}
|
return $default(_that.unreadCount,_that.lastMessage);}
|
||||||
@@ -1566,7 +1596,7 @@ return $default(_that.unreadCount,_that.lastMessage);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int unreadCount, SnChatMessage lastMessage)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( int unreadCount, SnChatMessage? lastMessage)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _SnChatSummary() when $default != null:
|
case _SnChatSummary() when $default != null:
|
||||||
return $default(_that.unreadCount,_that.lastMessage);case _:
|
return $default(_that.unreadCount,_that.lastMessage);case _:
|
||||||
@@ -1585,7 +1615,7 @@ class _SnChatSummary implements SnChatSummary {
|
|||||||
factory _SnChatSummary.fromJson(Map<String, dynamic> json) => _$SnChatSummaryFromJson(json);
|
factory _SnChatSummary.fromJson(Map<String, dynamic> json) => _$SnChatSummaryFromJson(json);
|
||||||
|
|
||||||
@override final int unreadCount;
|
@override final int unreadCount;
|
||||||
@override final SnChatMessage lastMessage;
|
@override final SnChatMessage? lastMessage;
|
||||||
|
|
||||||
/// Create a copy of SnChatSummary
|
/// Create a copy of SnChatSummary
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@@ -1620,11 +1650,11 @@ abstract mixin class _$SnChatSummaryCopyWith<$Res> implements $SnChatSummaryCopy
|
|||||||
factory _$SnChatSummaryCopyWith(_SnChatSummary value, $Res Function(_SnChatSummary) _then) = __$SnChatSummaryCopyWithImpl;
|
factory _$SnChatSummaryCopyWith(_SnChatSummary value, $Res Function(_SnChatSummary) _then) = __$SnChatSummaryCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
int unreadCount, SnChatMessage lastMessage
|
int unreadCount, SnChatMessage? lastMessage
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@override $SnChatMessageCopyWith<$Res> get lastMessage;
|
@override $SnChatMessageCopyWith<$Res>? get lastMessage;
|
||||||
|
|
||||||
}
|
}
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
@@ -1637,11 +1667,11 @@ class __$SnChatSummaryCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of SnChatSummary
|
/// Create a copy of SnChatSummary
|
||||||
/// 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? unreadCount = null,Object? lastMessage = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? unreadCount = null,Object? lastMessage = freezed,}) {
|
||||||
return _then(_SnChatSummary(
|
return _then(_SnChatSummary(
|
||||||
unreadCount: null == unreadCount ? _self.unreadCount : unreadCount // ignore: cast_nullable_to_non_nullable
|
unreadCount: null == unreadCount ? _self.unreadCount : unreadCount // ignore: cast_nullable_to_non_nullable
|
||||||
as int,lastMessage: null == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
as int,lastMessage: freezed == lastMessage ? _self.lastMessage : lastMessage // ignore: cast_nullable_to_non_nullable
|
||||||
as SnChatMessage,
|
as SnChatMessage?,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1649,309 +1679,22 @@ as SnChatMessage,
|
|||||||
/// with the given fields replaced by the non-null parameter values.
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
@override
|
@override
|
||||||
@pragma('vm:prefer-inline')
|
@pragma('vm:prefer-inline')
|
||||||
$SnChatMessageCopyWith<$Res> get lastMessage {
|
$SnChatMessageCopyWith<$Res>? get lastMessage {
|
||||||
|
if (_self.lastMessage == null) {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
return $SnChatMessageCopyWith<$Res>(_self.lastMessage, (value) {
|
return $SnChatMessageCopyWith<$Res>(_self.lastMessage!, (value) {
|
||||||
return _then(_self.copyWith(lastMessage: value));
|
return _then(_self.copyWith(lastMessage: value));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
mixin _$MessageChange {
|
|
||||||
|
|
||||||
String get messageId; String get action; SnChatMessage? get message; DateTime get timestamp;
|
|
||||||
/// Create a copy of MessageChange
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$MessageChangeCopyWith<MessageChange> get copyWith => _$MessageChangeCopyWithImpl<MessageChange>(this as MessageChange, _$identity);
|
|
||||||
|
|
||||||
/// Serializes this MessageChange to a JSON map.
|
|
||||||
Map<String, dynamic> toJson();
|
|
||||||
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is MessageChange&&(identical(other.messageId, messageId) || other.messageId == messageId)&&(identical(other.action, action) || other.action == action)&&(identical(other.message, message) || other.message == message)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,messageId,action,message,timestamp);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'MessageChange(messageId: $messageId, action: $action, message: $message, timestamp: $timestamp)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class $MessageChangeCopyWith<$Res> {
|
|
||||||
factory $MessageChangeCopyWith(MessageChange value, $Res Function(MessageChange) _then) = _$MessageChangeCopyWithImpl;
|
|
||||||
@useResult
|
|
||||||
$Res call({
|
|
||||||
String messageId, String action, SnChatMessage? message, DateTime timestamp
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
$SnChatMessageCopyWith<$Res>? get message;
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class _$MessageChangeCopyWithImpl<$Res>
|
|
||||||
implements $MessageChangeCopyWith<$Res> {
|
|
||||||
_$MessageChangeCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final MessageChange _self;
|
|
||||||
final $Res Function(MessageChange) _then;
|
|
||||||
|
|
||||||
/// Create a copy of MessageChange
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@pragma('vm:prefer-inline') @override $Res call({Object? messageId = null,Object? action = null,Object? message = freezed,Object? timestamp = null,}) {
|
|
||||||
return _then(_self.copyWith(
|
|
||||||
messageId: null == messageId ? _self.messageId : messageId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,action: null == action ? _self.action : action // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnChatMessage?,timestamp: null == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
/// Create a copy of MessageChange
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnChatMessageCopyWith<$Res>? get message {
|
|
||||||
if (_self.message == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $SnChatMessageCopyWith<$Res>(_self.message!, (value) {
|
|
||||||
return _then(_self.copyWith(message: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// Adds pattern-matching-related methods to [MessageChange].
|
|
||||||
extension MessageChangePatterns on MessageChange {
|
|
||||||
/// A variant of `map` that fallback to returning `orElse`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _MessageChange value)? $default,{required TResult orElse(),}){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _MessageChange() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// Callbacks receives the raw object, upcasted.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case final Subclass2 value:
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _MessageChange value) $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _MessageChange():
|
|
||||||
return $default(_that);}
|
|
||||||
}
|
|
||||||
/// A variant of `map` that fallback to returning `null`.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case final Subclass value:
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _MessageChange value)? $default,){
|
|
||||||
final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _MessageChange() when $default != null:
|
|
||||||
return $default(_that);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to an `orElse` callback.
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return orElse();
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String messageId, String action, SnChatMessage? message, DateTime timestamp)? $default,{required TResult orElse(),}) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _MessageChange() when $default != null:
|
|
||||||
return $default(_that.messageId,_that.action,_that.message,_that.timestamp);case _:
|
|
||||||
return orElse();
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/// A `switch`-like method, using callbacks.
|
|
||||||
///
|
|
||||||
/// As opposed to `map`, this offers destructuring.
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case Subclass2(:final field2):
|
|
||||||
/// return ...;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String messageId, String action, SnChatMessage? message, DateTime timestamp) $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _MessageChange():
|
|
||||||
return $default(_that.messageId,_that.action,_that.message,_that.timestamp);}
|
|
||||||
}
|
|
||||||
/// A variant of `when` that fallback to returning `null`
|
|
||||||
///
|
|
||||||
/// It is equivalent to doing:
|
|
||||||
/// ```dart
|
|
||||||
/// switch (sealedClass) {
|
|
||||||
/// case Subclass(:final field):
|
|
||||||
/// return ...;
|
|
||||||
/// case _:
|
|
||||||
/// return null;
|
|
||||||
/// }
|
|
||||||
/// ```
|
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String messageId, String action, SnChatMessage? message, DateTime timestamp)? $default,) {final _that = this;
|
|
||||||
switch (_that) {
|
|
||||||
case _MessageChange() when $default != null:
|
|
||||||
return $default(_that.messageId,_that.action,_that.message,_that.timestamp);case _:
|
|
||||||
return null;
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
@JsonSerializable()
|
|
||||||
|
|
||||||
class _MessageChange implements MessageChange {
|
|
||||||
const _MessageChange({required this.messageId, required this.action, this.message, required this.timestamp});
|
|
||||||
factory _MessageChange.fromJson(Map<String, dynamic> json) => _$MessageChangeFromJson(json);
|
|
||||||
|
|
||||||
@override final String messageId;
|
|
||||||
@override final String action;
|
|
||||||
@override final SnChatMessage? message;
|
|
||||||
@override final DateTime timestamp;
|
|
||||||
|
|
||||||
/// Create a copy of MessageChange
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
_$MessageChangeCopyWith<_MessageChange> get copyWith => __$MessageChangeCopyWithImpl<_MessageChange>(this, _$identity);
|
|
||||||
|
|
||||||
@override
|
|
||||||
Map<String, dynamic> toJson() {
|
|
||||||
return _$MessageChangeToJson(this, );
|
|
||||||
}
|
|
||||||
|
|
||||||
@override
|
|
||||||
bool operator ==(Object other) {
|
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _MessageChange&&(identical(other.messageId, messageId) || other.messageId == messageId)&&(identical(other.action, action) || other.action == action)&&(identical(other.message, message) || other.message == message)&&(identical(other.timestamp, timestamp) || other.timestamp == timestamp));
|
|
||||||
}
|
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
|
||||||
@override
|
|
||||||
int get hashCode => Object.hash(runtimeType,messageId,action,message,timestamp);
|
|
||||||
|
|
||||||
@override
|
|
||||||
String toString() {
|
|
||||||
return 'MessageChange(messageId: $messageId, action: $action, message: $message, timestamp: $timestamp)';
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
/// @nodoc
|
|
||||||
abstract mixin class _$MessageChangeCopyWith<$Res> implements $MessageChangeCopyWith<$Res> {
|
|
||||||
factory _$MessageChangeCopyWith(_MessageChange value, $Res Function(_MessageChange) _then) = __$MessageChangeCopyWithImpl;
|
|
||||||
@override @useResult
|
|
||||||
$Res call({
|
|
||||||
String messageId, String action, SnChatMessage? message, DateTime timestamp
|
|
||||||
});
|
|
||||||
|
|
||||||
|
|
||||||
@override $SnChatMessageCopyWith<$Res>? get message;
|
|
||||||
|
|
||||||
}
|
|
||||||
/// @nodoc
|
|
||||||
class __$MessageChangeCopyWithImpl<$Res>
|
|
||||||
implements _$MessageChangeCopyWith<$Res> {
|
|
||||||
__$MessageChangeCopyWithImpl(this._self, this._then);
|
|
||||||
|
|
||||||
final _MessageChange _self;
|
|
||||||
final $Res Function(_MessageChange) _then;
|
|
||||||
|
|
||||||
/// Create a copy of MessageChange
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override @pragma('vm:prefer-inline') $Res call({Object? messageId = null,Object? action = null,Object? message = freezed,Object? timestamp = null,}) {
|
|
||||||
return _then(_MessageChange(
|
|
||||||
messageId: null == messageId ? _self.messageId : messageId // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,action: null == action ? _self.action : action // ignore: cast_nullable_to_non_nullable
|
|
||||||
as String,message: freezed == message ? _self.message : message // ignore: cast_nullable_to_non_nullable
|
|
||||||
as SnChatMessage?,timestamp: null == timestamp ? _self.timestamp : timestamp // ignore: cast_nullable_to_non_nullable
|
|
||||||
as DateTime,
|
|
||||||
));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Create a copy of MessageChange
|
|
||||||
/// with the given fields replaced by the non-null parameter values.
|
|
||||||
@override
|
|
||||||
@pragma('vm:prefer-inline')
|
|
||||||
$SnChatMessageCopyWith<$Res>? get message {
|
|
||||||
if (_self.message == null) {
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
return $SnChatMessageCopyWith<$Res>(_self.message!, (value) {
|
|
||||||
return _then(_self.copyWith(message: value));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/// @nodoc
|
/// @nodoc
|
||||||
mixin _$MessageSyncResponse {
|
mixin _$MessageSyncResponse {
|
||||||
|
|
||||||
List<MessageChange> get changes; DateTime get currentTimestamp;
|
List<SnChatMessage> get messages; DateTime get currentTimestamp;
|
||||||
/// Create a copy of MessageSyncResponse
|
/// Create a copy of MessageSyncResponse
|
||||||
/// 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)
|
||||||
@@ -1964,16 +1707,16 @@ $MessageSyncResponseCopyWith<MessageSyncResponse> get copyWith => _$MessageSyncR
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is MessageSyncResponse&&const DeepCollectionEquality().equals(other.changes, changes)&&(identical(other.currentTimestamp, currentTimestamp) || other.currentTimestamp == currentTimestamp));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is MessageSyncResponse&&const DeepCollectionEquality().equals(other.messages, messages)&&(identical(other.currentTimestamp, currentTimestamp) || other.currentTimestamp == currentTimestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(changes),currentTimestamp);
|
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(messages),currentTimestamp);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'MessageSyncResponse(changes: $changes, currentTimestamp: $currentTimestamp)';
|
return 'MessageSyncResponse(messages: $messages, currentTimestamp: $currentTimestamp)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1984,7 +1727,7 @@ abstract mixin class $MessageSyncResponseCopyWith<$Res> {
|
|||||||
factory $MessageSyncResponseCopyWith(MessageSyncResponse value, $Res Function(MessageSyncResponse) _then) = _$MessageSyncResponseCopyWithImpl;
|
factory $MessageSyncResponseCopyWith(MessageSyncResponse value, $Res Function(MessageSyncResponse) _then) = _$MessageSyncResponseCopyWithImpl;
|
||||||
@useResult
|
@useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
List<MessageChange> changes, DateTime currentTimestamp
|
List<SnChatMessage> messages, DateTime currentTimestamp
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -2001,10 +1744,10 @@ class _$MessageSyncResponseCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of MessageSyncResponse
|
/// Create a copy of MessageSyncResponse
|
||||||
/// 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? changes = null,Object? currentTimestamp = null,}) {
|
@pragma('vm:prefer-inline') @override $Res call({Object? messages = null,Object? currentTimestamp = null,}) {
|
||||||
return _then(_self.copyWith(
|
return _then(_self.copyWith(
|
||||||
changes: null == changes ? _self.changes : changes // ignore: cast_nullable_to_non_nullable
|
messages: null == messages ? _self.messages : messages // ignore: cast_nullable_to_non_nullable
|
||||||
as List<MessageChange>,currentTimestamp: null == currentTimestamp ? _self.currentTimestamp : currentTimestamp // ignore: cast_nullable_to_non_nullable
|
as List<SnChatMessage>,currentTimestamp: null == currentTimestamp ? _self.currentTimestamp : currentTimestamp // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,
|
as DateTime,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
@@ -2087,10 +1830,10 @@ return $default(_that);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<MessageChange> changes, DateTime currentTimestamp)? $default,{required TResult orElse(),}) {final _that = this;
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( List<SnChatMessage> messages, DateTime currentTimestamp)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _MessageSyncResponse() when $default != null:
|
case _MessageSyncResponse() when $default != null:
|
||||||
return $default(_that.changes,_that.currentTimestamp);case _:
|
return $default(_that.messages,_that.currentTimestamp);case _:
|
||||||
return orElse();
|
return orElse();
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2108,10 +1851,10 @@ return $default(_that.changes,_that.currentTimestamp);case _:
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<MessageChange> changes, DateTime currentTimestamp) $default,) {final _that = this;
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( List<SnChatMessage> messages, DateTime currentTimestamp) $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _MessageSyncResponse():
|
case _MessageSyncResponse():
|
||||||
return $default(_that.changes,_that.currentTimestamp);}
|
return $default(_that.messages,_that.currentTimestamp);}
|
||||||
}
|
}
|
||||||
/// A variant of `when` that fallback to returning `null`
|
/// A variant of `when` that fallback to returning `null`
|
||||||
///
|
///
|
||||||
@@ -2125,10 +1868,10 @@ return $default(_that.changes,_that.currentTimestamp);}
|
|||||||
/// }
|
/// }
|
||||||
/// ```
|
/// ```
|
||||||
|
|
||||||
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<MessageChange> changes, DateTime currentTimestamp)? $default,) {final _that = this;
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( List<SnChatMessage> messages, DateTime currentTimestamp)? $default,) {final _that = this;
|
||||||
switch (_that) {
|
switch (_that) {
|
||||||
case _MessageSyncResponse() when $default != null:
|
case _MessageSyncResponse() when $default != null:
|
||||||
return $default(_that.changes,_that.currentTimestamp);case _:
|
return $default(_that.messages,_that.currentTimestamp);case _:
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2140,14 +1883,14 @@ return $default(_that.changes,_that.currentTimestamp);case _:
|
|||||||
@JsonSerializable()
|
@JsonSerializable()
|
||||||
|
|
||||||
class _MessageSyncResponse implements MessageSyncResponse {
|
class _MessageSyncResponse implements MessageSyncResponse {
|
||||||
const _MessageSyncResponse({final List<MessageChange> changes = const [], required this.currentTimestamp}): _changes = changes;
|
const _MessageSyncResponse({final List<SnChatMessage> messages = const [], required this.currentTimestamp}): _messages = messages;
|
||||||
factory _MessageSyncResponse.fromJson(Map<String, dynamic> json) => _$MessageSyncResponseFromJson(json);
|
factory _MessageSyncResponse.fromJson(Map<String, dynamic> json) => _$MessageSyncResponseFromJson(json);
|
||||||
|
|
||||||
final List<MessageChange> _changes;
|
final List<SnChatMessage> _messages;
|
||||||
@override@JsonKey() List<MessageChange> get changes {
|
@override@JsonKey() List<SnChatMessage> get messages {
|
||||||
if (_changes is EqualUnmodifiableListView) return _changes;
|
if (_messages is EqualUnmodifiableListView) return _messages;
|
||||||
// ignore: implicit_dynamic_type
|
// ignore: implicit_dynamic_type
|
||||||
return EqualUnmodifiableListView(_changes);
|
return EqualUnmodifiableListView(_messages);
|
||||||
}
|
}
|
||||||
|
|
||||||
@override final DateTime currentTimestamp;
|
@override final DateTime currentTimestamp;
|
||||||
@@ -2165,16 +1908,16 @@ Map<String, dynamic> toJson() {
|
|||||||
|
|
||||||
@override
|
@override
|
||||||
bool operator ==(Object other) {
|
bool operator ==(Object other) {
|
||||||
return identical(this, other) || (other.runtimeType == runtimeType&&other is _MessageSyncResponse&&const DeepCollectionEquality().equals(other._changes, _changes)&&(identical(other.currentTimestamp, currentTimestamp) || other.currentTimestamp == currentTimestamp));
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _MessageSyncResponse&&const DeepCollectionEquality().equals(other._messages, _messages)&&(identical(other.currentTimestamp, currentTimestamp) || other.currentTimestamp == currentTimestamp));
|
||||||
}
|
}
|
||||||
|
|
||||||
@JsonKey(includeFromJson: false, includeToJson: false)
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
@override
|
@override
|
||||||
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_changes),currentTimestamp);
|
int get hashCode => Object.hash(runtimeType,const DeepCollectionEquality().hash(_messages),currentTimestamp);
|
||||||
|
|
||||||
@override
|
@override
|
||||||
String toString() {
|
String toString() {
|
||||||
return 'MessageSyncResponse(changes: $changes, currentTimestamp: $currentTimestamp)';
|
return 'MessageSyncResponse(messages: $messages, currentTimestamp: $currentTimestamp)';
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -2185,7 +1928,7 @@ abstract mixin class _$MessageSyncResponseCopyWith<$Res> implements $MessageSync
|
|||||||
factory _$MessageSyncResponseCopyWith(_MessageSyncResponse value, $Res Function(_MessageSyncResponse) _then) = __$MessageSyncResponseCopyWithImpl;
|
factory _$MessageSyncResponseCopyWith(_MessageSyncResponse value, $Res Function(_MessageSyncResponse) _then) = __$MessageSyncResponseCopyWithImpl;
|
||||||
@override @useResult
|
@override @useResult
|
||||||
$Res call({
|
$Res call({
|
||||||
List<MessageChange> changes, DateTime currentTimestamp
|
List<SnChatMessage> messages, DateTime currentTimestamp
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
@@ -2202,10 +1945,10 @@ class __$MessageSyncResponseCopyWithImpl<$Res>
|
|||||||
|
|
||||||
/// Create a copy of MessageSyncResponse
|
/// Create a copy of MessageSyncResponse
|
||||||
/// 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? changes = null,Object? currentTimestamp = null,}) {
|
@override @pragma('vm:prefer-inline') $Res call({Object? messages = null,Object? currentTimestamp = null,}) {
|
||||||
return _then(_MessageSyncResponse(
|
return _then(_MessageSyncResponse(
|
||||||
changes: null == changes ? _self._changes : changes // ignore: cast_nullable_to_non_nullable
|
messages: null == messages ? _self._messages : messages // ignore: cast_nullable_to_non_nullable
|
||||||
as List<MessageChange>,currentTimestamp: null == currentTimestamp ? _self.currentTimestamp : currentTimestamp // ignore: cast_nullable_to_non_nullable
|
as List<SnChatMessage>,currentTimestamp: null == currentTimestamp ? _self.currentTimestamp : currentTimestamp // ignore: cast_nullable_to_non_nullable
|
||||||
as DateTime,
|
as DateTime,
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -69,8 +69,8 @@ _SnChatMessage _$SnChatMessageFromJson(Map<String, dynamic> json) =>
|
|||||||
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 {},
|
||||||
membersMetioned:
|
membersMentioned:
|
||||||
(json['members_metioned'] as List<dynamic>?)
|
(json['members_mentioned'] as List<dynamic>?)
|
||||||
?.map((e) => e as String)
|
?.map((e) => e as String)
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
@@ -105,7 +105,7 @@ Map<String, dynamic> _$SnChatMessageToJson(_SnChatMessage instance) =>
|
|||||||
'content': instance.content,
|
'content': instance.content,
|
||||||
'nonce': instance.nonce,
|
'nonce': instance.nonce,
|
||||||
'meta': instance.meta,
|
'meta': instance.meta,
|
||||||
'members_metioned': instance.membersMetioned,
|
'members_mentioned': instance.membersMentioned,
|
||||||
'edited_at': instance.editedAt?.toIso8601String(),
|
'edited_at': instance.editedAt?.toIso8601String(),
|
||||||
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
'attachments': instance.attachments.map((e) => e.toJson()).toList(),
|
||||||
'reactions': instance.reactions.map((e) => e.toJson()).toList(),
|
'reactions': instance.reactions.map((e) => e.toJson()).toList(),
|
||||||
@@ -177,6 +177,12 @@ _SnChatMember _$SnChatMemberFromJson(Map<String, dynamic> json) =>
|
|||||||
? null
|
? null
|
||||||
: DateTime.parse(json['timeout_until'] as String),
|
: DateTime.parse(json['timeout_until'] as String),
|
||||||
isBot: json['is_bot'] as bool,
|
isBot: json['is_bot'] as bool,
|
||||||
|
status:
|
||||||
|
json['status'] == null
|
||||||
|
? null
|
||||||
|
: SnAccountStatus.fromJson(
|
||||||
|
json['status'] as Map<String, dynamic>,
|
||||||
|
),
|
||||||
lastTyped:
|
lastTyped:
|
||||||
json['last_typed'] == null
|
json['last_typed'] == null
|
||||||
? null
|
? null
|
||||||
@@ -200,13 +206,17 @@ Map<String, dynamic> _$SnChatMemberToJson(_SnChatMember instance) =>
|
|||||||
'break_until': instance.breakUntil?.toIso8601String(),
|
'break_until': instance.breakUntil?.toIso8601String(),
|
||||||
'timeout_until': instance.timeoutUntil?.toIso8601String(),
|
'timeout_until': instance.timeoutUntil?.toIso8601String(),
|
||||||
'is_bot': instance.isBot,
|
'is_bot': instance.isBot,
|
||||||
|
'status': instance.status?.toJson(),
|
||||||
'last_typed': instance.lastTyped?.toIso8601String(),
|
'last_typed': instance.lastTyped?.toIso8601String(),
|
||||||
};
|
};
|
||||||
|
|
||||||
_SnChatSummary _$SnChatSummaryFromJson(Map<String, dynamic> json) =>
|
_SnChatSummary _$SnChatSummaryFromJson(Map<String, dynamic> json) =>
|
||||||
_SnChatSummary(
|
_SnChatSummary(
|
||||||
unreadCount: (json['unread_count'] as num).toInt(),
|
unreadCount: (json['unread_count'] as num).toInt(),
|
||||||
lastMessage: SnChatMessage.fromJson(
|
lastMessage:
|
||||||
|
json['last_message'] == null
|
||||||
|
? null
|
||||||
|
: SnChatMessage.fromJson(
|
||||||
json['last_message'] as Map<String, dynamic>,
|
json['last_message'] as Map<String, dynamic>,
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
@@ -214,33 +224,14 @@ _SnChatSummary _$SnChatSummaryFromJson(Map<String, dynamic> json) =>
|
|||||||
Map<String, dynamic> _$SnChatSummaryToJson(_SnChatSummary instance) =>
|
Map<String, dynamic> _$SnChatSummaryToJson(_SnChatSummary instance) =>
|
||||||
<String, dynamic>{
|
<String, dynamic>{
|
||||||
'unread_count': instance.unreadCount,
|
'unread_count': instance.unreadCount,
|
||||||
'last_message': instance.lastMessage.toJson(),
|
'last_message': instance.lastMessage?.toJson(),
|
||||||
};
|
|
||||||
|
|
||||||
_MessageChange _$MessageChangeFromJson(Map<String, dynamic> json) =>
|
|
||||||
_MessageChange(
|
|
||||||
messageId: json['message_id'] as String,
|
|
||||||
action: json['action'] as String,
|
|
||||||
message:
|
|
||||||
json['message'] == null
|
|
||||||
? null
|
|
||||||
: SnChatMessage.fromJson(json['message'] as Map<String, dynamic>),
|
|
||||||
timestamp: DateTime.parse(json['timestamp'] as String),
|
|
||||||
);
|
|
||||||
|
|
||||||
Map<String, dynamic> _$MessageChangeToJson(_MessageChange instance) =>
|
|
||||||
<String, dynamic>{
|
|
||||||
'message_id': instance.messageId,
|
|
||||||
'action': instance.action,
|
|
||||||
'message': instance.message?.toJson(),
|
|
||||||
'timestamp': instance.timestamp.toIso8601String(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
_MessageSyncResponse _$MessageSyncResponseFromJson(Map<String, dynamic> json) =>
|
_MessageSyncResponse _$MessageSyncResponseFromJson(Map<String, dynamic> json) =>
|
||||||
_MessageSyncResponse(
|
_MessageSyncResponse(
|
||||||
changes:
|
messages:
|
||||||
(json['changes'] as List<dynamic>?)
|
(json['messages'] as List<dynamic>?)
|
||||||
?.map((e) => MessageChange.fromJson(e as Map<String, dynamic>))
|
?.map((e) => SnChatMessage.fromJson(e as Map<String, dynamic>))
|
||||||
.toList() ??
|
.toList() ??
|
||||||
const [],
|
const [],
|
||||||
currentTimestamp: DateTime.parse(json['current_timestamp'] as String),
|
currentTimestamp: DateTime.parse(json['current_timestamp'] as String),
|
||||||
@@ -249,7 +240,7 @@ _MessageSyncResponse _$MessageSyncResponseFromJson(Map<String, dynamic> json) =>
|
|||||||
Map<String, dynamic> _$MessageSyncResponseToJson(
|
Map<String, dynamic> _$MessageSyncResponseToJson(
|
||||||
_MessageSyncResponse instance,
|
_MessageSyncResponse instance,
|
||||||
) => <String, dynamic>{
|
) => <String, dynamic>{
|
||||||
'changes': instance.changes.map((e) => e.toJson()).toList(),
|
'messages': instance.messages.map((e) => e.toJson()).toList(),
|
||||||
'current_timestamp': instance.currentTimestamp.toIso8601String(),
|
'current_timestamp': instance.currentTimestamp.toIso8601String(),
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
19
lib/models/custom_app_secret.dart
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
import 'package:freezed_annotation/freezed_annotation.dart';
|
||||||
|
|
||||||
|
part 'custom_app_secret.freezed.dart';
|
||||||
|
part 'custom_app_secret.g.dart';
|
||||||
|
|
||||||
|
@freezed
|
||||||
|
sealed class CustomAppSecret with _$CustomAppSecret {
|
||||||
|
const factory CustomAppSecret({
|
||||||
|
required String id,
|
||||||
|
required String? secret,
|
||||||
|
required DateTime createdAt,
|
||||||
|
String? description,
|
||||||
|
int? expiresIn,
|
||||||
|
bool? isOidc,
|
||||||
|
}) = _CustomAppSecret;
|
||||||
|
|
||||||
|
factory CustomAppSecret.fromJson(Map<String, dynamic> json) =>
|
||||||
|
_$CustomAppSecretFromJson(json);
|
||||||
|
}
|
||||||
286
lib/models/custom_app_secret.freezed.dart
Normal file
@@ -0,0 +1,286 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
// coverage:ignore-file
|
||||||
|
// ignore_for_file: type=lint
|
||||||
|
// ignore_for_file: unused_element, deprecated_member_use, deprecated_member_use_from_same_package, use_function_type_syntax_for_parameters, unnecessary_const, avoid_init_to_null, invalid_override_different_default_values_named, prefer_expression_function_bodies, annotate_overrides, invalid_annotation_target, unnecessary_question_mark
|
||||||
|
|
||||||
|
part of 'custom_app_secret.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// FreezedGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
// dart format off
|
||||||
|
T _$identity<T>(T value) => value;
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
mixin _$CustomAppSecret {
|
||||||
|
|
||||||
|
String get id; String? get secret; DateTime get createdAt; String? get description; int? get expiresIn; bool? get isOidc;
|
||||||
|
/// Create a copy of CustomAppSecret
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
$CustomAppSecretCopyWith<CustomAppSecret> get copyWith => _$CustomAppSecretCopyWithImpl<CustomAppSecret>(this as CustomAppSecret, _$identity);
|
||||||
|
|
||||||
|
/// Serializes this CustomAppSecret to a JSON map.
|
||||||
|
Map<String, dynamic> toJson();
|
||||||
|
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is CustomAppSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiresIn, expiresIn) || other.expiresIn == expiresIn)&&(identical(other.isOidc, isOidc) || other.isOidc == isOidc));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,secret,createdAt,description,expiresIn,isOidc);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CustomAppSecret(id: $id, secret: $secret, createdAt: $createdAt, description: $description, expiresIn: $expiresIn, isOidc: $isOidc)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class $CustomAppSecretCopyWith<$Res> {
|
||||||
|
factory $CustomAppSecretCopyWith(CustomAppSecret value, $Res Function(CustomAppSecret) _then) = _$CustomAppSecretCopyWithImpl;
|
||||||
|
@useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class _$CustomAppSecretCopyWithImpl<$Res>
|
||||||
|
implements $CustomAppSecretCopyWith<$Res> {
|
||||||
|
_$CustomAppSecretCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final CustomAppSecret _self;
|
||||||
|
final $Res Function(CustomAppSecret) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CustomAppSecret
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@pragma('vm:prefer-inline') @override $Res call({Object? id = null,Object? secret = freezed,Object? createdAt = null,Object? description = freezed,Object? expiresIn = freezed,Object? isOidc = freezed,}) {
|
||||||
|
return _then(_self.copyWith(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,secret: freezed == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,expiresIn: freezed == expiresIn ? _self.expiresIn : expiresIn // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,isOidc: freezed == isOidc ? _self.isOidc : isOidc // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/// Adds pattern-matching-related methods to [CustomAppSecret].
|
||||||
|
extension CustomAppSecretPatterns on CustomAppSecret {
|
||||||
|
/// A variant of `map` that fallback to returning `orElse`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeMap<TResult extends Object?>(TResult Function( _CustomAppSecret value)? $default,{required TResult orElse(),}){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CustomAppSecret() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// Callbacks receives the raw object, upcasted.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case final Subclass2 value:
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult map<TResult extends Object?>(TResult Function( _CustomAppSecret value) $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CustomAppSecret():
|
||||||
|
return $default(_that);}
|
||||||
|
}
|
||||||
|
/// A variant of `map` that fallback to returning `null`.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case final Subclass value:
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? mapOrNull<TResult extends Object?>(TResult? Function( _CustomAppSecret value)? $default,){
|
||||||
|
final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CustomAppSecret() when $default != null:
|
||||||
|
return $default(_that);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to an `orElse` callback.
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return orElse();
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult maybeWhen<TResult extends Object?>(TResult Function( String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc)? $default,{required TResult orElse(),}) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CustomAppSecret() when $default != null:
|
||||||
|
return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);case _:
|
||||||
|
return orElse();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/// A `switch`-like method, using callbacks.
|
||||||
|
///
|
||||||
|
/// As opposed to `map`, this offers destructuring.
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case Subclass2(:final field2):
|
||||||
|
/// return ...;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult when<TResult extends Object?>(TResult Function( String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc) $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CustomAppSecret():
|
||||||
|
return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);}
|
||||||
|
}
|
||||||
|
/// A variant of `when` that fallback to returning `null`
|
||||||
|
///
|
||||||
|
/// It is equivalent to doing:
|
||||||
|
/// ```dart
|
||||||
|
/// switch (sealedClass) {
|
||||||
|
/// case Subclass(:final field):
|
||||||
|
/// return ...;
|
||||||
|
/// case _:
|
||||||
|
/// return null;
|
||||||
|
/// }
|
||||||
|
/// ```
|
||||||
|
|
||||||
|
@optionalTypeArgs TResult? whenOrNull<TResult extends Object?>(TResult? Function( String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc)? $default,) {final _that = this;
|
||||||
|
switch (_that) {
|
||||||
|
case _CustomAppSecret() when $default != null:
|
||||||
|
return $default(_that.id,_that.secret,_that.createdAt,_that.description,_that.expiresIn,_that.isOidc);case _:
|
||||||
|
return null;
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
@JsonSerializable()
|
||||||
|
|
||||||
|
class _CustomAppSecret implements CustomAppSecret {
|
||||||
|
const _CustomAppSecret({required this.id, required this.secret, required this.createdAt, this.description, this.expiresIn, this.isOidc});
|
||||||
|
factory _CustomAppSecret.fromJson(Map<String, dynamic> json) => _$CustomAppSecretFromJson(json);
|
||||||
|
|
||||||
|
@override final String id;
|
||||||
|
@override final String? secret;
|
||||||
|
@override final DateTime createdAt;
|
||||||
|
@override final String? description;
|
||||||
|
@override final int? expiresIn;
|
||||||
|
@override final bool? isOidc;
|
||||||
|
|
||||||
|
/// Create a copy of CustomAppSecret
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@pragma('vm:prefer-inline')
|
||||||
|
_$CustomAppSecretCopyWith<_CustomAppSecret> get copyWith => __$CustomAppSecretCopyWithImpl<_CustomAppSecret>(this, _$identity);
|
||||||
|
|
||||||
|
@override
|
||||||
|
Map<String, dynamic> toJson() {
|
||||||
|
return _$CustomAppSecretToJson(this, );
|
||||||
|
}
|
||||||
|
|
||||||
|
@override
|
||||||
|
bool operator ==(Object other) {
|
||||||
|
return identical(this, other) || (other.runtimeType == runtimeType&&other is _CustomAppSecret&&(identical(other.id, id) || other.id == id)&&(identical(other.secret, secret) || other.secret == secret)&&(identical(other.createdAt, createdAt) || other.createdAt == createdAt)&&(identical(other.description, description) || other.description == description)&&(identical(other.expiresIn, expiresIn) || other.expiresIn == expiresIn)&&(identical(other.isOidc, isOidc) || other.isOidc == isOidc));
|
||||||
|
}
|
||||||
|
|
||||||
|
@JsonKey(includeFromJson: false, includeToJson: false)
|
||||||
|
@override
|
||||||
|
int get hashCode => Object.hash(runtimeType,id,secret,createdAt,description,expiresIn,isOidc);
|
||||||
|
|
||||||
|
@override
|
||||||
|
String toString() {
|
||||||
|
return 'CustomAppSecret(id: $id, secret: $secret, createdAt: $createdAt, description: $description, expiresIn: $expiresIn, isOidc: $isOidc)';
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @nodoc
|
||||||
|
abstract mixin class _$CustomAppSecretCopyWith<$Res> implements $CustomAppSecretCopyWith<$Res> {
|
||||||
|
factory _$CustomAppSecretCopyWith(_CustomAppSecret value, $Res Function(_CustomAppSecret) _then) = __$CustomAppSecretCopyWithImpl;
|
||||||
|
@override @useResult
|
||||||
|
$Res call({
|
||||||
|
String id, String? secret, DateTime createdAt, String? description, int? expiresIn, bool? isOidc
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
/// @nodoc
|
||||||
|
class __$CustomAppSecretCopyWithImpl<$Res>
|
||||||
|
implements _$CustomAppSecretCopyWith<$Res> {
|
||||||
|
__$CustomAppSecretCopyWithImpl(this._self, this._then);
|
||||||
|
|
||||||
|
final _CustomAppSecret _self;
|
||||||
|
final $Res Function(_CustomAppSecret) _then;
|
||||||
|
|
||||||
|
/// Create a copy of CustomAppSecret
|
||||||
|
/// with the given fields replaced by the non-null parameter values.
|
||||||
|
@override @pragma('vm:prefer-inline') $Res call({Object? id = null,Object? secret = freezed,Object? createdAt = null,Object? description = freezed,Object? expiresIn = freezed,Object? isOidc = freezed,}) {
|
||||||
|
return _then(_CustomAppSecret(
|
||||||
|
id: null == id ? _self.id : id // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String,secret: freezed == secret ? _self.secret : secret // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,createdAt: null == createdAt ? _self.createdAt : createdAt // ignore: cast_nullable_to_non_nullable
|
||||||
|
as DateTime,description: freezed == description ? _self.description : description // ignore: cast_nullable_to_non_nullable
|
||||||
|
as String?,expiresIn: freezed == expiresIn ? _self.expiresIn : expiresIn // ignore: cast_nullable_to_non_nullable
|
||||||
|
as int?,isOidc: freezed == isOidc ? _self.isOidc : isOidc // ignore: cast_nullable_to_non_nullable
|
||||||
|
as bool?,
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// dart format on
|
||||||
27
lib/models/custom_app_secret.g.dart
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
// GENERATED CODE - DO NOT MODIFY BY HAND
|
||||||
|
|
||||||
|
part of 'custom_app_secret.dart';
|
||||||
|
|
||||||
|
// **************************************************************************
|
||||||
|
// JsonSerializableGenerator
|
||||||
|
// **************************************************************************
|
||||||
|
|
||||||
|
_CustomAppSecret _$CustomAppSecretFromJson(Map<String, dynamic> json) =>
|
||||||
|
_CustomAppSecret(
|
||||||
|
id: json['id'] as String,
|
||||||
|
secret: json['secret'] as String?,
|
||||||
|
createdAt: DateTime.parse(json['created_at'] as String),
|
||||||
|
description: json['description'] as String?,
|
||||||
|
expiresIn: (json['expires_in'] as num?)?.toInt(),
|
||||||
|
isOidc: json['is_oidc'] as bool?,
|
||||||
|
);
|
||||||
|
|
||||||
|
Map<String, dynamic> _$CustomAppSecretToJson(_CustomAppSecret instance) =>
|
||||||
|
<String, dynamic>{
|
||||||
|
'id': instance.id,
|
||||||
|
'secret': instance.secret,
|
||||||
|
'created_at': instance.createdAt.toIso8601String(),
|
||||||
|
'description': instance.description,
|
||||||
|
'expires_in': instance.expiresIn,
|
||||||
|
'is_oidc': instance.isOidc,
|
||||||
|
};
|
||||||
23
lib/models/dev_project.dart
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
|
||||||
|
class DevProject {
|
||||||
|
final String id;
|
||||||
|
final String slug;
|
||||||
|
final String name;
|
||||||
|
final String? description;
|
||||||
|
|
||||||
|
DevProject({
|
||||||
|
required this.id,
|
||||||
|
required this.slug,
|
||||||
|
required this.name,
|
||||||
|
this.description,
|
||||||
|
});
|
||||||
|
|
||||||
|
factory DevProject.fromJson(Map<String, dynamic> json) {
|
||||||
|
return DevProject(
|
||||||
|
id: json['id'],
|
||||||
|
slug: json['slug'],
|
||||||
|
name: json['name'],
|
||||||
|
description: json['description'],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,8 +11,8 @@ sealed class SnScrappedLink with _$SnScrappedLink {
|
|||||||
required String title,
|
required String title,
|
||||||
required String? description,
|
required String? description,
|
||||||
required String? imageUrl,
|
required String? imageUrl,
|
||||||
required String faviconUrl,
|
required String? faviconUrl,
|
||||||
required String siteName,
|
required String? siteName,
|
||||||
required String? contentType,
|
required String? contentType,
|
||||||
required String? author,
|
required String? author,
|
||||||
required DateTime? publishedDate,
|
required DateTime? publishedDate,
|
||||||
|
|||||||