Compare commits
578 Commits
c061ef2132
...
3.3.0+145
| Author | SHA1 | Date | |
|---|---|---|---|
|
5ebefae961
|
|||
|
d4758674bb
|
|||
|
f5f1ddc0ea
|
|||
|
2720b59485
|
|||
|
29b1ac7fce
|
|||
|
83ca5551ad
|
|||
| 611cb024a9 | |||
|
74fb56891d
|
|||
|
ac4fa5eb85
|
|||
|
8857718709
|
|||
|
dd17b2b9c1
|
|||
|
848439f664
|
|||
|
f83117424d
|
|||
|
8c19c32c76
|
|||
|
d62b2bed80
|
|||
|
5a23eb1768
|
|||
|
5f6e4763d3
|
|||
|
580c36fb89
|
|||
|
6c25af3b30
|
|||
|
a1da72d447
|
|||
|
ab4120cc22
|
|||
|
52eff0fa25
|
|||
|
beeb28abf2
|
|||
|
c0ab3837ac
|
|||
|
59d38c0d8d
|
|||
|
bd2247ce86
|
|||
|
da2d3f7f17
|
|||
|
7497b77384
|
|||
|
f542d9fa97
|
|||
|
e70439870e
|
|||
|
d764b042fe
|
|||
|
a76b97d1d2
|
|||
|
cfbe6e580b
|
|||
|
f08b9e057f
|
|||
|
0509f37c96
|
|||
|
a7dc9ac6fa
|
|||
|
caf2f5f1f6
|
|||
|
12b79af3a2
|
|||
|
88f149584e
|
|||
|
877001b802
|
|||
| fec28f6223 | |||
| 85005ff9c3 | |||
| e3c92a3c55 | |||
| 9e9fbc5d6a | |||
| 8d1d836b52 | |||
| bc60ce5d42 | |||
| c093123e3a | |||
| 3de73538c7 | |||
| ba8d5cee09 | |||
|
5ee2e70442
|
|||
|
53a3a32907
|
|||
|
9a628779d9
|
|||
|
b60bd63d0c
|
|||
|
01cc71fd47
|
|||
|
a2b0cd0b6a
|
|||
|
7f971bcee3
|
|||
|
7de98a1731
|
|||
|
b52eb95b14
|
|||
|
b3ef7d6ad0
|
|||
|
d28c11940d
|
|||
|
504322c2dd
|
|||
|
a07ec3ca36
|
|||
| d96691e920 | |||
|
6273b2d917
|
|||
|
ab90d244b5
|
|||
|
dc6af6d9e5
|
|||
|
0ca801d963
|
|||
|
3edcdd72af
|
|||
|
402bb3fe04
|
|||
|
8ba55eb1be
|
|||
|
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 | |||
| fbfe8cbdee | |||
| fbbab0a981 | |||
| ae2fb3b303 | |||
| 3d7a4666ed | |||
| 5d3e0fb800 | |||
| 85ff52a661 | |||
| da7fd64a43 | |||
| 3902633217 | |||
| f478ea8b84 | |||
| 0f481aff5b | |||
| 7a31663310 | |||
| 0239c53c04 | |||
| 16987c758e | |||
| 3a36915140 | |||
| 4bde708878 | |||
| 2f0cf560f8 | |||
| cf355a95fd | |||
| 2f43073172 | |||
| 8236d31ecc | |||
| 459a7dade0 | |||
| e6000a660a | |||
| 75abaac205 | |||
| 603d5c3f73 | |||
| 4e4bd99598 | |||
| d1fbe5f15e |
9
.github/workflows/build.yml
vendored
@@ -41,6 +41,15 @@ jobs:
|
||||
with:
|
||||
name: build-output-windows
|
||||
path: build/windows/x64/runner/Release
|
||||
- name: Compile Installer
|
||||
uses: Minionguyjpro/Inno-Setup-Action@v1.2.2
|
||||
with:
|
||||
path: setup.iss
|
||||
- name: Archive installer artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: build-output-windows-installer
|
||||
path: Installer/windows-x86_64-setup.exe
|
||||
build-linux:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
||||
3
.gitignore
vendored
@@ -12,6 +12,9 @@
|
||||
.swiftpm/
|
||||
migrate_working_dir/
|
||||
|
||||
# Inno Setup
|
||||
Installer/
|
||||
|
||||
# IntelliJ related
|
||||
*.iml
|
||||
*.ipr
|
||||
|
||||
@@ -14,13 +14,13 @@ The backend of the Solar Network is written in Go and is a microservices app. Th
|
||||
|
||||
## 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
|
||||
|
||||
## 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
|
||||
|
||||
@@ -28,9 +28,14 @@ To contribute new features, please create an issue or mention the feature you wa
|
||||
|
||||
## Bug Reports / Ask for help
|
||||
|
||||
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!
|
||||
|
||||
|
||||
@@ -63,3 +63,8 @@ If you want to build the release version, use the flutter build command. Learn m
|
||||
flutter build <platform>
|
||||
```
|
||||
|
||||
### Known Issues
|
||||
|
||||
Due to the issues with the flutter build tools, [see](https://github.com/flutter/flutter/issues/160622).
|
||||
|
||||
Since there is a watchOS app for iOS, you're unable to use the flutter cli to run iOS app. Use xcode instead.
|
||||
@@ -5,6 +5,7 @@ plugins {
|
||||
id("com.android.application")
|
||||
// START: FlutterFire Configuration
|
||||
id("com.google.gms.google-services")
|
||||
id("com.google.firebase.crashlytics")
|
||||
// END: FlutterFire Configuration
|
||||
id("kotlin-android")
|
||||
// The Flutter Gradle Plugin must be applied after the Android and Kotlin Gradle plugins.
|
||||
@@ -23,6 +24,8 @@ android {
|
||||
ndkVersion = "29.0.13113456"
|
||||
|
||||
compileOptions {
|
||||
isCoreLibraryDesugaringEnabled = true
|
||||
|
||||
sourceCompatibility = JavaVersion.VERSION_17
|
||||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
@@ -62,6 +65,8 @@ android {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
coreLibraryDesugaring("com.android.tools:desugar_jdk_libs:2.1.4")
|
||||
|
||||
implementation("com.google.android.material:material:1.12.0")
|
||||
implementation("com.github.bumptech.glide:glide:4.16.0")
|
||||
implementation("com.squareup.okhttp3:okhttp:5.1.0")
|
||||
@@ -70,3 +75,4 @@ dependencies {
|
||||
flutter {
|
||||
source = "../.."
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,16 @@
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- App protocol -->
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
<!-- Accepts URIs that begin with YOUR_SCHEME://YOUR_HOST -->
|
||||
<data android:scheme="solian" />
|
||||
</intent-filter>
|
||||
|
||||
<!-- Deeplinking -->
|
||||
<intent-filter android:autoVerify="true">
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
@@ -51,6 +61,12 @@
|
||||
<data android:scheme="http" android:host="solian.app" />
|
||||
<data android:scheme="https" />
|
||||
</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 -->
|
||||
<intent-filter>
|
||||
|
||||
41
android/app/src/main/res/drawable/ic_notification.xml
Normal file
@@ -0,0 +1,41 @@
|
||||
<vector xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:width="192dp"
|
||||
android:height="192dp"
|
||||
android:viewportWidth="192"
|
||||
android:viewportHeight="192">
|
||||
<path
|
||||
android:pathData="M54,147h86"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="12"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M57,111s-2,-4.5 -2,-10m22,22s-4,7 -11,4m9,-22s-2,-4.5 -2,-10"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="10"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M54,147a32,32 0,0 1,-12 -61.67A39,39 0,0 1,81 46m59,101a30,30 0,0 0,29.93 -28"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="12"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M132,75m-4,0a4,4 0,1 1,8 0a4,4 0,1 1,-8 0"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="8"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
<path
|
||||
android:pathData="M112.5,41.22C100.84,47.96 93,60.56 93,75c0,6.38 1.53,12.39 4.24,17.71m69.51,-35.42A38.84,38.84 0,0 1,171 75c0,14.43 -7.84,27.03 -19.49,33.78m-0.79,-43.32A20.9,20.9 0,0 1,153 75c0,7.77 -4.22,14.56 -10.49,18.19m-21,-36.38C115.22,60.44 111,67.23 111,75a20.9,20.9 0,0 0,2.28 9.53"
|
||||
android:strokeLineJoin="round"
|
||||
android:strokeWidth="10"
|
||||
android:fillColor="#00000000"
|
||||
android:strokeColor="#000"
|
||||
android:strokeLineCap="round"/>
|
||||
</vector>
|
||||
@@ -21,6 +21,7 @@ plugins {
|
||||
id("com.android.application") version "8.12.0" apply false
|
||||
// START: FlutterFire Configuration
|
||||
id("com.google.gms.google-services") version("4.3.15") apply false
|
||||
id("com.google.firebase.crashlytics") version("2.8.1") apply false
|
||||
// END: FlutterFire Configuration
|
||||
id("org.jetbrains.kotlin.android") version("2.2.0") apply false
|
||||
}
|
||||
|
||||
1079
assets/i18n/es-ES.json
Normal file
1079
assets/i18n/ja-JP.json
Normal file
1079
assets/i18n/ko-KR.json
Normal file
@@ -46,7 +46,6 @@
|
||||
"delete": "删除",
|
||||
"deletePublisher": "删除发布者",
|
||||
"deletePublisherHint": "确定要删除此发布者吗?这也会删除此发布者下的所有帖子和收藏。",
|
||||
"somethingWentWrong": "发生了一些错误……",
|
||||
"deletePost": "删除帖子",
|
||||
"deletePostHint": "确定要删除这篇帖子吗?",
|
||||
"copyLink": "复制链接",
|
||||
@@ -159,11 +158,11 @@
|
||||
"checkIn": "签到",
|
||||
"checkInNone": "尚未签到",
|
||||
"checkInNoneHint": "通过签到获取您的财富提示和每日奖励。",
|
||||
"checkInResultLevel0": "最差运气",
|
||||
"checkInResultLevel1": "坏运气",
|
||||
"checkInResultLevel2": "一个普通的日常",
|
||||
"checkInResultLevel3": "好运",
|
||||
"checkInResultLevel4": "最佳运气",
|
||||
"checkInResultLevel0": "大凶",
|
||||
"checkInResultLevel1": "凶",
|
||||
"checkInResultLevel2": "中平",
|
||||
"checkInResultLevel3": "吉",
|
||||
"checkInResultLevel4": "大吉",
|
||||
"checkInActivityTitle": "{} 在 {} 签到并获得了 {}",
|
||||
"eventCalander": "活动日历",
|
||||
"eventCalanderEmpty": "该日无活动。",
|
||||
@@ -345,11 +344,10 @@
|
||||
"accountSettingsHelpContent": "此页面允许您管理您的帐户安全性、隐私和其他设置。如果您需要帮助,请联系管理员。",
|
||||
"unauthorized": "未授权",
|
||||
"unauthorizedHint": "您未登录或会话已过期,请重新登录。",
|
||||
"publisherBelongsTo": "属于",
|
||||
"publisherBelongsTo": "属于 {}",
|
||||
"postContent": "内容",
|
||||
"postSettings": "设置",
|
||||
"postPublisherUnselected": "未指定发布者",
|
||||
"postVisibility": "可见性",
|
||||
"postVisibilityPublic": "公开",
|
||||
"postVisibilityFriends": "仅好友可见",
|
||||
"postVisibilityUnlisted": "不公开",
|
||||
@@ -501,9 +499,6 @@
|
||||
"membershipTierNova": "新星",
|
||||
"membershipTierSupernova": "超新星",
|
||||
"membershipTierUnknown": "未知",
|
||||
"membershipPriceStellar": "每月 10 金点",
|
||||
"membershipPriceNova": "每月 20 金点",
|
||||
"membershipPriceSupernova": "每月 30 金点",
|
||||
"membershipFeatureBasic": "基础功能",
|
||||
"membershipFeaturePrioritySupport": "优先支持",
|
||||
"membershipFeatureAdFree": "无广告",
|
||||
@@ -573,37 +568,36 @@
|
||||
"share": "分享",
|
||||
"sharePost": "分享帖子",
|
||||
"quickActions": "快捷操作",
|
||||
"post": "帖子",
|
||||
"post": "发帖",
|
||||
"copy": "复制",
|
||||
"sendToChat": "发送到聊天",
|
||||
"failedToShareToPost": "分享到帖子失败:{}",
|
||||
"shareToChatComingSoon": "分享到聊天的功能即将到来",
|
||||
"shareToChatComingSoon": "分享到聊天功能即将推出",
|
||||
"failedToShareToChat": "分享到聊天失败:{}",
|
||||
"shareToSpecificChatComingSoon": "分享到 {} 的功能即将到来",
|
||||
"shareToSpecificChatComingSoon": "分享到 {} 功能即将推出",
|
||||
"directChat": "私信",
|
||||
"systemShareComingSoon": "系统分享功能即将到来",
|
||||
"systemShareComingSoon": "系统分享功能即将推出",
|
||||
"failedToShareToSystem": "分享到系统失败:{}",
|
||||
"failedToCopy": "复制失败:{}",
|
||||
"noChatRoomsAvailable": "没有聊天室可用",
|
||||
"failedToLoadChats": "加载聊天室失败",
|
||||
"contentToShare": "要分享的内容:",
|
||||
"unknownChat": "未知聊天室",
|
||||
"addAdditionalMessage": "添加额外消息……",
|
||||
"noChatRoomsAvailable": "无可用聊天室",
|
||||
"failedToLoadChats": "加载聊天失败",
|
||||
"contentToShare": "分享内容:",
|
||||
"unknownChat": "未知聊天",
|
||||
"addAdditionalMessage": "添加附加消息……",
|
||||
"uploadingFiles": "上传文件中……",
|
||||
"sharedSuccessfully": "分享成功!",
|
||||
"shareSuccess": "分享成功!",
|
||||
"shareToSpecificChatSuccess": "分享到 {} 成功!",
|
||||
"wouldYouLikeToGoToChat": "你想要前往聊天页面吗?",
|
||||
"no": "是",
|
||||
"yes": "否",
|
||||
"navigateToChat": "前往聊天室",
|
||||
"wouldYouLikeToNavigateToChat": "你想要前往聊天页面吗?",
|
||||
"shareToSpecificChatSuccess": "成功分享至 {}!",
|
||||
"wouldYouLikeToGoToChat": "是否前往该聊天?",
|
||||
"no": "否",
|
||||
"yes": "是",
|
||||
"navigateToChat": "前往聊天",
|
||||
"abuseReport": "举报",
|
||||
"abuseReportTitle": "举报内容",
|
||||
"abuseReportDescription": "通过举报不合适的内容和行为来帮助我们维护社区的健康稳定发展。",
|
||||
"abuseReportDescription": "举报不当内容或行为,协助维护社区安全。",
|
||||
"abuseReportType": "举报类型",
|
||||
"abuseReportReason": "额外细节",
|
||||
"abuseReportReasonHint": "请提供更多关于此的细节……",
|
||||
"abuseReportReason": "补充详情",
|
||||
"abuseReportReasonHint": "请提供更多详情……",
|
||||
"abuseReportSubmit": "提交举报",
|
||||
"abuseReportSuccess": "举报提交成功,感谢你为社区维护作出贡献。",
|
||||
"abuseReportError": "无法提交举报,请稍后再试。",
|
||||
@@ -629,8 +623,6 @@
|
||||
"chatJoin": "加入聊天",
|
||||
"realmJoin": "加入领域",
|
||||
"realmJoinSuccess": "成功加入领域。",
|
||||
"discoverRealms": "发现领域",
|
||||
"discoverPublishers": "发现开发者",
|
||||
"search": "搜索",
|
||||
"publisherMembers": "合作者",
|
||||
"developerHub": "开发者中心",
|
||||
@@ -676,7 +668,427 @@
|
||||
"publisherFeatureDevelopDescription": "为你的开发者解锁包括应用套件,API 及更多开发功能。",
|
||||
"publisherFeatureDevelopHint": "目前该功能还在开发中,你需要邀请才可解锁。",
|
||||
"learnMore": "了解更多",
|
||||
"discoverWebArticles": "来自站外的文章",
|
||||
"webArticlesStand": "文章亭",
|
||||
"about": "关于"
|
||||
}
|
||||
"about": "关于",
|
||||
"somethingWentWrong": "发生了一些错误",
|
||||
"editedAt": "编辑于 {}",
|
||||
"addAudio": "添加音频",
|
||||
"recordAudio": "录制音频",
|
||||
"linkAttachment": "链接附件",
|
||||
"fileIdCannotBeEmpty": "文件 ID 不能为空",
|
||||
"fileIdLinkHint": "还没有上传到 Solar Network?点击此处打开 Solar Network Drive,自定义您的上传内容。",
|
||||
"failedToFetchFile": "获取文件失败:{}",
|
||||
"callLeave": "离开",
|
||||
"callEnd": "挂断通话",
|
||||
"postType": "帖子类型",
|
||||
"articleAttachmentHint": "附件必须上传并插入到文章主体中才能显示出来。",
|
||||
"postVisibility": "可见性",
|
||||
"currentMembershipMember": "恒星计划成员 · {}",
|
||||
"membershipPriceStellar": "需要用户等级 3+,每月价格 1200 NSP",
|
||||
"membershipPriceNova": "需要用户等级 6+,每月价格 2400 NSP",
|
||||
"membershipPriceSupernova": "需要用户等级 9+,每月价格 3600 NSP",
|
||||
"sharePostPhoto": "通过图片分享帖子",
|
||||
"wouldYouLikeToNavigateToChat": "你想要前往聊天页面吗?",
|
||||
"abuseReports": "举报",
|
||||
"membershipCancel": "取消会员订阅",
|
||||
"membershipCancelConfirm": "你确定要取消会员订阅吗?",
|
||||
"membershipCancelHint": "你确定要取消会员订阅吗?你将不会再次被扣费。你的会员资格将在当前计费周期结束前保持有效。并且你将无法重新订阅,直到当前订阅结束。",
|
||||
"membershipCancelSuccess": "你的会员订阅已成功取消。",
|
||||
"aboutScreenTitle": "关于",
|
||||
"aboutScreenVersionInfo": "版本 {} ({})",
|
||||
"aboutScreenAppInfoSectionTitle": "应用信息",
|
||||
"aboutScreenPackageNameLabel": "包名",
|
||||
"aboutScreenVersionLabel": "版本",
|
||||
"aboutScreenBuildNumberLabel": "构建编号",
|
||||
"aboutScreenLinksSectionTitle": "链接",
|
||||
"aboutScreenPrivacyPolicyTitle": "隐私政策",
|
||||
"aboutScreenTermsOfServiceTitle": "服务条款",
|
||||
"aboutScreenOpenSourceLicensesTitle": "开源许可",
|
||||
"aboutScreenDeveloperSectionTitle": "开发者",
|
||||
"aboutScreenContactUsTitle": "联系我们",
|
||||
"aboutScreenLicenseTitle": "许可",
|
||||
"aboutScreenLicenseContent": "无法翻译",
|
||||
"aboutScreenCopyright": "版权所有 © Solsynth {}",
|
||||
"aboutScreenMadeWith": "由 Solar Network 团队用 ❤︎️ 制作",
|
||||
"aboutScreenFailedToLoadPackageInfo": "无法加载包信息:{error}",
|
||||
"copiedToClipboard": "已复制到剪贴板",
|
||||
"copyToClipboardTooltip": "复制到剪贴板",
|
||||
"postForwardingTo": "正在转发到",
|
||||
"postReplyingTo": "正在回复",
|
||||
"postReplyPlaceholder": "发表你的回复",
|
||||
"postEditing": "你正在编辑一个现有的帖子",
|
||||
"postArticle": "文章",
|
||||
"aboutDeviceName": "设备名称",
|
||||
"aboutDeviceIdentifier": "设备标识符",
|
||||
"donate": "捐赠",
|
||||
"donateDescription": "支持我们继续开发 Solar Network,并维持服务器运行。",
|
||||
"fileId": "文件 ID",
|
||||
"fileIdHint": "文件 ID 是你通过 Solar Network Drive 上传文件后获得的 ID。",
|
||||
"translate": "翻译",
|
||||
"translating": "正在翻译",
|
||||
"translated": "已翻译",
|
||||
"reactionThumbUp": "赞",
|
||||
"reactionThumbDown": "踩",
|
||||
"reactionJustOkay": "还行",
|
||||
"reactionCry": "哭",
|
||||
"reactionConfuse": "困惑",
|
||||
"reactionClap": "鼓掌",
|
||||
"reactionLaugh": "笑",
|
||||
"reactionAngry": "生气",
|
||||
"reactionParty": "派对",
|
||||
"reactionPray": "祈祷",
|
||||
"reactionHeart": "爱心",
|
||||
"selectMicrophone": "选择麦克风",
|
||||
"selectCamera": "选择摄像头",
|
||||
"switchedTo": "已切换到 {}",
|
||||
"connecting": "正在连接",
|
||||
"reconnecting": "正在重新连接",
|
||||
"disconnected": "已断开连接",
|
||||
"connected": "已连接",
|
||||
"repliesLoadMore": "加载更多回复",
|
||||
"attachmentsRecentUploads": "最近上传",
|
||||
"attachmentsManualInput": "手动输入",
|
||||
"crop": "裁剪",
|
||||
"rename": "重命名",
|
||||
"markAsSensitive": "标记为敏感",
|
||||
"fileName": "文件名",
|
||||
"sensitiveCategories": {
|
||||
"language": "语言",
|
||||
"sexualContent": "色情内容",
|
||||
"violence": "暴力",
|
||||
"profanity": "亵渎",
|
||||
"hateSpeech": "仇恨言论",
|
||||
"racism": "种族主义",
|
||||
"adultContent": "成人内容",
|
||||
"drugAbuse": "药物滥用",
|
||||
"alcoholAbuse": "酗酒",
|
||||
"gambling": "赌博",
|
||||
"selfHarm": "自残",
|
||||
"childAbuse": "虐待儿童",
|
||||
"other": "其他"
|
||||
},
|
||||
"poll": "投票",
|
||||
"pollsRecent": "最近投票",
|
||||
"pollCreateNew": "创建新投票",
|
||||
"pollCreateNewHint": "为你的帖子创建一个新投票。选择一个发布者然后继续。",
|
||||
"publisher": "发布者",
|
||||
"publisherHint": "输入发布者名称",
|
||||
"publisherCannotBeEmpty": "发布者不能为空",
|
||||
"operationFailed": "操作失败:{}",
|
||||
"stickerMarketplace": "贴纸市场",
|
||||
"stickerPackAdded": "贴纸包已添加到你的收藏",
|
||||
"stickerPackRemoved": "贴纸包已从你的收藏中移除",
|
||||
"addPack": "添加贴纸包",
|
||||
"removePack": "移除贴纸包",
|
||||
"browseAndAddStickers": "浏览并添加贴纸包",
|
||||
"stickerPack": "贴纸包",
|
||||
"postCategoryTechnology": "科技",
|
||||
"postCategoryTravel": "旅行",
|
||||
"postCategoryFood": "美食",
|
||||
"postCategoryHealth": "健康",
|
||||
"postCategoryScience": "科学",
|
||||
"postCategorySports": "体育",
|
||||
"postCategoryFinance": "金融",
|
||||
"postCategoryLife": "生活",
|
||||
"postCategoryArt": "艺术",
|
||||
"postCategoryStudy": "学习",
|
||||
"postCategoryGaming": "游戏",
|
||||
"postCategoryProgramming": "编程",
|
||||
"postCategoryMusic": "音乐",
|
||||
"links": "链接",
|
||||
"addLink": "添加链接",
|
||||
"linkKey": "链接名称",
|
||||
"linkValue": "链接",
|
||||
"debugOptions": "调试选项",
|
||||
"joinedAt": "加入于 {}",
|
||||
"searchAccounts": "搜索帐号……",
|
||||
"webFeeds": "订阅源",
|
||||
"polls": "投票",
|
||||
"sharePostSlogan": "加入 Solar Network 以便探索更多",
|
||||
"filesListAdditional": {
|
||||
"one": "+{} 个文件被折叠",
|
||||
"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
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/icons/icon-tray.png
Normal file
|
After Width: | Height: | Size: 63 KiB |
BIN
assets/icons/icon.ico
Normal file
|
After Width: | Height: | Size: 108 KiB |
BIN
assets/images/media-offline.jpg
Normal file
|
After Width: | Height: | Size: 461 KiB |
BIN
assets/images/oidc/spotify.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
1
assets/images/oidc/steam.svg
Normal file
@@ -0,0 +1 @@
|
||||
<svg width="2471" height="2500" viewBox="0 0 256 259" xmlns="http://www.w3.org/2000/svg" preserveAspectRatio="xMidYMid"><path d="M127.779 0C60.42 0 5.24 52.412 0 119.014l68.724 28.674a35.812 35.812 0 0 1 20.426-6.366c.682 0 1.356.019 2.02.056l30.566-44.71v-.626c0-26.903 21.69-48.796 48.353-48.796 26.662 0 48.352 21.893 48.352 48.796 0 26.902-21.69 48.804-48.352 48.804-.37 0-.73-.009-1.098-.018l-43.593 31.377c.028.582.046 1.163.046 1.735 0 20.204-16.283 36.636-36.294 36.636-17.566 0-32.263-12.658-35.584-29.412L4.41 164.654c15.223 54.313 64.673 94.132 123.369 94.132 70.818 0 128.221-57.938 128.221-129.393C256 57.93 198.597 0 127.779 0zM80.352 196.332l-15.749-6.568c2.787 5.867 7.621 10.775 14.033 13.47 13.857 5.83 29.836-.803 35.612-14.799a27.555 27.555 0 0 0 .046-21.035c-2.768-6.79-7.999-12.086-14.706-14.909-6.67-2.795-13.811-2.694-20.085-.304l16.275 6.79c10.222 4.3 15.056 16.145 10.794 26.46-4.253 10.314-15.998 15.195-26.22 10.895zm121.957-100.29c0-17.925-14.457-32.52-32.217-32.52-17.769 0-32.226 14.595-32.226 32.52 0 17.926 14.457 32.512 32.226 32.512 17.76 0 32.217-14.586 32.217-32.512zm-56.37-.055c0-13.488 10.84-24.42 24.2-24.42 13.368 0 24.208 10.932 24.208 24.42 0 13.488-10.84 24.421-24.209 24.421-13.359 0-24.2-10.933-24.2-24.42z" fill="#1A1918"/></svg>
|
||||
|
After Width: | Height: | Size: 1.2 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:
|
||||
explicit_to_json: true
|
||||
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>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>12.0</string>
|
||||
<string>13.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
||||
15
ios/Podfile
@@ -1,4 +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.
|
||||
@@ -32,6 +31,8 @@ target 'Runner' do
|
||||
use_modular_headers!
|
||||
|
||||
pod 'Alamofire'
|
||||
pod 'Kingfisher', '~> 8.0'
|
||||
pod 'KingfisherWebP'
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
|
||||
@@ -41,8 +42,6 @@ target 'Runner' do
|
||||
|
||||
target 'SolianNotificationService' do
|
||||
inherit! :search_paths
|
||||
pod 'Kingfisher', '~> 8.0'
|
||||
pod 'Alamofire'
|
||||
end
|
||||
|
||||
target 'SolianShareExtension' do
|
||||
@@ -50,6 +49,16 @@ target 'Runner' do
|
||||
end
|
||||
end
|
||||
|
||||
target 'Solian Watch App' do
|
||||
platform :watchos, '11.0'
|
||||
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
pod 'Kingfisher', '~> 8.0'
|
||||
pod 'KingfisherWebP'
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
flutter_additional_ios_build_settings(target)
|
||||
|
||||
246
ios/Podfile.lock
@@ -1,5 +1,7 @@
|
||||
PODS:
|
||||
- Alamofire (5.10.2)
|
||||
- app_links (6.4.1):
|
||||
- Flutter
|
||||
- connectivity_plus (0.0.1):
|
||||
- Flutter
|
||||
- croppy (0.0.1):
|
||||
@@ -40,38 +42,90 @@ PODS:
|
||||
- file_picker (0.0.1):
|
||||
- DKImagePickerController/PhotoGallery
|
||||
- Flutter
|
||||
- Firebase/CoreOnly (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- Firebase/Messaging (12.0.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 12.0.0)
|
||||
- firebase_core (4.0.0):
|
||||
- Firebase/CoreOnly (= 12.0.0)
|
||||
- file_saver (0.0.1):
|
||||
- Flutter
|
||||
- firebase_messaging (16.0.0):
|
||||
- Firebase/Messaging (= 12.0.0)
|
||||
- Firebase/CoreOnly (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- Firebase/Crashlytics (12.4.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseCrashlytics (~> 12.4.0)
|
||||
- Firebase/Messaging (12.4.0):
|
||||
- Firebase/CoreOnly
|
||||
- FirebaseMessaging (~> 12.4.0)
|
||||
- firebase_analytics (12.0.3):
|
||||
- firebase_core
|
||||
- FirebaseAnalytics (= 12.4.0)
|
||||
- Flutter
|
||||
- firebase_core (4.2.0):
|
||||
- Firebase/CoreOnly (= 12.4.0)
|
||||
- Flutter
|
||||
- firebase_crashlytics (5.0.3):
|
||||
- Firebase/Crashlytics (= 12.4.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseCore (12.0.0):
|
||||
- FirebaseCoreInternal (~> 12.0.0)
|
||||
- firebase_messaging (16.0.3):
|
||||
- Firebase/Messaging (= 12.4.0)
|
||||
- firebase_core
|
||||
- Flutter
|
||||
- FirebaseAnalytics (12.4.0):
|
||||
- FirebaseAnalytics/Default (= 12.4.0)
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseAnalytics/Default (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleAppMeasurement/Default (= 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseCore (12.4.0):
|
||||
- FirebaseCoreInternal (~> 12.4.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- FirebaseCoreInternal (12.0.0):
|
||||
- FirebaseCoreExtension (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseCoreInternal (12.4.0):
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- FirebaseInstallations (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseCrashlytics (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- FirebaseRemoteConfigInterop (~> 12.4.0)
|
||||
- FirebaseSessions (~> 12.4.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseInstallations (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- PromisesObjC (~> 2.4)
|
||||
- FirebaseMessaging (12.0.0):
|
||||
- FirebaseCore (~> 12.0.0)
|
||||
- FirebaseInstallations (~> 12.0.0)
|
||||
- FirebaseMessaging (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Reachability (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- FirebaseRemoteConfigInterop (12.4.0)
|
||||
- FirebaseSessions (12.4.0):
|
||||
- FirebaseCore (~> 12.4.0)
|
||||
- FirebaseCoreExtension (~> 12.4.0)
|
||||
- FirebaseInstallations (~> 12.4.0)
|
||||
- GoogleDataTransport (~> 10.1)
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/UserDefaults (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesSwift (~> 2.1)
|
||||
- Flutter (1.0.0)
|
||||
- flutter_app_update (0.0.1):
|
||||
- Flutter
|
||||
@@ -84,6 +138,8 @@ PODS:
|
||||
- OrderedSet (~> 6.0.3)
|
||||
- flutter_keyboard_visibility (0.0.1):
|
||||
- Flutter
|
||||
- flutter_local_notifications (0.0.1):
|
||||
- Flutter
|
||||
- flutter_native_splash (2.4.3):
|
||||
- Flutter
|
||||
- flutter_platform_alert (0.0.1):
|
||||
@@ -95,12 +151,39 @@ PODS:
|
||||
- flutter_udid (0.0.1):
|
||||
- Flutter
|
||||
- SAMKeychain
|
||||
- flutter_webrtc (1.0.0):
|
||||
- flutter_webrtc (1.2.0):
|
||||
- Flutter
|
||||
- WebRTC-SDK (= 137.7151.02)
|
||||
- WebRTC-SDK (= 137.7151.04)
|
||||
- gal (1.0.0):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
- GoogleAdsOnDeviceConversion (3.1.0):
|
||||
- GoogleUtilities/Environment (~> 8.1)
|
||||
- GoogleUtilities/Logger (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Core (12.4.0):
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/Default (12.4.0):
|
||||
- GoogleAdsOnDeviceConversion (~> 3.1.0)
|
||||
- GoogleAppMeasurement/Core (= 12.4.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (= 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleAppMeasurement/IdentitySupport (12.4.0):
|
||||
- GoogleAppMeasurement/Core (= 12.4.0)
|
||||
- GoogleUtilities/AppDelegateSwizzler (~> 8.1)
|
||||
- GoogleUtilities/MethodSwizzler (~> 8.1)
|
||||
- GoogleUtilities/Network (~> 8.1)
|
||||
- "GoogleUtilities/NSData+zlib (~> 8.1)"
|
||||
- nanopb (~> 3.30910.0)
|
||||
- GoogleDataTransport (10.1.0):
|
||||
- nanopb (~> 3.30910.0)
|
||||
- PromisesObjC (~> 2.4)
|
||||
@@ -114,6 +197,9 @@ PODS:
|
||||
- GoogleUtilities/Logger (8.1.0):
|
||||
- GoogleUtilities/Environment
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/MethodSwizzler (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- GoogleUtilities/Privacy
|
||||
- GoogleUtilities/Network (8.1.0):
|
||||
- GoogleUtilities/Logger
|
||||
- "GoogleUtilities/NSData+zlib"
|
||||
@@ -132,11 +218,26 @@ PODS:
|
||||
- Flutter
|
||||
- irondash_engine_context (0.0.1):
|
||||
- Flutter
|
||||
- Kingfisher (8.5.0)
|
||||
- livekit_client (2.5.0):
|
||||
- Kingfisher (8.6.1)
|
||||
- KingfisherWebP (1.7.2):
|
||||
- Kingfisher (~> 8.0)
|
||||
- libwebp (>= 1.1.0)
|
||||
- libwebp (1.5.0):
|
||||
- libwebp/demux (= 1.5.0)
|
||||
- libwebp/mux (= 1.5.0)
|
||||
- libwebp/sharpyuv (= 1.5.0)
|
||||
- libwebp/webp (= 1.5.0)
|
||||
- libwebp/demux (1.5.0):
|
||||
- libwebp/webp
|
||||
- libwebp/mux (1.5.0):
|
||||
- libwebp/demux
|
||||
- libwebp/sharpyuv (1.5.0)
|
||||
- libwebp/webp (1.5.0):
|
||||
- libwebp/sharpyuv
|
||||
- livekit_client (2.5.3):
|
||||
- Flutter
|
||||
- flutter_webrtc
|
||||
- WebRTC-SDK (= 137.7151.02)
|
||||
- WebRTC-SDK (= 137.7151.04)
|
||||
- local_auth_darwin (0.0.1):
|
||||
- Flutter
|
||||
- FlutterMacOS
|
||||
@@ -162,14 +263,16 @@ PODS:
|
||||
- pointer_interceptor_ios (0.0.1):
|
||||
- Flutter
|
||||
- PromisesObjC (2.4.0)
|
||||
- PromisesSwift (2.4.0):
|
||||
- PromisesObjC (= 2.4.0)
|
||||
- receive_sharing_intent (1.8.1):
|
||||
- Flutter
|
||||
- record_ios (1.0.0):
|
||||
- record_ios (1.1.0):
|
||||
- Flutter
|
||||
- SAMKeychain (1.5.3)
|
||||
- SDWebImage (5.21.1):
|
||||
- SDWebImage/Core (= 5.21.1)
|
||||
- SDWebImage/Core (5.21.1)
|
||||
- SDWebImage (5.21.3):
|
||||
- SDWebImage/Core (= 5.21.3)
|
||||
- SDWebImage/Core (5.21.3)
|
||||
- share_plus (0.0.1):
|
||||
- Flutter
|
||||
- shared_preferences_foundation (0.0.1):
|
||||
@@ -208,26 +311,33 @@ PODS:
|
||||
- super_native_extensions (0.0.1):
|
||||
- Flutter
|
||||
- SwiftyGif (5.4.5)
|
||||
- syncfusion_flutter_pdfviewer (0.0.1):
|
||||
- Flutter
|
||||
- url_launcher_ios (0.0.1):
|
||||
- Flutter
|
||||
- volume_controller (0.0.1):
|
||||
- Flutter
|
||||
- wakelock_plus (0.0.1):
|
||||
- Flutter
|
||||
- WebRTC-SDK (137.7151.02)
|
||||
- WebRTC-SDK (137.7151.04)
|
||||
|
||||
DEPENDENCIES:
|
||||
- Alamofire
|
||||
- app_links (from `.symlinks/plugins/app_links/ios`)
|
||||
- connectivity_plus (from `.symlinks/plugins/connectivity_plus/ios`)
|
||||
- croppy (from `.symlinks/plugins/croppy/ios`)
|
||||
- device_info_plus (from `.symlinks/plugins/device_info_plus/ios`)
|
||||
- file_picker (from `.symlinks/plugins/file_picker/ios`)
|
||||
- file_saver (from `.symlinks/plugins/file_saver/ios`)
|
||||
- firebase_analytics (from `.symlinks/plugins/firebase_analytics/ios`)
|
||||
- firebase_core (from `.symlinks/plugins/firebase_core/ios`)
|
||||
- firebase_crashlytics (from `.symlinks/plugins/firebase_crashlytics/ios`)
|
||||
- firebase_messaging (from `.symlinks/plugins/firebase_messaging/ios`)
|
||||
- Flutter (from `Flutter`)
|
||||
- flutter_app_update (from `.symlinks/plugins/flutter_app_update/ios`)
|
||||
- flutter_inappwebview_ios (from `.symlinks/plugins/flutter_inappwebview_ios/ios`)
|
||||
- flutter_keyboard_visibility (from `.symlinks/plugins/flutter_keyboard_visibility/ios`)
|
||||
- flutter_local_notifications (from `.symlinks/plugins/flutter_local_notifications/ios`)
|
||||
- flutter_native_splash (from `.symlinks/plugins/flutter_native_splash/ios`)
|
||||
- flutter_platform_alert (from `.symlinks/plugins/flutter_platform_alert/ios`)
|
||||
- flutter_secure_storage (from `.symlinks/plugins/flutter_secure_storage/ios`)
|
||||
@@ -238,6 +348,7 @@ DEPENDENCIES:
|
||||
- image_picker_ios (from `.symlinks/plugins/image_picker_ios/ios`)
|
||||
- irondash_engine_context (from `.symlinks/plugins/irondash_engine_context/ios`)
|
||||
- Kingfisher (~> 8.0)
|
||||
- KingfisherWebP
|
||||
- livekit_client (from `.symlinks/plugins/livekit_client/ios`)
|
||||
- local_auth_darwin (from `.symlinks/plugins/local_auth_darwin/darwin`)
|
||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||
@@ -255,6 +366,7 @@ DEPENDENCIES:
|
||||
- sqflite_darwin (from `.symlinks/plugins/sqflite_darwin/darwin`)
|
||||
- sqlite3_flutter_libs (from `.symlinks/plugins/sqlite3_flutter_libs/darwin`)
|
||||
- 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`)
|
||||
- volume_controller (from `.symlinks/plugins/volume_controller/ios`)
|
||||
- wakelock_plus (from `.symlinks/plugins/wakelock_plus/ios`)
|
||||
@@ -265,16 +377,26 @@ SPEC REPOS:
|
||||
- DKImagePickerController
|
||||
- DKPhotoGallery
|
||||
- Firebase
|
||||
- FirebaseAnalytics
|
||||
- FirebaseCore
|
||||
- FirebaseCoreExtension
|
||||
- FirebaseCoreInternal
|
||||
- FirebaseCrashlytics
|
||||
- FirebaseInstallations
|
||||
- FirebaseMessaging
|
||||
- FirebaseRemoteConfigInterop
|
||||
- FirebaseSessions
|
||||
- GoogleAdsOnDeviceConversion
|
||||
- GoogleAppMeasurement
|
||||
- GoogleDataTransport
|
||||
- GoogleUtilities
|
||||
- Kingfisher
|
||||
- KingfisherWebP
|
||||
- libwebp
|
||||
- nanopb
|
||||
- OrderedSet
|
||||
- PromisesObjC
|
||||
- PromisesSwift
|
||||
- SAMKeychain
|
||||
- SDWebImage
|
||||
- sqlite3
|
||||
@@ -282,6 +404,8 @@ SPEC REPOS:
|
||||
- WebRTC-SDK
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
app_links:
|
||||
:path: ".symlinks/plugins/app_links/ios"
|
||||
connectivity_plus:
|
||||
:path: ".symlinks/plugins/connectivity_plus/ios"
|
||||
croppy:
|
||||
@@ -290,8 +414,14 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/device_info_plus/ios"
|
||||
file_picker:
|
||||
:path: ".symlinks/plugins/file_picker/ios"
|
||||
file_saver:
|
||||
:path: ".symlinks/plugins/file_saver/ios"
|
||||
firebase_analytics:
|
||||
:path: ".symlinks/plugins/firebase_analytics/ios"
|
||||
firebase_core:
|
||||
:path: ".symlinks/plugins/firebase_core/ios"
|
||||
firebase_crashlytics:
|
||||
:path: ".symlinks/plugins/firebase_crashlytics/ios"
|
||||
firebase_messaging:
|
||||
:path: ".symlinks/plugins/firebase_messaging/ios"
|
||||
Flutter:
|
||||
@@ -302,6 +432,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/flutter_inappwebview_ios/ios"
|
||||
flutter_keyboard_visibility:
|
||||
:path: ".symlinks/plugins/flutter_keyboard_visibility/ios"
|
||||
flutter_local_notifications:
|
||||
:path: ".symlinks/plugins/flutter_local_notifications/ios"
|
||||
flutter_native_splash:
|
||||
:path: ".symlinks/plugins/flutter_native_splash/ios"
|
||||
flutter_platform_alert:
|
||||
@@ -354,6 +486,8 @@ EXTERNAL SOURCES:
|
||||
:path: ".symlinks/plugins/sqlite3_flutter_libs/darwin"
|
||||
super_native_extensions:
|
||||
:path: ".symlinks/plugins/super_native_extensions/ios"
|
||||
syncfusion_flutter_pdfviewer:
|
||||
:path: ".symlinks/plugins/syncfusion_flutter_pdfviewer/ios"
|
||||
url_launcher_ios:
|
||||
:path: ".symlinks/plugins/url_launcher_ios/ios"
|
||||
volume_controller:
|
||||
@@ -363,37 +497,51 @@ EXTERNAL SOURCES:
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Alamofire: 7193b3b92c74a07f85569e1a6c4f4237291e7496
|
||||
app_links: 3dbc685f76b1693c66a6d9dd1e9ab6f73d97dc0a
|
||||
connectivity_plus: cb623214f4e1f6ef8fe7403d580fdad517d2f7dd
|
||||
croppy: 979e8ddc254f4642bffe7d52dc7193354b27ba30
|
||||
device_info_plus: 21fcca2080fbcd348be798aa36c3e5ed849eefbe
|
||||
DKImagePickerController: 946cec48c7873164274ecc4624d19e3da4c1ef3c
|
||||
DKPhotoGallery: b3834fecb755ee09a593d7c9e389d8b5d6deed60
|
||||
file_picker: a0560bc09d61de87f12d246fc47d2119e6ef37be
|
||||
Firebase: 800d487043c0557d9faed71477a38d9aafb08a41
|
||||
firebase_core: 633e1851ffe1b9ab875f6467a4f574c79cef02e4
|
||||
firebase_messaging: d17feef781edc84ebefe62624fb384358ad96361
|
||||
FirebaseCore: 055f4ab117d5964158c833f3d5e7ec6d91648d4a
|
||||
FirebaseCoreInternal: dedc28e569a4be85f38f3d6af1070a2e12018d55
|
||||
FirebaseInstallations: d4c7c958f99c8860d7fcece786314ae790e2f988
|
||||
FirebaseMessaging: af49f8d7c0a3d2a017d9302c80946f45a7777dde
|
||||
Flutter: e0871f40cf51350855a761d2e70bf5af5b9b5de7
|
||||
file_saver: 6cdbcddd690cb02b0c1a0c225b37cd805c2bf8b6
|
||||
Firebase: f07b15ae5a6ec0f93713e30b923d9970d144af3e
|
||||
firebase_analytics: 1d024068b1d4707d5ba7a42a12976ddf3316d835
|
||||
firebase_core: 744984dbbed8b3036abf34f0b98d80f130a7e464
|
||||
firebase_crashlytics: f3a9a4338ab99b67042f64e9e22e1bf349cb44ed
|
||||
firebase_messaging: 82c70650c426a0a14873e1acdb9ec2b443c4e8b4
|
||||
FirebaseAnalytics: 0fc2b20091f0ddd21bf73397cf8f0eb5346dc24f
|
||||
FirebaseCore: bb595f3114953664e3c1dc032f008a244147cfd3
|
||||
FirebaseCoreExtension: 7e1f7118ee970e001a8013719fb90950ee5e0018
|
||||
FirebaseCoreInternal: d7f5a043c2cd01a08103ab586587c1468047bca6
|
||||
FirebaseCrashlytics: a6ece278a837c7e88de2d9b5da0a3542f2342395
|
||||
FirebaseInstallations: ae9f4902cb5bf1d0c5eaa31ec1f4e5495a0714e2
|
||||
FirebaseMessaging: d33971b7bb252745ea6cd31ab190d1a1df4b8ed5
|
||||
FirebaseRemoteConfigInterop: 1e31ec72b89c9924367c59bfb5ec9ab60d1d6766
|
||||
FirebaseSessions: ba7c7a7ca8696a8d540eb3fe3800fbe98c79786d
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
flutter_app_update: 816fdb2e30e4832a7c45e3f108d391c42ef040a9
|
||||
flutter_inappwebview_ios: b89ba3482b96fb25e00c967aae065701b66e9b99
|
||||
flutter_keyboard_visibility: 4625131e43015dbbe759d9b20daaf77e0e3f6619
|
||||
flutter_local_notifications: a5a732f069baa862e728d839dd2ebb904737effb
|
||||
flutter_native_splash: c32d145d68aeda5502d5f543ee38c192065986cf
|
||||
flutter_platform_alert: bf3b5fcd4ac14bd637e20527e9c471633071afd3
|
||||
flutter_secure_storage: 1ed9476fba7e7a782b22888f956cce43e2c62f13
|
||||
flutter_timezone: 7c838e17ffd4645d261e87037e5bebf6d38fe544
|
||||
flutter_udid: f7c3884e6ec2951efe4f9de082257fc77c4d15e9
|
||||
flutter_webrtc: 6f7da106613d52ade777d5b4875a43f48c28b457
|
||||
flutter_webrtc: c3e21fc0dcd9d8eb246ae4d5256fcbeb2f5ecd22
|
||||
gal: baecd024ebfd13c441269ca7404792a7152fde89
|
||||
GoogleAdsOnDeviceConversion: e03a386840803ea7eef3fd22a061930142c039c1
|
||||
GoogleAppMeasurement: 1e718274b7e015cefd846ac1fcf7820c70dc017d
|
||||
GoogleDataTransport: aae35b7ea0c09004c3797d53c8c41f66f219d6a7
|
||||
GoogleUtilities: 00c88b9a86066ef77f0da2fab05f65d7768ed8e1
|
||||
image_picker_ios: 7fe1ff8e34c1790d6fff70a32484959f563a928a
|
||||
image_picker_ios: e0ece4aa2a75771a7de3fa735d26d90817041326
|
||||
irondash_engine_context: 8e58ca8e0212ee9d1c7dc6a42121849986c88486
|
||||
Kingfisher: ff0d31a1f07bdff6a1ebb3ba08b8e6e567b6500c
|
||||
livekit_client: e3b79b99405428aac439b6b76a254cd9a11dbbfb
|
||||
local_auth_darwin: d2e8c53ef0c4f43c646462e3415432c4dab3ae19
|
||||
Kingfisher: 7ac7a7288653787a54206b11a3c74f49ab650f1f
|
||||
KingfisherWebP: 38b9721821947f547afb78f933f75f4f9e0ae402
|
||||
libwebp: 02b23773aedb6ff1fd38cec7a77b81414c6842a8
|
||||
livekit_client: 86c8af579274e4b7a215185a8080db2d4e176f40
|
||||
local_auth_darwin: c3ee6cce0a8d56be34c8ccb66ba31f7f180aaebb
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
nanopb: fad817b59e0457d11a5dfbde799381cd727c1275
|
||||
@@ -401,26 +549,28 @@ SPEC CHECKSUMS:
|
||||
OrderedSet: e539b66b644ff081c73a262d24ad552a69be3a94
|
||||
package_info_plus: af8e2ca6888548050f16fa2f1938db7b5a5df499
|
||||
pasteboard: 49088aeb6119d51f976a421db60d8e1ab079b63c
|
||||
path_provider_foundation: 080d55be775b7414fd5a5ef3ac137b97b097e564
|
||||
pointer_interceptor_ios: ec847ef8b0915778bed2b2cef636f4d177fa8eed
|
||||
path_provider_foundation: bb55f6dbba17d0dccd6737fe6f7f34fbd0376880
|
||||
pointer_interceptor_ios: da06a662d5bfd329602b45b2ab41bc0fb5fdb0f0
|
||||
PromisesObjC: f5707f49cb48b9636751c5b2e7d227e43fba9f47
|
||||
PromisesSwift: 9d77319bbe72ebf6d872900551f7eeba9bce2851
|
||||
receive_sharing_intent: 222384f00ffe7e952bbfabaa9e3967cb87e5fe00
|
||||
record_ios: fee1c924aa4879b882ebca2b4bce6011bcfc3d8b
|
||||
record_ios: f75fa1d57f840012775c0e93a38a7f3ceea1a374
|
||||
SAMKeychain: 483e1c9f32984d50ca961e26818a534283b4cd5c
|
||||
SDWebImage: f29024626962457f3470184232766516dee8dfea
|
||||
SDWebImage: 16309af6d214ba3f77a7c6f6fdda888cb313a50a
|
||||
share_plus: 50da8cb520a8f0f65671c6c6a99b3617ed10a58a
|
||||
shared_preferences_foundation: 9e1978ff2562383bd5676f64ec4e9aa8fa06a6f7
|
||||
shared_preferences_foundation: 7036424c3d8ec98dfe75ff1667cb0cd531ec82bb
|
||||
sign_in_with_apple: c5dcc141574c8c54d5ac99dd2163c0c72ad22418
|
||||
sqflite_darwin: 20b2a3a3b70e43edae938624ce550a3cbf66a3d0
|
||||
sqlite3: 73513155ec6979715d3904ef53a8d68892d4032b
|
||||
sqlite3_flutter_libs: 83f8e9f5b6554077f1d93119fe20ebaa5f3a9ef1
|
||||
super_native_extensions: b763c02dc3a8fd078389f410bf15149179020cb4
|
||||
SwiftyGif: 706c60cf65fa2bc5ee0313beece843c8eb8194d4
|
||||
url_launcher_ios: 694010445543906933d732453a59da0a173ae33d
|
||||
syncfusion_flutter_pdfviewer: 90dc48305d2e33d4aa20681d1e98ddeda891bc14
|
||||
url_launcher_ios: 7a95fa5b60cc718a708b8f2966718e93db0cef1b
|
||||
volume_controller: 3657a1f65bedb98fa41ff7dc5793537919f31b12
|
||||
wakelock_plus: e29112ab3ef0b318e58cfa5c32326458be66b556
|
||||
WebRTC-SDK: d20de357dcbf7c9696b124b39f3ff62125107e4b
|
||||
WebRTC-SDK: 40d4f5ba05cadff14e4db5614aec402a633f007e
|
||||
|
||||
PODFILE CHECKSUM: c818292390b02fa379036ea099713a332bd7193f
|
||||
PODFILE CHECKSUM: 585198f58dca90ac6492607c83a8d17045ab3852
|
||||
|
||||
COCOAPODS: 1.16.2
|
||||
|
||||
@@ -10,6 +10,8 @@
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
5D8143680678FCD1D1827271 /* Pods_Solian_Watch_App.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = C9C046CF867AE03DC170F861 /* Pods_Solian_Watch_App.framework */; };
|
||||
7310A7DF2EB10963002C0FD3 /* Solian Watch App.app in Embed Watch Content */ = {isa = PBXBuildFile; fileRef = 7310A7D42EB10962002C0FD3 /* Solian Watch App.app */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
73ACDFAD2E3D0E6100B63535 /* ReplayKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */; };
|
||||
73ACDFC32E3D0E6100B63535 /* SolianBroadcastExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
73C305D82E0BE878009035B9 /* SolianShareExtension.appex in Embed Foundation Extensions */ = {isa = PBXBuildFile; fileRef = 73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */; settings = {ATTRIBUTES = (RemoveHeadersOnCopy, ); }; };
|
||||
@@ -58,6 +60,17 @@
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
7310A7DE2EB10963002C0FD3 /* Embed Watch Content */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 12;
|
||||
dstPath = "$(CONTENTS_FOLDER_PATH)/Watch";
|
||||
dstSubfolderSpec = 16;
|
||||
files = (
|
||||
7310A7DF2EB10963002C0FD3 /* Solian Watch App.app in Embed Watch Content */,
|
||||
);
|
||||
name = "Embed Watch Content";
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -84,6 +97,8 @@
|
||||
/* End PBXCopyFilesBuildPhase section */
|
||||
|
||||
/* Begin PBXFileReference section */
|
||||
0ECC3D56D018DD87FC342699 /* Pods-Solian Watch App.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Solian Watch App.profile.xcconfig"; path = "Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.profile.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
14118AC858B441AB16B7309E /* Pods-RunnerTests.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.release.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.release.xcconfig"; sourceTree = "<group>"; };
|
||||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GeneratedPluginRegistrant.h; sourceTree = "<group>"; };
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GeneratedPluginRegistrant.m; sourceTree = "<group>"; };
|
||||
@@ -91,15 +106,18 @@
|
||||
17FAB080A9C53193ABD9C15B /* Pods-SolianShareExtension.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianShareExtension.debug.xcconfig"; path = "Target Support Files/Pods-SolianShareExtension/Pods-SolianShareExtension.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
192FDACE67D7CB6AED15C634 /* Pods-NotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.debug.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
1C14F71D23E4371602065522 /* Pods-Runner.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.debug.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
2440CEDEAAD6D51FDA95FA62 /* Pods-Solian Watch App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Solian Watch App.release.xcconfig"; path = "Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App.release.xcconfig"; sourceTree = "<group>"; };
|
||||
252A83CE6862573BB856ED8E /* Pods-NotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.release.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||
27C66EFB5A705F1A822C3EB0 /* Pods-SolianShareExtension.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianShareExtension.release.xcconfig"; path = "Target Support Files/Pods-SolianShareExtension/Pods-SolianShareExtension.release.xcconfig"; sourceTree = "<group>"; };
|
||||
29812C17FFBE7DBBC7203981 /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
2D2457F8B2E6EF9C0F935035 /* Pods-NotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-NotificationService.profile.xcconfig"; path = "Target Support Files/Pods-NotificationService/Pods-NotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
31EA49B10397BD4145AD765E /* Pods-Solian Watch App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Solian Watch App.debug.xcconfig"; path = "Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = RunnerTests.swift; sourceTree = "<group>"; };
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = RunnerTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
39FE4CC6223F0D3C0E1FFD04 /* Pods_SolianNotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianNotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
3A1C47BD29CC6AC2587D4DBE /* Pods-Runner.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.profile.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
7310A7D42EB10962002C0FD3 /* Solian Watch App.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "Solian Watch App.app"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
737E920B2DB6A9FF00BE9CDB /* Runner.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Runner.entitlements; sourceTree = "<group>"; };
|
||||
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */ = {isa = PBXFileReference; explicitFileType = "wrapper.app-extension"; includeInIndex = 0; path = SolianBroadcastExtension.appex; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = ReplayKit.framework; path = System/Library/Frameworks/ReplayKit.framework; sourceTree = SDKROOT; };
|
||||
@@ -111,6 +129,7 @@
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_SolianShareExtension.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.debug.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
8B40620B1EEBB09456406A3C /* Pods-SolianNotificationService.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.profile.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Debug.xcconfig; path = Flutter/Debug.xcconfig; sourceTree = "<group>"; };
|
||||
9740EEB31CF90195004384FC /* Generated.xcconfig */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.xcconfig; name = Generated.xcconfig; path = Flutter/Generated.xcconfig; sourceTree = "<group>"; };
|
||||
@@ -120,10 +139,12 @@
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
9AE244813FCDFAA941430393 /* GoogleService-Info.plist */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.plist.xml; name = "GoogleService-Info.plist"; path = "Runner/GoogleService-Info.plist"; sourceTree = "<group>"; };
|
||||
A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-WatchRunner Watch App.release.xcconfig"; path = "Target Support Files/Pods-WatchRunner Watch App/Pods-WatchRunner Watch App.release.xcconfig"; sourceTree = "<group>"; };
|
||||
A499FDB2082EB000933AA8C5 /* Pods-Runner.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-Runner.release.xcconfig"; path = "Target Support Files/Pods-Runner/Pods-Runner.release.xcconfig"; sourceTree = "<group>"; };
|
||||
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianShareExtension.profile.xcconfig"; path = "Target Support Files/Pods-SolianShareExtension/Pods-SolianShareExtension.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
AA0CA8A3E15DEE023BB27438 /* Pods_NotificationService.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_NotificationService.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
B93771F2A63E4148DC6142F7 /* Pods-SolianNotificationService.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.release.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.release.xcconfig"; sourceTree = "<group>"; };
|
||||
C9C046CF867AE03DC170F861 /* Pods_Solian_Watch_App.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Solian_Watch_App.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E6B10A9A85BECA2E576C91FF /* Pods-RunnerTests.profile.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.profile.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.profile.xcconfig"; sourceTree = "<group>"; };
|
||||
F6D834CA86410B09796B312B /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
F830F535CB92E3F2E1653A11 /* Pods-SolianNotificationService.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-SolianNotificationService.debug.xcconfig"; path = "Target Support Files/Pods-SolianNotificationService/Pods-SolianNotificationService.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
@@ -162,6 +183,13 @@
|
||||
/* End PBXFileSystemSynchronizedBuildFileExceptionSet section */
|
||||
|
||||
/* Begin PBXFileSystemSynchronizedRootGroup section */
|
||||
7310A7D52EB10962002C0FD3 /* Solian Watch App */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
);
|
||||
path = "Solian Watch App";
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
73268D272DEB012A0076E970 /* Services */ = {
|
||||
isa = PBXFileSystemSynchronizedRootGroup;
|
||||
exceptions = (
|
||||
@@ -205,6 +233,14 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7310A7D12EB10962002C0FD3 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
5D8143680678FCD1D1827271 /* Pods_Solian_Watch_App.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73ACDFA82E3D0E6100B63535 /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -258,6 +294,7 @@
|
||||
7B40764A2C4CC0E7DC70A0D3 /* Pods_SolianShareExtension.framework */,
|
||||
73ACDFAC2E3D0E6100B63535 /* ReplayKit.framework */,
|
||||
73ACDFB82E3D0E6100B63535 /* UIKit.framework */,
|
||||
C9C046CF867AE03DC170F861 /* Pods_Solian_Watch_App.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
@@ -280,6 +317,12 @@
|
||||
17FAB080A9C53193ABD9C15B /* Pods-SolianShareExtension.debug.xcconfig */,
|
||||
27C66EFB5A705F1A822C3EB0 /* Pods-SolianShareExtension.release.xcconfig */,
|
||||
A85FF612AE7623A9934E57CE /* Pods-SolianShareExtension.profile.xcconfig */,
|
||||
86D60BA96DA647E1B11AA7F0 /* Pods-WatchRunner Watch App.debug.xcconfig */,
|
||||
A2EB1DAFDE9B8E6D88BBF7A3 /* Pods-WatchRunner Watch App.release.xcconfig */,
|
||||
103EA2362B9E9F127016A1F1 /* Pods-WatchRunner Watch App.profile.xcconfig */,
|
||||
31EA49B10397BD4145AD765E /* Pods-Solian Watch App.debug.xcconfig */,
|
||||
2440CEDEAAD6D51FDA95FA62 /* Pods-Solian Watch App.release.xcconfig */,
|
||||
0ECC3D56D018DD87FC342699 /* Pods-Solian Watch App.profile.xcconfig */,
|
||||
);
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
@@ -303,6 +346,7 @@
|
||||
73CDD67B2DEC00480059D95D /* SolianNotificationService */,
|
||||
73C305CF2E0BE878009035B9 /* SolianShareExtension */,
|
||||
73ACDFAE2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||
7310A7D52EB10962002C0FD3 /* Solian Watch App */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
91E124CE95BCB4DCD890160D /* Pods */,
|
||||
@@ -319,6 +363,7 @@
|
||||
73CDD67A2DEC00480059D95D /* SolianNotificationService.appex */,
|
||||
73C305CE2E0BE878009035B9 /* SolianShareExtension.appex */,
|
||||
73ACDFAB2E3D0E6100B63535 /* SolianBroadcastExtension.appex */,
|
||||
7310A7D42EB10962002C0FD3 /* Solian Watch App.app */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
@@ -363,6 +408,28 @@
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
7310A7D32EB10962002C0FD3 /* Solian Watch App */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 7310A7E32EB10963002C0FD3 /* Build configuration list for PBXNativeTarget "Solian Watch App" */;
|
||||
buildPhases = (
|
||||
DDEDA1BA6278B94F0F7B9B61 /* [CP] Check Pods Manifest.lock */,
|
||||
7310A7D02EB10962002C0FD3 /* Sources */,
|
||||
7310A7D12EB10962002C0FD3 /* Frameworks */,
|
||||
7310A7D22EB10962002C0FD3 /* Resources */,
|
||||
E29ECA5954168075BDB000DC /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
fileSystemSynchronizedGroups = (
|
||||
7310A7D52EB10962002C0FD3 /* Solian Watch App */,
|
||||
);
|
||||
name = "Solian Watch App";
|
||||
productName = "WatchRunner Watch App";
|
||||
productReference = 7310A7D42EB10962002C0FD3 /* Solian Watch App.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
};
|
||||
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */;
|
||||
@@ -434,11 +501,13 @@
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
73268D1D2DEAFD670076E970 /* Embed Foundation Extensions */,
|
||||
7310A7DE2EB10963002C0FD3 /* Embed Watch Content */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
8C0351B03869BBF493808288 /* [CP] Embed Pods Frameworks */,
|
||||
5E7D6EF29B671AC7EDBA5649 /* [CP] Copy Pods Resources */,
|
||||
E86CDE9D6464F4F52B910856 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
@@ -462,7 +531,7 @@
|
||||
isa = PBXProject;
|
||||
attributes = {
|
||||
BuildIndependentTargetsInParallel = YES;
|
||||
LastSwiftUpdateCheck = 1640;
|
||||
LastSwiftUpdateCheck = 2600;
|
||||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
@@ -470,6 +539,9 @@
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
7310A7D32EB10962002C0FD3 = {
|
||||
CreatedOnToolsVersion = 26.0.1;
|
||||
};
|
||||
73ACDFAA2E3D0E6100B63535 = {
|
||||
CreatedOnToolsVersion = 16.4;
|
||||
};
|
||||
@@ -503,6 +575,7 @@
|
||||
73CDD6792DEC00480059D95D /* SolianNotificationService */,
|
||||
73C305CD2E0BE878009035B9 /* SolianShareExtension */,
|
||||
73ACDFAA2E3D0E6100B63535 /* SolianBroadcastExtension */,
|
||||
7310A7D32EB10962002C0FD3 /* Solian Watch App */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
@@ -515,6 +588,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7310A7D22EB10962002C0FD3 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73ACDFA92E3D0E6100B63535 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -565,7 +645,7 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
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 */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
@@ -682,6 +762,63 @@
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
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-Solian 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;
|
||||
};
|
||||
E29ECA5954168075BDB000DC /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Solian Watch App/Pods-Solian Watch App-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
E86CDE9D6464F4F52B910856 /* FlutterFire: "flutterfire upload-crashlytics-symbols" */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
);
|
||||
inputPaths = (
|
||||
);
|
||||
name = "FlutterFire: \"flutterfire upload-crashlytics-symbols\"";
|
||||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\n#!/bin/bash\nPATH=\"${PATH}:$FLUTTER_ROOT/bin:${PUB_CACHE}/bin:$HOME/.pub-cache/bin\"\n\nif [ -z \"$PODS_ROOT\" ] || [ ! -d \"$PODS_ROOT/FirebaseCrashlytics\" ]; then\n # Cannot use \"BUILD_DIR%/Build/*\" as per Firebase documentation, it points to \"flutter-project/build/ios/*\" path which doesn't have run script\n DERIVED_DATA_PATH=$(echo \"$BUILD_ROOT\" | sed -E 's|(.*DerivedData/[^/]+).*|\\1|')\n PATH_TO_CRASHLYTICS_UPLOAD_SCRIPT=\"${DERIVED_DATA_PATH}/SourcePackages/checkouts/firebase-ios-sdk/Crashlytics/run\"\nelse\n PATH_TO_CRASHLYTICS_UPLOAD_SCRIPT=\"$PODS_ROOT/FirebaseCrashlytics/run\"\nfi\n\n# Command to upload symbols script used to upload symbols to Firebase server\nflutterfire upload-crashlytics-symbols --upload-symbols-script-path=\"$PATH_TO_CRASHLYTICS_UPLOAD_SCRIPT\" --platform=ios --apple-project-path=\"${SRCROOT}\" --env-platform-name=\"${PLATFORM_NAME}\" --env-configuration=\"${CONFIGURATION}\" --env-project-dir=\"${PROJECT_DIR}\" --env-built-products-dir=\"${BUILT_PRODUCTS_DIR}\" --env-dwarf-dsym-folder-path=\"${DWARF_DSYM_FOLDER_PATH}\" --env-dwarf-dsym-file-name=\"${DWARF_DSYM_FILE_NAME}\" --env-infoplist-path=\"${INFOPLIST_PATH}\" --default-config=default\n";
|
||||
};
|
||||
E947029FCA058878F9B63890 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -715,6 +852,13 @@
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
7310A7D02EB10962002C0FD3 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
73ACDFA72E3D0E6100B63535 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
@@ -834,7 +978,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@@ -854,6 +998,7 @@
|
||||
CUSTOM_GROUP_ID = group.solsynth.solian;
|
||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||
ENABLE_BITCODE = NO;
|
||||
EXCLUDED_SOURCE_FILE_NAMES = "";
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
@@ -864,9 +1009,12 @@
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_ENABLE_EXPLICIT_MODULES = "$(SWIFT_USE_INTEGRATED_DRIVER)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 11.6;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
@@ -874,13 +1022,17 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14DFD79BE7C26E51B117583C /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
@@ -892,13 +1044,17 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 14118AC858B441AB16B7309E /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
@@ -908,18 +1064,171 @@
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = E6B10A9A85BECA2E576C91FF /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
ALLOW_TARGET_PLATFORM_SPECIALIZATION = YES;
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SUPPORTS_MACCATALYST = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
7310A7E02EB10963002C0FD3 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 31EA49B10397BD4145AD765E /* Pods-Solian 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_FILE = "WatchRunner-Watch-App-Info.plist";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||
INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 18.6;
|
||||
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 = 11.6;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
7310A7E12EB10963002C0FD3 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 2440CEDEAAD6D51FDA95FA62 /* Pods-Solian 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_FILE = "WatchRunner-Watch-App-Info.plist";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||
INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 18.6;
|
||||
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;
|
||||
SUPPORTED_PLATFORMS = "watchsimulator watchos";
|
||||
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 = 11.6;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
7310A7E22EB10963002C0FD3 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 0ECC3D56D018DD87FC342699 /* Pods-Solian 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_FILE = "WatchRunner-Watch-App-Info.plist";
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||
INFOPLIST_KEY_UISupportedInterfaceOrientations = "UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown";
|
||||
INFOPLIST_KEY_WKCompanionAppBundleIdentifier = dev.solsynth.solian;
|
||||
INFOPLIST_KEY_WKRunsIndependentlyOfCompanionApp = NO;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 18.6;
|
||||
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;
|
||||
SUPPORTED_PLATFORMS = "watchsimulator watchos";
|
||||
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 = 11.6;
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
73ACDFC42E3D0E6100B63535 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
@@ -953,6 +1262,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianBroadcastExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
@@ -993,6 +1303,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianBroadcastExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -1031,6 +1342,7 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianBroadcastExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -1059,7 +1371,7 @@
|
||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -1072,8 +1384,10 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianShareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = "DEBUG $(inherited)";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
@@ -1102,7 +1416,7 @@
|
||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -1114,7 +1428,9 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianShareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
@@ -1142,7 +1458,7 @@
|
||||
INFOPLIST_FILE = SolianShareExtension/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = SolianShareExtension;
|
||||
INFOPLIST_KEY_NSHumanReadableCopyright = "";
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 15.0;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
@@ -1154,7 +1470,9 @@
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian.SolianShareExtension;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SKIP_INSTALL = YES;
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_EMIT_LOC_STRINGS = YES;
|
||||
SWIFT_ENABLE_EXPLICIT_MODULES = NO;
|
||||
SWIFT_VERSION = 5.0;
|
||||
TARGETED_DEVICE_FAMILY = "1,2";
|
||||
};
|
||||
@@ -1329,7 +1647,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = YES;
|
||||
ONLY_ACTIVE_ARCH = YES;
|
||||
SDKROOT = iphoneos;
|
||||
@@ -1380,7 +1698,7 @@
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE;
|
||||
GCC_WARN_UNUSED_FUNCTION = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 12.0;
|
||||
IPHONEOS_DEPLOYMENT_TARGET = 13.0;
|
||||
MTL_ENABLE_DEBUG_INFO = NO;
|
||||
SDKROOT = iphoneos;
|
||||
SUPPORTED_PLATFORMS = iphoneos;
|
||||
@@ -1402,6 +1720,7 @@
|
||||
CUSTOM_GROUP_ID = group.solsynth.solian;
|
||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||
ENABLE_BITCODE = NO;
|
||||
EXCLUDED_SOURCE_FILE_NAMES = "";
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
@@ -1412,10 +1731,12 @@
|
||||
);
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ENABLE_EXPLICIT_MODULES = "$(SWIFT_USE_INTEGRATED_DRIVER)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 11.6;
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
@@ -1430,6 +1751,7 @@
|
||||
CUSTOM_GROUP_ID = group.solsynth.solian;
|
||||
DEVELOPMENT_TEAM = W7HPZ53V6B;
|
||||
ENABLE_BITCODE = NO;
|
||||
EXCLUDED_SOURCE_FILE_NAMES = "";
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
INFOPLIST_KEY_CFBundleDisplayName = Solian;
|
||||
INFOPLIST_KEY_LSApplicationCategoryType = "public.app-category.social-networking";
|
||||
@@ -1438,11 +1760,15 @@
|
||||
"$(inherited)",
|
||||
"@executable_path/Frameworks",
|
||||
);
|
||||
ONLY_ACTIVE_ARCH = NO;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = dev.solsynth.solian;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SUPPORTED_PLATFORMS = "iphonesimulator iphoneos";
|
||||
SWIFT_ENABLE_EXPLICIT_MODULES = "$(SWIFT_USE_INTEGRATED_DRIVER)";
|
||||
SWIFT_OBJC_BRIDGING_HEADER = "Runner/Runner-Bridging-Header.h";
|
||||
SWIFT_VERSION = 5.0;
|
||||
VERSIONING_SYSTEM = "apple-generic";
|
||||
WATCHOS_DEPLOYMENT_TARGET = 11.6;
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
@@ -1459,6 +1785,16 @@
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
7310A7E32EB10963002C0FD3 /* Build configuration list for PBXNativeTarget "Solian Watch App" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
7310A7E02EB10963002C0FD3 /* Debug */,
|
||||
7310A7E12EB10963002C0FD3 /* Release */,
|
||||
7310A7E22EB10963002C0FD3 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
73ACDFCB2E3D0E6100B63535 /* Build configuration list for PBXNativeTarget "SolianBroadcastExtension" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
||||
@@ -20,6 +20,20 @@
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
buildForRunning = "YES"
|
||||
buildForProfiling = "YES"
|
||||
buildForArchiving = "YES"
|
||||
buildForAnalyzing = "YES">
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "7310A7D32EB10962002C0FD3"
|
||||
BuildableName = "Solian Watch App.app"
|
||||
BlueprintName = "Solian Watch App"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</BuildActionEntry>
|
||||
</BuildActionEntries>
|
||||
</BuildAction>
|
||||
<TestAction
|
||||
|
||||
@@ -1,18 +1,20 @@
|
||||
import Flutter
|
||||
import UIKit
|
||||
import WatchConnectivity
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
let notifyDelegate = NotifyDelegate()
|
||||
|
||||
private static var sharedWatchConnectivityService: WatchConnectivityService?
|
||||
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
UNUserNotificationCenter.current().delegate = notifyDelegate
|
||||
|
||||
|
||||
let replyableMessageCategory = UNNotificationCategory(
|
||||
identifier: "REPLYABLE_MESSAGE",
|
||||
identifier: "CHAT_MESSAGE",
|
||||
actions: [
|
||||
UNTextInputNotificationAction(
|
||||
identifier: "reply_action",
|
||||
@@ -23,11 +25,85 @@ import UIKit
|
||||
intentIdentifiers: [],
|
||||
options: []
|
||||
)
|
||||
|
||||
UNUserNotificationCenter.current().setNotificationCategories([replyableMessageCategory])
|
||||
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
|
||||
// Always initialize and retain a strong reference
|
||||
if WCSession.isSupported() {
|
||||
AppDelegate.sharedWatchConnectivityService = WatchConnectivityService.shared
|
||||
} else {
|
||||
print("[iOS] WCSession not supported on this device.")
|
||||
}
|
||||
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
}
|
||||
|
||||
final class WatchConnectivityService: NSObject, WCSessionDelegate {
|
||||
static let shared = WatchConnectivityService()
|
||||
private let session: WCSession = .default
|
||||
|
||||
private override init() {
|
||||
super.init()
|
||||
print("[iOS] Activating WCSession...")
|
||||
session.delegate = self
|
||||
session.activate()
|
||||
}
|
||||
|
||||
// MARK: - WCSessionDelegate
|
||||
|
||||
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
|
||||
if let error = error {
|
||||
print("[iOS] WCSession activation failed: \(error.localizedDescription)")
|
||||
} else {
|
||||
print("[iOS] WCSession activated with state: \(activationState.rawValue)")
|
||||
if activationState == .activated {
|
||||
sendDataToWatch()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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()
|
||||
|
||||
var data: [String: Any] = ["serverUrl": serverUrl ?? ""]
|
||||
if let token = token {
|
||||
data["token"] = token
|
||||
}
|
||||
|
||||
print("[iOS] Replying with data: \(data)")
|
||||
replyHandler(data)
|
||||
}
|
||||
}
|
||||
|
||||
func sendDataToWatch() {
|
||||
guard session.activationState == .activated else {
|
||||
return
|
||||
}
|
||||
|
||||
let token = UserDefaults.standard.getFlutterToken()
|
||||
let serverUrl = UserDefaults.standard.getServerUrl()
|
||||
|
||||
var data: [String: Any] = ["serverUrl": serverUrl ?? ""]
|
||||
if let token = token {
|
||||
data["token"] = token
|
||||
}
|
||||
|
||||
do {
|
||||
try session.updateApplicationContext(data)
|
||||
print("[iOS] Sent application context: \(data)")
|
||||
} catch {
|
||||
print("[iOS] Failed to send application context: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 |
@@ -1,98 +1,111 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>AppGroupId</key>
|
||||
<string>$(CUSTOM_GROUP_ID)</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>dev.solsynth.solian</string>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Solian</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>solian</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>CLIENT_ID</key>
|
||||
<string>961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSCalendarsUsageDescription</key>
|
||||
<string>Grant access to Calander help us to shows Solar Calander with your own events.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Grant access to Camera will allow Solian take photo or video for your post.</string>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>Allow the Solar Network verify your ownership of the logged in account and continue your action quickly.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Grant access to Microphone will allow Solian record audio for your post.</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>Grant access to Photo Library will allow Solian download photo to album for you.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Grant access to Photo Library will allow Solian upload photo or video for your post.</string>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>INStartCallIntent</string>
|
||||
<string>INSendMessageIntent</string>
|
||||
</array>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>REVERSED_CLIENT_ID</key>
|
||||
<string>com.googleusercontent.apps.961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>audio</string>
|
||||
<string>remote-notification</string>
|
||||
<string>voip</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false/>
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
<dict>
|
||||
<key>AppGroupId</key>
|
||||
<string>$(CUSTOM_GROUP_ID)</string>
|
||||
<key>BUNDLE_ID</key>
|
||||
<string>dev.solsynth.solian</string>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true />
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>Solian</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>solian</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>APPL</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>ShareMedia-$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
</array>
|
||||
</dict>
|
||||
<dict>
|
||||
<key>CFBundleTypeRole</key>
|
||||
<string>Editor</string>
|
||||
<key>CFBundleURLName</key>
|
||||
<string></string>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>solian</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>CLIENT_ID</key>
|
||||
<string>961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig.apps.googleusercontent.com</string>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false />
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true />
|
||||
<key>NSCalendarsUsageDescription</key>
|
||||
<string>Grant access to Calander help us to shows Solar Calander with your own events.</string>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>Grant access to Camera will allow Solian take photo or video for your post.</string>
|
||||
<key>NSFaceIDUsageDescription</key>
|
||||
<string>Allow the Solar Network verify your ownership of the logged in account and continue
|
||||
your action quickly.</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>Grant access to Microphone will allow Solian record audio for your post.</string>
|
||||
<key>NSPhotoLibraryAddUsageDescription</key>
|
||||
<string>Grant access to Photo Library will allow Solian download photo to album for you.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>Grant access to Photo Library will allow Solian upload photo or video for your post.</string>
|
||||
<key>NSUserActivityTypes</key>
|
||||
<array>
|
||||
<string>INStartCallIntent</string>
|
||||
<string>INSendMessageIntent</string>
|
||||
</array>
|
||||
<key>PLIST_VERSION</key>
|
||||
<string>1</string>
|
||||
<key>REVERSED_CLIENT_ID</key>
|
||||
<string>com.googleusercontent.apps.961776991058-stt7et4qvn3cpscl4r61gl1hnlatqkig</string>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true />
|
||||
<key>UIBackgroundModes</key>
|
||||
<array>
|
||||
<string>fetch</string>
|
||||
<string>audio</string>
|
||||
<string>remote-notification</string>
|
||||
<string>voip</string>
|
||||
</array>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
<string>LaunchScreen</string>
|
||||
<key>UIMainStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
<key>UIStatusBarHidden</key>
|
||||
<false />
|
||||
<key>UISupportedInterfaceOrientations</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
</array>
|
||||
<key>WKCompanionAppBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>UISupportedInterfaceOrientations~ipad</key>
|
||||
<array>
|
||||
<string>UIInterfaceOrientationLandscapeLeft</string>
|
||||
<string>UIInterfaceOrientationLandscapeRight</string>
|
||||
<string>UIInterfaceOrientationPortrait</string>
|
||||
<string>UIInterfaceOrientationPortraitUpsideDown</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
@@ -8,7 +8,7 @@
|
||||
import Foundation
|
||||
|
||||
func getAttachmentUrl(for identifier: String) -> String {
|
||||
let serverBaseUrl = "https://api.solian.app"
|
||||
let serverBaseUrl = UserDefaults.standard.getServerUrl()
|
||||
|
||||
return identifier.starts(with: "http") ? identifier : "\(serverBaseUrl)/drive/files/\(identifier)"
|
||||
}
|
||||
|
||||
@@ -26,6 +26,6 @@ extension UserDefaults {
|
||||
}
|
||||
|
||||
func getServerUrl(forKey key: String = "app_server_url") -> String {
|
||||
return self.getFlutterValue(forKey: key) ?? "https://nt.solian.app"
|
||||
return self.getFlutterValue(forKey: key) ?? "https://api.solian.app"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,15 @@
|
||||
{
|
||||
"colors" : [
|
||||
{
|
||||
"color" : {
|
||||
"platform" : "universal",
|
||||
"reference" : "systemIndigoColor"
|
||||
},
|
||||
"idiom" : "universal"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,318 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon-ios-20x20@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-20x20@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "20x20"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-29x29@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-29x29@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-38x38@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "38x38"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-38x38@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "38x38"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-40x40@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-40x40@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-60x60@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-60x60@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "60x60"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-64x64@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "64x64"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-64x64@3x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "3x",
|
||||
"size" : "64x64"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-68x68@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "68x68"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-76x76@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "76x76"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-83.5x83.5@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"scale" : "2x",
|
||||
"size" : "83.5x83.5"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-ios-1024x1024.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "ios",
|
||||
"size" : "1024x1024"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-16x16.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-16x16@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "16x16"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-32x32.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-32x32@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-128x128.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-128x128@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "128x128"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-256x256.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-256x256@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "256x256"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-512x512.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "1x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-mac-512x512@2x.png",
|
||||
"idiom" : "mac",
|
||||
"scale" : "2x",
|
||||
"size" : "512x512"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-22x22@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "22x22"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-24x24@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "24x24"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-27.5x27.5@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "27.5x27.5"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-29x29@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "29x29"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-30x30@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "30x30"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-32x32@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "32x32"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-33x33@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "33x33"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-40x40@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "40x40"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-43.5x43.5@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "43.5x43.5"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-44x44@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "44x44"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-46x46@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "46x46"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-50x50@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "50x50"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-51x51@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "51x51"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-54x54@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "54x54"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-86x86@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "86x86"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-98x98@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "98x98"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-108x108@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "108x108"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-117x117@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "117x117"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-129x129@2x.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"scale" : "2x",
|
||||
"size" : "129x129"
|
||||
},
|
||||
{
|
||||
"filename" : "icon-watchos-1024x1024.png",
|
||||
"idiom" : "universal",
|
||||
"platform" : "watchos",
|
||||
"size" : "1024x1024"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 1.5 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 3.4 KiB |
|
After Width: | Height: | Size: 5.7 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 6.1 KiB |
|
After Width: | Height: | Size: 9.6 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 7.0 KiB |
|
After Width: | Height: | Size: 7.8 KiB |
|
After Width: | Height: | Size: 8.8 KiB |
|
After Width: | Height: | Size: 6.6 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 473 B |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 1.2 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 30 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 45 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 14 KiB |
|
After Width: | Height: | Size: 1.7 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 2.4 KiB |
|
After Width: | Height: | Size: 2.5 KiB |
|
After Width: | Height: | Size: 2.7 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.6 KiB |
|
After Width: | Height: | Size: 4.1 KiB |
|
After Width: | Height: | Size: 4.2 KiB |
|
After Width: | Height: | Size: 4.4 KiB |
|
After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 5.0 KiB |
|
After Width: | Height: | Size: 5.3 KiB |
|
After Width: | Height: | Size: 9.1 KiB |
|
After Width: | Height: | Size: 10 KiB |
6
ios/Solian Watch App/Assets.xcassets/Contents.json
Normal file
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
21
ios/Solian Watch App/Assets.xcassets/Logo.imageset/Contents.json
vendored
Normal file
@@ -0,0 +1,21 @@
|
||||
{
|
||||
"images" : [
|
||||
{
|
||||
"filename" : "icon.png",
|
||||
"idiom" : "universal",
|
||||
"scale" : "1x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "2x"
|
||||
},
|
||||
{
|
||||
"idiom" : "universal",
|
||||
"scale" : "3x"
|
||||
}
|
||||
],
|
||||
"info" : {
|
||||
"author" : "xcode",
|
||||
"version" : 1
|
||||
}
|
||||
}
|
||||
0
android/app/src/main/res/drawable/ic_notification.png → ios/Solian Watch App/Assets.xcassets/Logo.imageset/icon.png
vendored
Executable file → Normal file
|
Before Width: | Height: | Size: 70 KiB After Width: | Height: | Size: 70 KiB |
50
ios/Solian 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) {
|
||||
AppInfoHeaderView()
|
||||
.listRowBackground(Color.clear)
|
||||
.environmentObject(appState)
|
||||
|
||||
Label("Explore", systemImage: "globe.fill").tag(Panel.explore)
|
||||
Label("Chat", systemImage: "message.fill").tag(Panel.chat)
|
||||
Label("Notifications", systemImage: "bell.fill").tag(Panel.notifications)
|
||||
Label("Account", systemImage: "person.circle.fill").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/Solian 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/Solian 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"
|
||||
}
|
||||
}
|
||||
95
ios/Solian Watch App/Services/ImageLoader.swift
Normal file
@@ -0,0 +1,95 @@
|
||||
//
|
||||
// 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)
|
||||
self.isLoading = false
|
||||
case .failure(_):
|
||||
// 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)
|
||||
case .failure(let fallbackError):
|
||||
self.errorMessage = fallbackError.localizedDescription
|
||||
print("[watchOS] Image loading failed: \(fallbackError.localizedDescription)")
|
||||
}
|
||||
self.isLoading = false
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func cancel() {
|
||||
currentTask?.cancel()
|
||||
}
|
||||
}
|
||||
643
ios/Solian Watch App/Services/NetworkService.swift
Normal file
@@ -0,0 +1,643 @@
|
||||
//
|
||||
// NetworkService.swift
|
||||
// WatchRunner Watch App
|
||||
//
|
||||
// Created by LittleSheep on 2025/10/29. //
|
||||
|
||||
import Combine
|
||||
import Foundation
|
||||
|
||||
// MARK: - WebSocket Data Structures
|
||||
|
||||
enum WebSocketState: Equatable {
|
||||
case connected
|
||||
case connecting
|
||||
case disconnected
|
||||
case serverDown
|
||||
case duplicateDevice
|
||||
case error(String)
|
||||
|
||||
// Equatable conformance
|
||||
static func == (lhs: WebSocketState, rhs: WebSocketState) -> Bool {
|
||||
switch (lhs, rhs) {
|
||||
case (.connected, .connected),
|
||||
(.connecting, .connecting),
|
||||
(.disconnected, .disconnected),
|
||||
(.serverDown, .serverDown),
|
||||
(.duplicateDevice, .duplicateDevice):
|
||||
return true
|
||||
case let (.error(a), .error(b)):
|
||||
return a == b
|
||||
default:
|
||||
return false
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
struct WebSocketPacket {
|
||||
let type: String
|
||||
let data: [String: Any]?
|
||||
let endpoint: String?
|
||||
let errorMessage: String?
|
||||
}
|
||||
|
||||
// MARK: - Network Service
|
||||
|
||||
class NetworkService {
|
||||
private let session: URLSession
|
||||
|
||||
init() {
|
||||
let config = URLSessionConfiguration.ephemeral
|
||||
config.waitsForConnectivity = true
|
||||
session = URLSession(configuration: config)
|
||||
}
|
||||
|
||||
// Add a serial queue for WebSocket operations
|
||||
private let webSocketQueue = DispatchQueue(label: "com.solian.websocketQueue")
|
||||
|
||||
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)!
|
||||
let 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 {
|
||||
print("error: ", error)
|
||||
throw error
|
||||
}
|
||||
}
|
||||
|
||||
// MARK: - WebSocket
|
||||
|
||||
private var webSocketTask: URLSessionWebSocketTask?
|
||||
private var heartbeatTimer: Timer?
|
||||
private var reconnectTimer: Timer?
|
||||
private var isDisconnectingManually = false
|
||||
|
||||
private var lastToken: String?
|
||||
private var lastServerUrl: String?
|
||||
|
||||
private var heartbeatAt: Date?
|
||||
var heartbeatDelay: TimeInterval?
|
||||
|
||||
private let connectLock = NSLock()
|
||||
|
||||
private let packetSubject = PassthroughSubject<WebSocketPacket, Error>()
|
||||
private let stateSubject = CurrentValueSubject<WebSocketState, Never>(.disconnected) // Changed to CurrentValueSubject
|
||||
|
||||
private var currentConnectionState: WebSocketState = .disconnected { // New property
|
||||
didSet {
|
||||
// Only send updates if the state has actually changed
|
||||
if oldValue != currentConnectionState {
|
||||
stateSubject.send(currentConnectionState)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var packetStream: AnyPublisher<WebSocketPacket, Error> {
|
||||
packetSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
var stateStream: AnyPublisher<WebSocketState, Never> {
|
||||
stateSubject.eraseToAnyPublisher()
|
||||
}
|
||||
|
||||
func connectWebSocket(token: String, serverUrl: String) {
|
||||
webSocketQueue.async { [weak self] in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.connectLock.lock()
|
||||
defer { self.connectLock.unlock() }
|
||||
|
||||
// Prevent redundant connection attempts
|
||||
if self.currentConnectionState == .connecting || self.currentConnectionState == .connected {
|
||||
print("[WebSocket] Already connecting or connected, ignoring new connect request.")
|
||||
return
|
||||
}
|
||||
|
||||
self.currentConnectionState = .connecting
|
||||
|
||||
// Ensure any existing task is cancelled before starting a new one
|
||||
self.webSocketTask?.cancel(with: .goingAway, reason: nil)
|
||||
self.webSocketTask = nil
|
||||
|
||||
self.isDisconnectingManually = false // Reset this flag for a new connection attempt
|
||||
|
||||
self.lastToken = token
|
||||
self.lastServerUrl = serverUrl
|
||||
|
||||
guard var urlComponents = URLComponents(string: serverUrl) else {
|
||||
self.currentConnectionState = .error("Invalid server URL")
|
||||
return
|
||||
}
|
||||
|
||||
urlComponents.scheme = urlComponents.scheme?.replacingOccurrences(of: "http", with: "ws")
|
||||
urlComponents.path = "/ws"
|
||||
urlComponents.queryItems = [URLQueryItem(name: "deviceAlt", value: "watch")]
|
||||
|
||||
guard let url = urlComponents.url else {
|
||||
self.currentConnectionState = .error("Invalid WebSocket URL")
|
||||
return
|
||||
}
|
||||
|
||||
var request = URLRequest(url: url)
|
||||
request.setValue("AtField \(token)", forHTTPHeaderField: "Authorization")
|
||||
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
|
||||
|
||||
print("[WebSocket] Trying connecting to \(url)")
|
||||
|
||||
self.webSocketTask = self.session.webSocketTask(with: request)
|
||||
self.webSocketTask?.resume()
|
||||
|
||||
self.listenForWebSocketMessages()
|
||||
self.scheduleHeartbeat()
|
||||
self.currentConnectionState = .connected
|
||||
}
|
||||
}
|
||||
|
||||
private func listenForWebSocketMessages() {
|
||||
// Ensure webSocketTask is still valid before attempting to receive
|
||||
guard let task = webSocketTask else {
|
||||
print("[WebSocket] listenForWebSocketMessages: webSocketTask is nil, stopping listen.")
|
||||
return
|
||||
}
|
||||
|
||||
task.receive { [weak self] result in
|
||||
guard let self = self else { return }
|
||||
|
||||
switch result {
|
||||
case .failure(let error):
|
||||
print("[WebSocket] Error in receiving message: \(error)")
|
||||
// Only attempt to reconnect if not manually disconnecting
|
||||
if !self.isDisconnectingManually {
|
||||
self.currentConnectionState = .error(error.localizedDescription)
|
||||
self.scheduleReconnect()
|
||||
} else {
|
||||
// If manually disconnecting, just ensure state is disconnected
|
||||
self.currentConnectionState = .disconnected
|
||||
}
|
||||
case .success(let message):
|
||||
switch message {
|
||||
case .string(let text):
|
||||
self.handleWebSocketMessage(text: text)
|
||||
case .data(let data):
|
||||
if let text = String(data: data, encoding: .utf8) {
|
||||
self.handleWebSocketMessage(text: text)
|
||||
}
|
||||
@unknown default:
|
||||
break
|
||||
}
|
||||
// Continue listening for next message only if task is still valid
|
||||
if self.webSocketTask === task { // Check if it's the same task
|
||||
self.listenForWebSocketMessages()
|
||||
} else {
|
||||
print("[WebSocket] listenForWebSocketMessages: Task changed, stopping listen for old task.")
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private func handleWebSocketMessage(text: String) {
|
||||
guard let data = text.data(using: .utf8) else {
|
||||
print("[WebSocket] Could not convert message to data")
|
||||
return
|
||||
}
|
||||
|
||||
do {
|
||||
if let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any],
|
||||
let type = json["type"] as? String
|
||||
{
|
||||
let packet = WebSocketPacket(
|
||||
type: type,
|
||||
data: json["data"] as? [String: Any],
|
||||
endpoint: json["endpoint"] as? String,
|
||||
errorMessage: json["errorMessage"] as? String
|
||||
)
|
||||
|
||||
print("[WebSocket] Received packet: \(packet.type) \(packet.errorMessage ?? "")")
|
||||
|
||||
if packet.type == "error.dupe" {
|
||||
self.currentConnectionState = .duplicateDevice
|
||||
self.disconnectWebSocket()
|
||||
return
|
||||
}
|
||||
|
||||
if packet.type == "pong" {
|
||||
if let beatAt = self.heartbeatAt {
|
||||
let now = Date()
|
||||
self.heartbeatDelay = now.timeIntervalSince(beatAt)
|
||||
print("[WebSocket] Server respond last heartbeat for \((self.heartbeatDelay ?? 0) * 1000) ms")
|
||||
}
|
||||
}
|
||||
|
||||
self.packetSubject.send(packet)
|
||||
}
|
||||
} catch {
|
||||
print("[WebSocket] Could not parse message json: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
|
||||
private func scheduleReconnect() {
|
||||
reconnectTimer?.invalidate()
|
||||
reconnectTimer = Timer.scheduledTimer(withTimeInterval: 0.5, repeats: false) { [weak self] _ in
|
||||
guard let self = self, let token = self.lastToken, let serverUrl = self.lastServerUrl else { return }
|
||||
print("[WebSocket] Attempting to reconnect...")
|
||||
|
||||
// No need to call disconnectWebSocket here, connectWebSocket will handle cancelling old task
|
||||
self.isDisconnectingManually = false // Reset for the new connection attempt
|
||||
|
||||
self.connectWebSocket(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
}
|
||||
|
||||
private func scheduleHeartbeat() {
|
||||
heartbeatTimer?.invalidate()
|
||||
heartbeatTimer = Timer.scheduledTimer(withTimeInterval: 60.0, repeats: true) { [weak self] _ in
|
||||
self?.beatTheHeart()
|
||||
}
|
||||
}
|
||||
|
||||
private func beatTheHeart() {
|
||||
heartbeatAt = Date()
|
||||
print("[WebSocket] We\'re beating the heart! \(String(describing: self.heartbeatAt))")
|
||||
sendWebSocketMessage(message: "{\"type\":\"ping\"}")
|
||||
}
|
||||
|
||||
func sendWebSocketMessage(message: String) {
|
||||
webSocketTask?.send(.string(message)) { error in
|
||||
if let error = error {
|
||||
print("[WebSocket] Error sending message: \(error.localizedDescription)")
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func disconnectWebSocket() {
|
||||
isDisconnectingManually = true
|
||||
reconnectTimer?.invalidate()
|
||||
heartbeatTimer?.invalidate()
|
||||
|
||||
// Cancel the task and then nil it out
|
||||
webSocketTask?.cancel(with: .goingAway, reason: nil)
|
||||
webSocketTask = nil // Set to nil immediately after cancelling
|
||||
|
||||
self.currentConnectionState = .disconnected
|
||||
}
|
||||
}
|
||||
58
ios/Solian Watch App/State/AppState.swift
Normal file
@@ -0,0 +1,58 @@
|
||||
//
|
||||
// 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
|
||||
@Published var errorMessage: String? = nil
|
||||
|
||||
let networkService = NetworkService()
|
||||
private var wcService = WatchConnectivityService()
|
||||
private var cancellables = Set<AnyCancellable>()
|
||||
private var hasAttemptedConnection = false
|
||||
|
||||
init() {
|
||||
wcService.$token.combineLatest(wcService.$serverUrl, wcService.$isFetched, wcService.$errorMessage)
|
||||
.receive(on: DispatchQueue.main)
|
||||
.sink { [weak self] (token: String?, serverUrl: String?, isFetched: Bool?, errorMessage: String?) in
|
||||
guard let self = self else { return }
|
||||
|
||||
self.token = token
|
||||
self.serverUrl = serverUrl
|
||||
self.errorMessage = errorMessage
|
||||
|
||||
if let token = token, let serverUrl = serverUrl, !token.isEmpty, !serverUrl.isEmpty {
|
||||
self.isReady = true
|
||||
// Only connect once when we have valid credentials and tried fetch from phone
|
||||
if !self.hasAttemptedConnection && isFetched == true {
|
||||
self.hasAttemptedConnection = true
|
||||
print("[AppState] Connecting WebSocket to server: \(serverUrl)")
|
||||
self.networkService.connectWebSocket(token: token, serverUrl: serverUrl)
|
||||
}
|
||||
} else {
|
||||
self.isReady = false
|
||||
if self.hasAttemptedConnection {
|
||||
self.hasAttemptedConnection = false
|
||||
// Disconnect WebSocket if token or serverUrl become invalid
|
||||
self.networkService.disconnectWebSocket()
|
||||
}
|
||||
}
|
||||
}
|
||||
.store(in: &cancellables)
|
||||
}
|
||||
|
||||
func requestData() {
|
||||
wcService.requestDataFromPhone()
|
||||
}
|
||||
}
|
||||