Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
01b13b4764 |
|||
|
050e42cc6f |
|||
|
67cee201b6 |
|||
|
2d7b067c93 |
|||
|
a9993013f5 |
|||
|
9c488e8981 |
|||
|
5c16f42d20 |
|||
|
092fc616e6 |
|||
|
6cbf78be6b |
|||
|
68f4bb0c03 |
|||
|
9e24f4cb31 |
|||
|
43d2e94d62 |
|||
|
62fe37c6ae |
|||
|
b9dfbd3ca2 |
|||
|
620440e2a1 |
|||
|
724171384c |
|||
|
1bd677eb23 |
|||
|
41658c3a9d |
|||
|
b011cc2166 |
|||
|
75ad6cbd02 |
|||
|
6c1d3d8894 |
|||
|
842ab0a82c |
|||
|
a0e5d2fb9e |
|||
|
a2cdc3df68 |
|||
|
07f8a35b74 |
|||
|
85b9007c47 |
|||
|
5bbd51c4bc |
|||
|
21a0e0db70 |
|||
|
a5f42fe56e |
|||
|
185c1d2714 |
|||
|
7eab09585b |
|||
|
c84f0e7e93 |
|||
|
f7847d587c |
|||
|
56dbd91c96 |
|||
| 7bb4d87638 | |||
|
bf31f5510a |
|||
|
bd185824f9 |
|||
|
2afd5ae258 |
|||
|
76f9175857 |
|||
|
e32941f062 |
|||
|
cf89604ff5 |
|||
|
83e8084213 |
|||
|
ae5b6e2b40 |
|||
|
1621e917c0 |
|||
|
d1c2b2dd0a |
|||
|
82a0dd90b0 |
|||
|
f97c5548a3 |
|||
|
115bec5f05 |
|||
|
fc4aa5a10d |
|||
|
f3c31db244 |
|||
|
419d75ca83 |
|||
|
9831446c66 |
|||
|
d7f49568a7 |
|||
|
f0f426a647 |
|||
|
80fa9673bb |
|||
|
8c25228bd9 |
|||
|
9bf664624a |
|||
|
e8b90591d5 |
|||
|
b2813a0eb5 |
|||
|
9298eb815d |
|||
|
06075f75c5 |
|||
|
60968f5f3e |
|||
|
afd6168535 |
|||
|
2a1cc33ee3 |
|||
|
5f13d3fbf5 |
|||
|
eca9d3b411 |
|||
|
16fdf0c420 |
|||
|
3536f74851 |
|||
|
fa451621de |
|||
|
90230651e6 |
|||
|
92b88e46ac |
|||
|
1799e02844 |
|||
|
cf26ec7130 |
|||
|
716541b457 |
|||
|
965c7ea2dc |
|||
|
85d02f2ac9 |
|||
|
1c446c4cdf |
|||
|
51430d2830 |
|||
|
4e208764f5 |
|||
|
eecc307f04 |
|||
|
6221eb4a7a |
|||
|
370549072e |
|||
|
80b938c0be |
|||
|
87e1ef0d9b |
|||
|
f8c705531c |
|||
|
2a91959333 |
|||
|
34ddd6d32b |
|||
|
a8726feef6 |
|||
|
bd1bad76d7 |
|||
|
c4f63d18b5 |
|||
|
a8285548e8 |
|||
|
cdad9b760e |
|||
|
06c5411dfc |
|||
|
f6b5bd4057 |
|||
|
0da3b4da22 |
|||
|
a557cffdbf |
|||
|
9d7156d176 |
|||
|
b792247575 |
|||
|
35fbe1094f |
|||
|
05d1c3b04a |
|||
|
22e58e3d05 |
|||
|
09bc9bdcbd |
|||
| 7d106ad3a2 | |||
|
5df975f607 |
|||
|
8f3f9fbef1 |
|||
|
a9ac891ec4 |
|||
|
7992f0e815 |
|||
|
15d441e4c4 |
|||
|
7492d3a3d4 |
|||
|
518b0dd11e |
|||
| 0ef9b25320 | |||
|
06824784cb |
|||
|
08d67553be |
|||
|
8b2d354a60 |
|||
|
8773faf7c4 |
|||
| 818e582ddd | |||
|
71a4274ff2 |
|||
|
7b734a89ac |
|||
|
ceb749d272 |
|||
|
45240f6cb0 |
|||
|
4c90fbd7d1 |
|||
|
8e76da4ac2 |
|||
|
195ebc776a |
|||
|
a1e217ac78 |
|||
|
148bc8f95c |
|||
|
b037dc06c8 |
|||
|
3c7c74f745 |
|||
|
b727d0342d |
|||
|
db5735e9e2 |
|||
|
7c01611859 |
|||
|
632c02a517 |
|||
|
355c564123 |
|||
|
1af957d4a1 |
|||
|
1986e2a627 |
|||
| ab40600746 | |||
|
2d0f41000e |
|||
|
3349ca7253 |
|||
|
18657eb980 |
|||
|
b4b157c39f |
|||
|
a76b6e6ed3 |
|||
|
5bbd472999 |
|||
|
6c0e149c25 |
|||
|
b26c144eea |
|||
|
ddc8db8326 |
|||
|
bc307cbcda |
|||
|
e40de37b9d |
|||
|
7757825e27 |
|||
|
795e9b6e9b |
|||
|
abba60c28b |
|||
|
8cea4b6cf3 |
|||
|
d46646d781 |
|||
|
e15d947fac |
|||
|
562ce5d4ff |
|||
|
f60189bfb8 |
|||
|
309d0df581 |
|||
|
3310d9b907 |
|||
|
8c047827de |
|||
|
d513e466fd |
|||
|
84a729aea8 |
|||
|
23e0aa3c4e |
|||
|
f0a26b58d1 |
|||
|
78b5abea7d |
|||
|
e1d7a30a06 |
|||
|
0c61623a94 |
|||
|
0a9b71230b |
|||
|
15c057707f |
|||
|
9cc18e16b8 |
|||
|
240984a832 |
|||
|
633e83b915 |
|||
|
c5122fc34f |
|||
|
457de3c77c |
|||
|
c9aa0173d8 |
|||
|
22aa26fd05 |
|||
|
c10c74a1f3 |
|||
|
46136c09ad |
|||
|
5f9622e1c9 |
|||
|
6e02cce84f |
|||
|
7e7e6877e2 |
|||
|
895ab3c96f |
|||
|
b25840756d |
|||
|
735a3357d7 |
|||
|
02b7892fb0 |
|||
|
3afb4befa5 |
|||
|
a11663eece |
|||
|
7f12efd338 |
|||
|
fcdada6f3e |
|||
|
0c950247b0 |
|||
|
27dca24889 |
|||
|
621bb74cc9 |
|||
|
33c3a568f9 |
|||
|
561f6ecc84 |
|||
|
a7ccf0ff00 |
|||
|
0e984fd95b |
|||
|
c898b2671a |
|||
|
e63e5a8c08 |
|||
|
a87c9dc678 |
|||
|
5fcc31b427 |
|||
|
99270f4bd1 |
|||
|
d2ec5f035b |
|||
|
6281c1d13a |
|||
|
60315de04a |
|||
|
eb87cbc17b |
|||
|
130dbac879 |
|||
|
2dd3fed62f |
|||
|
f60a499875 |
|||
|
a72ef5ea2d |
|||
|
1b81e31c13 |
|||
|
db12fd2e9a |
|||
|
60454ed249 |
|||
|
0a333e92d1 |
|||
|
31c3173bb5 |
|||
|
c6904e9766 |
|||
|
e5b7512e79 |
|||
|
5daa861a31 |
|||
|
82860deff1 |
|||
|
2ec442b35b |
|||
|
786c8cb3e2 |
|||
|
a150ef2ecf |
|||
|
bb037c8162 |
|||
|
eac59c58f5 |
|||
|
4e5c709fb9 |
|||
|
451875b137 |
|||
|
e1c81b504a |
|||
|
f27db22151 |
|||
|
3d6ebedd94 |
|||
|
70eba46c76 |
|||
|
ec64a81fed |
|||
|
2ba620350d |
|||
|
a0c2eefc1e |
|||
|
9939e59429 |
|||
|
e69f04f6e7 |
|||
|
4848840538 |
|||
|
64b3127fd1 |
|||
|
b836c3b06e |
|||
|
d9f62a9de9 |
|||
|
32dd08fd91 |
|||
|
6de046bf7b |
|||
|
ebbb4dc662 |
|||
|
1d6a121ec4 |
|||
|
ed0292468a |
|||
|
8b310c955d |
|||
|
14b140e23d |
|||
|
b47e61e005 |
|||
|
05bc9034d1 |
|||
|
d7ea233b18 |
|||
|
70ffbedba4 |
|||
|
a1386790a9 |
|||
|
68d2f654cc |
|||
|
5368bacf1d |
|||
| 564fe3c964 | |||
| 16cf126df4 | |||
|
bd1d5ea745 |
|||
|
1ca802c78b |
|||
|
7b9eda2d36 |
|||
|
63eb001c09 |
|||
|
00c3503c1f |
|||
|
469a625c40 |
|||
|
66ef2de027 |
|||
|
972c143de2 |
|||
|
2f39985afb |
|||
|
0ab466d011 |
|||
|
7857bcdc2e |
|||
|
9faff092ed |
|||
|
0949fa6523 |
|||
|
e310f0f60e |
|||
|
7d8b267986 |
|||
|
c945c26413 |
|||
|
4dc16a5529 |
|||
|
ebd4b8a765 |
|||
|
26b95fac69 |
|||
|
152331b262 |
|||
|
5f56c52fe0 |
|||
|
a8ae10c9ce |
|||
| ad36dcb2f3 | |||
|
|
8b4cd75076 | ||
|
5a99616e9c |
|||
|
def69d85e7 |
|||
|
f4b2dcb824 |
|||
|
50e1a8e4c7 |
|||
|
82dab26fd4 |
|||
|
313dc377ec |
|||
|
b93f4c979c |
|||
|
b701da19dc |
|||
|
327c4066f3 |
|||
|
1282a8b897 |
|||
|
6ca974e6fc |
|||
|
e16a780fa3 |
|||
|
dc1eb52fe0 |
|||
|
3e8eba0872 |
|||
|
4954fb8c09 |
|||
|
4ff507e93f |
|||
|
1dcf3018a2 |
|||
|
6b8eef3f17 |
|||
|
f997e257a2 |
|||
|
07decc10e2 |
|||
|
e9b78a14d5 |
|||
|
7b2a6b84ad |
|||
|
5154e0fc6b |
|||
|
3cfbe7c078 |
|||
|
133e613214 |
|||
|
5e07cec14d |
|||
|
116649e8d7 |
|||
|
5f5ad911c2 |
|||
|
624127f3a8 |
|||
|
f860d9651f |
|||
|
2850b015a1 |
|||
|
3a7e708e39 |
|||
|
798eb3c3fd |
|||
|
ee648ab105 |
|||
|
2c23951ea8 |
|||
|
f4b2669f3d |
|||
|
6fe5677a13 |
|||
|
729f71e529 |
|||
|
b80bd557dd |
|||
|
15d02458ab |
|||
|
8dff27c56f |
|||
|
c857b89899 |
|||
|
06d6bf0cbc |
|||
|
9fdf08a5d8 |
|||
|
7fc314036e |
|||
|
aac843d793 |
|||
|
639d27a5fc |
|||
|
92f6b2fbba |
|||
|
4aa962193d |
|||
|
24f5f7d0b6 |
|||
|
9464b2bf78 |
|||
|
fd4b16c700 |
|||
|
a8383951ba |
|||
|
185ee37f04 |
|||
|
f38715c8ef |
|||
|
63535fb462 |
|||
|
7c1918857a |
|||
|
20f0ce9fa5 |
|||
|
fa8b8ddd14 |
|||
|
c3ca1e3491 |
|||
|
8154d41dc5 |
|||
|
d70c439278 |
|||
|
5796d250c7 |
|||
|
a9c4acaa74 |
|||
|
73ac0018ca |
|||
|
a64cfd35be |
|||
|
f460a3bacc |
|||
|
51dd8c5668 |
|||
|
35bf379f03 |
|||
|
f4624c2866 |
|||
|
cadd5c1255 |
|||
|
3a1bcb5b8f |
|||
|
c130d28b93 |
|||
|
e669ede6fe |
|||
|
5a0a5cb138 |
|||
|
e30355a6f1 |
|||
|
4e4e387aa2 |
|||
|
2ead857805 |
|||
|
a562d043a8 |
|||
|
bb842abfb1 |
|||
|
0b9ddbfbc8 |
|||
|
7ee165b300 |
|||
|
60b7f22566 |
|||
|
e42aaeb30a |
|||
|
6d903a8882 |
|||
|
388e09abb7 |
|||
|
4dc692634e |
|||
|
0a6c097c50 |
|||
|
08cca4d3d3 |
|||
|
cdba3c480e |
|||
|
55ecbc3590 |
|||
|
8c7adbc9d3 |
|||
|
60be7aaf72 |
|||
|
e0ba99d9b9 |
|||
|
e2d29439d5 |
|||
|
92e5206326 |
|||
| ecc40bfe49 | |||
| eaf1f3a178 | |||
|
18ee13901c |
|||
|
c784094a4c |
|||
|
690d2549bc |
|||
|
ab61338382 |
|||
|
48adf82b7e |
|||
|
1f274307ad |
|||
|
c609de8279 |
|||
|
1d33eed829 |
|||
|
e6c47c036d |
|||
|
c6767863eb |
|||
|
f5c277e8b0 |
|||
|
84bed89632 |
|||
|
6c064cfcef |
|||
|
2c4d5670e5 |
|||
|
a51c869d7e |
|||
|
a1401f20ea |
|||
|
f8d6dcead5 |
|||
|
02c79a6d7c |
|||
|
11aef9fc5a |
|||
|
2f39949a2e |
|||
|
166295fdb5 |
|||
|
607cd54e02 |
|||
|
67b96ae731 |
|||
|
ed81b4afa1 |
|||
|
345fa3b5ff |
|||
|
f50fb6ab09 |
|||
|
5601fb27c0 |
|||
|
0d1f7c1819 |
|||
|
4bbf694479 |
|||
|
dd9b9fdc62 |
|||
|
8b7f88cc0b |
|||
|
70793a2f77 |
|||
|
b2c763deef |
|||
|
5c66d35017 |
|||
|
a25f9d2e73 |
|||
|
4a3b7e9a14 |
|||
|
6974e5cc06 |
|||
|
42c32b1b1c |
|||
|
87466f9d05 |
|||
|
ea72654887 |
|||
|
f1af130a63 |
|||
|
e7b772ef66 |
|||
|
28dfe9e981 |
|||
|
d4c98a0cfb |
|||
|
01772b567a |
|||
|
f9927d1eb3 |
|||
|
0d44d10e05 |
|||
|
11ecec5ab3 |
|||
|
b407bbfdee |
|||
|
04b7ab8e2e |
|||
|
0cae2692bc |
|||
|
b387f0755a |
|||
|
840f2fe464 |
|||
|
e5062683e8 |
|||
|
ffe879680d |
|||
|
32dfba178a |
|||
|
fe845e6cd6 |
|||
|
d3e6340b28 |
|||
|
b6e7bb82da |
|||
|
eb503ba647 |
|||
|
cda971a335 |
|||
| e4f666b824 | |||
| cf2150466e | |||
| 23bbbb533e | |||
|
db9fc597f3 |
|||
|
6839f0bdae |
|||
|
6f4ad046b0 |
|||
| 91516c2f20 |
39
.github/workflows/android.yml
vendored
Normal file
|
|
@ -0,0 +1,39 @@
|
|||
name: "Build APK"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-apk:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Lix GHA Installer Action
|
||||
uses: samueldr/lix-gha-installer-action@v2026-02-22
|
||||
with:
|
||||
extra_nix_config: experimental-features = nix-command flakes flake-self-attrs
|
||||
|
||||
- name: Decode keystore
|
||||
run: echo "$KEYSTORE_CONTENT" | base64 --decode > keystore.jks
|
||||
env:
|
||||
KEYSTORE_CONTENT: ${{ secrets.KEYSTORE_CONTENT }}
|
||||
|
||||
- name: Build app
|
||||
run: nix develop --command bash -c "flutter pub get && dart scripts/generate.dart && flutter pub run build_runner build && flutter build apk --release"
|
||||
env:
|
||||
KEYSTORE_PATH: ../../keystore.jks
|
||||
KEYSTORE_PASSWORD: ${{ secrets.KEYSTORE_PASSWORD }}
|
||||
|
||||
- name: Upload installer artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: APK
|
||||
path: build/app/outputs/flutter-apk/app-release.apk
|
||||
37
.github/workflows/flatpak.yml
vendored
Normal file
|
|
@ -0,0 +1,37 @@
|
|||
name: "Build Flatpaks"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-flatpak:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- arch: x86_64
|
||||
runner: ubuntu-latest
|
||||
- arch: aarch64
|
||||
runner: ubuntu-24.04-arm
|
||||
runs-on: ${{ matrix.runner }}
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
|
||||
- name: Lix GHA Installer Action
|
||||
uses: samueldr/lix-gha-installer-action@v2026-02-22
|
||||
with:
|
||||
extra_nix_config: experimental-features = nix-command flakes flake-self-attrs
|
||||
|
||||
- name: Build app
|
||||
run: nix build .#flatpak
|
||||
|
||||
- name: Upload installer artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: flatpak-${{ matrix.arch }}
|
||||
path: result/nexus.federated.nexus.flatpak
|
||||
48
.github/workflows/ios.yml
vendored
Normal file
|
|
@ -0,0 +1,48 @@
|
|||
name: "Build iOS App"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-app:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: 3.44.4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: gomuks/go.mod
|
||||
|
||||
- name: Build app
|
||||
run: |
|
||||
flutter pub get
|
||||
dart scripts/generate.dart
|
||||
flutter pub run build_runner build
|
||||
flutter build ios --release --no-codesign
|
||||
|
||||
# Unsigned IPA: SideStore/AltStore re-sign this on-device with the
|
||||
# user's own Apple ID at install time, so no certificate is needed here.
|
||||
- name: Package unsigned IPA
|
||||
run: |
|
||||
mkdir Payload
|
||||
cp -r build/ios/iphoneos/Runner.app Payload/
|
||||
zip -r Nexus.ipa Payload
|
||||
|
||||
- name: Upload IPA artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: Nexus.ipa
|
||||
path: Nexus.ipa
|
||||
47
.github/workflows/macos.yml
vendored
Normal file
|
|
@ -0,0 +1,47 @@
|
|||
name: "Build MacOS App"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-app:
|
||||
runs-on: macos-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
submodules: recursive
|
||||
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: 3.44.4
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: gomuks/go.mod
|
||||
|
||||
- name: Build App
|
||||
run: |
|
||||
flutter pub get
|
||||
dart scripts/generate.dart
|
||||
flutter pub run build_runner build
|
||||
flutter build macos --release
|
||||
|
||||
- name: Create DMG
|
||||
id: create-dmg
|
||||
uses: L-Super/create-dmg-actions@28511e988b13ca34096d439159a66d468b8e724f
|
||||
with:
|
||||
dmg_name: nexus
|
||||
src_dir: build/macos/Build/Products/Release/Nexus.app
|
||||
|
||||
- name: Upload DMG
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: nexus.dmg
|
||||
path: ${{ steps.create-dmg.outputs.dmg_path }}
|
||||
73
.github/workflows/windows.yml
vendored
|
|
@ -1,46 +1,65 @@
|
|||
name: "Build Windows Version"
|
||||
name: "Build EXE"
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: ["main"]
|
||||
tags: ["*"]
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
build-windows:
|
||||
runs-on: "windows-latest"
|
||||
build-exe:
|
||||
runs-on: windows-latest
|
||||
|
||||
steps:
|
||||
- name: "Checkout repository"
|
||||
uses: "actions/checkout@v4"
|
||||
|
||||
- name: "Set up Flutter"
|
||||
uses: "subosito/flutter-action@v2"
|
||||
|
||||
- name: "Set up Rust"
|
||||
uses: "dtolnay/rust-toolchain@stable"
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v6
|
||||
with:
|
||||
targets: "x86_64-pc-windows-msvc"
|
||||
submodules: recursive
|
||||
|
||||
- name: "Install Flutter dependencies"
|
||||
run: flutter pub get
|
||||
- name: Set up Flutter
|
||||
uses: subosito/flutter-action@v2
|
||||
with:
|
||||
flutter-version: 3.44.4
|
||||
|
||||
- name: "Run build_runner & build Windows EXE"
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v6
|
||||
with:
|
||||
go-version-file: gomuks/go.mod
|
||||
|
||||
- name: Setup MSYS2
|
||||
uses: msys2/setup-msys2@v2
|
||||
with:
|
||||
msystem: MINGW64
|
||||
install: >-
|
||||
mingw-w64-x86_64-gcc
|
||||
|
||||
- name: Go build
|
||||
run: |
|
||||
flutter pub run build_runner build --delete-conflicting-outputs
|
||||
cd gomuks/pkg/ffi
|
||||
go build -tags goolm,sqlite_fts5 -o ../../../libgomuks.dll -buildmode=c-shared
|
||||
|
||||
- name: Build with Flutter
|
||||
run: |
|
||||
flutter pub get
|
||||
dart scripts/generate.dart
|
||||
flutter pub run build_runner build
|
||||
flutter build windows --release
|
||||
|
||||
- name: "Upload exe zip"
|
||||
uses: "actions/upload-artifact@v4"
|
||||
with:
|
||||
name: "windows-portable"
|
||||
path: "build/windows/x64/runner/Release/"
|
||||
- name: Copy MinGW runtime DLLs
|
||||
shell: msys2 {0}
|
||||
run: |
|
||||
cp /mingw64/bin/libgcc_s_seh-1.dll build/windows/x64/runner/Release/
|
||||
cp /mingw64/bin/libwinpthread-1.dll build/windows/x64/runner/Release/
|
||||
cp /mingw64/bin/libstdc++-6.dll build/windows/x64/runner/Release/
|
||||
|
||||
- name: "Install Inno Setup"
|
||||
- name: Install Inno Setup
|
||||
run: choco install innosetup -y
|
||||
|
||||
- name: "Build Inno Setup installer"
|
||||
- name: Build Inno Setup installer
|
||||
run: iscc windows/installer.iss
|
||||
|
||||
- name: "Upload installer artifact"
|
||||
uses: "actions/upload-artifact@v4"
|
||||
- name: Upload installer artifact
|
||||
uses: actions/upload-artifact@v6
|
||||
with:
|
||||
name: "windows-installer"
|
||||
path: "windows/dist/Nexus-Setup.exe"
|
||||
name: windows-installer
|
||||
path: windows/dist/Nexus-Setup.exe
|
||||
6
.gitignore
vendored
|
|
@ -36,7 +36,9 @@ key.properties
|
|||
# Generated Files
|
||||
*.g.dart
|
||||
*.freezed.dart
|
||||
src/
|
||||
|
||||
# Devel Password
|
||||
password.txt
|
||||
password.txt
|
||||
|
||||
# Nix
|
||||
/result
|
||||
4
.gitmodules
vendored
Normal file
|
|
@ -0,0 +1,4 @@
|
|||
[submodule "gomuks"]
|
||||
path = gomuks
|
||||
url = https://github.com/gomuks/gomuks
|
||||
branch = main
|
||||
12
.metadata
|
|
@ -4,7 +4,7 @@
|
|||
# This file should be version controlled and should not be manually edited.
|
||||
|
||||
version:
|
||||
revision: "nixpkgs000000000000000000000000000000000"
|
||||
revision: "6b182d2c7585eba26d4edce0f97630effd256c33"
|
||||
channel: "stable"
|
||||
|
||||
project_type: app
|
||||
|
|
@ -13,11 +13,11 @@ project_type: app
|
|||
migration:
|
||||
platforms:
|
||||
- platform: root
|
||||
create_revision: nixpkgs000000000000000000000000000000000
|
||||
base_revision: nixpkgs000000000000000000000000000000000
|
||||
- platform: windows
|
||||
create_revision: nixpkgs000000000000000000000000000000000
|
||||
base_revision: nixpkgs000000000000000000000000000000000
|
||||
create_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
base_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
- platform: ios
|
||||
create_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
base_revision: 6b182d2c7585eba26d4edce0f97630effd256c33
|
||||
|
||||
# User provided section
|
||||
|
||||
|
|
|
|||
9
.vscode/settings.json
vendored
|
|
@ -2,8 +2,15 @@
|
|||
"cSpell.words": [
|
||||
"Appbar",
|
||||
"Displayname",
|
||||
"fluttertagger",
|
||||
"Gomuks",
|
||||
"Homeserver",
|
||||
"Linkified",
|
||||
"localpart",
|
||||
"msgtype",
|
||||
"muks",
|
||||
"prefs",
|
||||
"vodozemac"
|
||||
"unban",
|
||||
"unredact"
|
||||
]
|
||||
}
|
||||
|
|
|
|||
70
DEVELOPMENT.md
Normal file
|
|
@ -0,0 +1,70 @@
|
|||
# Development Documentation
|
||||
|
||||
## Build instructions
|
||||
|
||||
Build instructions can be found in [README.md](./README.md#build-it-yourself).
|
||||
|
||||
## Updating Gomuks
|
||||
|
||||
You can run the following command to update the Gomuks submodule:
|
||||
|
||||
```sh
|
||||
git submodule update --remote
|
||||
```
|
||||
|
||||
## Code Style
|
||||
|
||||
See [Effective Dart: Style](https://dart.dev/effective-dart/style) for general rules. There are some extra rules detailed below:
|
||||
|
||||
### Controllers and Helpers ([Riverpod](https://pub.dev/packages/riverpod))
|
||||
|
||||
Controllers live in `lib/controllers/` and provide a source that exposes data and logic via Riverpod providers, allowing other parts of the code to watch state changes with ref.watch (`ref.watch(MyController.provider)`), access the current value with ref.read (`ref.read(MyController.provider)`), and run helper methods on those classes using the notifier:
|
||||
|
||||
```dart
|
||||
ref.watch(MyController.provider.notifier).helperMethod()
|
||||
```
|
||||
|
||||
We use an object oriented style for controllers, where `provider` is a static member on the controller class. E.g.
|
||||
|
||||
```dart
|
||||
class MyController extends AsyncNotifier<DataThisControllerExposes> {
|
||||
final SomeInputType input;
|
||||
MyController(this.input);
|
||||
|
||||
@override
|
||||
Future<DataThisControllerExposes> build() async {
|
||||
return input.foo;
|
||||
}
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider.family<MyController, DataThisControllerExposes, SomeInputType>(
|
||||
AuthorController.new,
|
||||
);
|
||||
}
|
||||
```
|
||||
|
||||
Providers which are not controllers, e.g. they expose no data, only methods, should instead live in `lib/helpers/`. For an example, see `lib/helpers/launch_helper.dart`. Other, non-provider helpers, like extensions or helper methods can also go in `lib/helpers/`.
|
||||
|
||||
### Don't use StatefulWidgets ([Flutter Hooks](https://pub.dev/packages/flutter_hooks))
|
||||
|
||||
This project uses Flutter Hooks to help with boilerplate that StatefulWidgets create. Instead of using a StatefulWidget, we just use hooks like `useState` or `useEffect` in the build method of a `HookWidget`, which is a drop in replacement for `StatelessWidget`. If you need both a `WidgetRef` to watch providers, and access to hooks, use `HookConsumerWidget`.
|
||||
|
||||
### Models ([Freezed](https://pub.dev/packages/freezed))
|
||||
|
||||
We use Freezed for our models to avoid boilerplate and enforce an immutable style of state and data modeling throughout the code. See their documentation for more info, or see our existing models in `lib/models/`.
|
||||
|
||||
### Immutable Data Collections ([Fast Immutable Collections](https://pub.dev/packages/fast_immutable_collections))
|
||||
|
||||
When possible, use immutable collections instead of the mutable equivalent. For example, use `IMap` over `Map`, `IList` over `List`, `ISet` over `Set`. This matches the immutable style of Riverpod and Freezed.
|
||||
|
||||
### Don't create globals
|
||||
|
||||
When possible, we prefer not to create global variables or methods. You can usually replace a global variable with a Riverpod controller, and a global method with an extension method.
|
||||
|
||||
## LLM/AI Assisted Contributions
|
||||
|
||||
LLM generated code is NOT allowed. All contributions should be written by humans. Using LLMs for interacting with others, e.g. for Comments, PRs, etc, is also not allowed.
|
||||
|
||||
## Code of Conduct
|
||||
|
||||
All contributions must follow the [Federated Nexus Code of Conduct](https://federated.nexus/code/).
|
||||
292
README.md
|
|
@ -1,11 +1,11 @@
|
|||
# Nexus Client
|
||||
|
||||
> [!WARNING]
|
||||
> Nexus Client is still heavily in development, and is not ready for use!
|
||||
> Nexus Client is still in development, and doesn't support everything needed for daily use.
|
||||
|
||||
## Description
|
||||
|
||||
A simple and user-friendly Matrix client made with Flutter and the Matrix Dart SDK.
|
||||
A simple and user-friendly Matrix client made with Flutter and a Gomuks backend.
|
||||
|
||||
## Screenshots
|
||||
|
||||
|
|
@ -15,135 +15,159 @@ A simple and user-friendly Matrix client made with Flutter and the Matrix Dart S
|
|||
|
||||
## Progress
|
||||
|
||||
- [ ] New logo
|
||||
- [ ] Make context menus appear as bottom sheets on mobile
|
||||
- [x] Move from the Dart SDK to the Gomuks SDK with Dart bindings: https://git.federated.nexus/Henry-Hiles/nexus/pulls/2
|
||||
- [ ] Allow using remote gomuks over websocket
|
||||
- [ ] Platform Support
|
||||
- [x] Linux
|
||||
- [x] Windows
|
||||
- [ ] MacOS
|
||||
- [ ] Android
|
||||
- [ ] iOS
|
||||
- [ ] Web (may not be possible)
|
||||
- [x] Login
|
||||
- [x] Username / password auth
|
||||
- [ ] OAuth / OIDC
|
||||
- [x] Improve initial sync experience
|
||||
- [x] Rooms / Spaces
|
||||
- [x] Displaying and choosing
|
||||
- [x] Reading, showing unread
|
||||
- [x] Mark as read button on rooms and spaces
|
||||
- [ ] Searching
|
||||
- [ ] Creating (Rooms, Spaces, and DMs)
|
||||
- [x] Joining
|
||||
- [ ] Parse vias
|
||||
- [x] Using a text/uri/link
|
||||
- [x] Plain text
|
||||
- [x] `matrix:` Uri
|
||||
- [x] Matrix.to link
|
||||
- [ ] From space
|
||||
- [ ] Exploring
|
||||
- [x] Leaving
|
||||
- [x] Subspaces
|
||||
- [x] Messages
|
||||
- [x] Encryption
|
||||
- [x] Restoring crypto identity from a recovery passphrase/key
|
||||
- [x] Sending
|
||||
- [x] Plain text
|
||||
- [x] HTML/Markdown
|
||||
- [x] Replies
|
||||
- [x] Choose ping on/off
|
||||
- [ ] Per message profiles
|
||||
- [ ] Attachments
|
||||
- [ ] Commands with [MSC4391](https://github.com/matrix-org/matrix-spec-proposals/pull/4391)
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Rooms
|
||||
- [ ] Inline emoji picker (Putting this here since it'll be implemented the same way as mentions)
|
||||
- [ ] Custom emojis/stickers
|
||||
- [ ] GIFs using Gomuks' GIF proxies
|
||||
- [x] Recieving
|
||||
- [x] Plain text
|
||||
- [x] Per message profiles
|
||||
- [x] HTML
|
||||
- [x] Replies
|
||||
- [x] Viewing
|
||||
- [ ] Jump to original message
|
||||
- [x] In loaded timeline
|
||||
- [ ] Out of loaded timeline
|
||||
- [x] Edits
|
||||
- [x] Attachments
|
||||
- [x] Unencrypted
|
||||
- [ ] Encrypted
|
||||
- [x] Blurhashing
|
||||
- [ ] Downloading attachments
|
||||
- [x] Opening attachments in their own view
|
||||
- [ ] Polls: Waiting on https://github.com/SwanFlutter/dynamic_polls/issues/1
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Rooms
|
||||
- [ ] Plain text (not sure if I want to add this or not, I probably won't unless there's interest)
|
||||
- [x] Matrix URIs
|
||||
- [x] Matrix.to links
|
||||
- [ ] Do some fancy fetching to get nice names
|
||||
- [ ] Make clickable
|
||||
- [x] Custom emojis/stickers
|
||||
- [x] History loading
|
||||
- [x] Backwards
|
||||
- [ ] Forwards
|
||||
- [x] Editing
|
||||
- [x] Deleting
|
||||
- [ ] Reactions: Waiting on https://github.com/flyerhq/flutter_chat_ui/pull/838 or me doing a custom impl
|
||||
- [ ] Pins
|
||||
- [ ] Displaying
|
||||
- [ ] Creating
|
||||
- [ ] Threads
|
||||
- [ ] Profile popouts
|
||||
- [ ] Copy link to [room, space]
|
||||
- [ ] Reporting
|
||||
- [x] Events
|
||||
- [ ] Rooms
|
||||
- [ ] Notifications using UnifiedPush
|
||||
- [ ] Group calls using [MSC4195](https://github.com/matrix-org/matrix-spec-proposals/pull/4195)
|
||||
- [ ] Invites
|
||||
- [ ] Settings
|
||||
- [ ] Light/Dark mode
|
||||
- [ ] SSD or CSD
|
||||
- [ ] Show media by default
|
||||
- [ ] Dynamic Theming
|
||||
- [ ] Devices
|
||||
- [ ] Viewing devices
|
||||
- [ ] Verifying devices
|
||||
- [ ] URL preview: Server / Client / None
|
||||
- [ ] Account changes
|
||||
- [ ] Display name
|
||||
- [ ] Profile picture
|
||||
- [ ] Timezone
|
||||
- [ ] Pronouns
|
||||
- [ ] Password
|
||||
- [ ] About
|
||||
- [x] Log Out
|
||||
- [x] Platform Support
|
||||
- [x] Linux
|
||||
- [x] Windows - Currently has some bugs, due to us not having any developers on Windows. If you want to fix these, get in contact with us though the [Nexus Client Matrix room](https://matrix.to/#/#nexus:federated.nexus).
|
||||
- [x] Android
|
||||
- [x] MacOS - Unsigned .dmg only
|
||||
- [x] iOS - Unsigned .ipa only
|
||||
- [ ] Web (may not be possible)
|
||||
- [x] Login (via OAuth)
|
||||
- [x] Rooms / Spaces
|
||||
- [x] Displaying and choosing
|
||||
- [x] Reading, showing unread
|
||||
- [x] Mark as read button on rooms and spaces
|
||||
- [ ] Searching
|
||||
- [ ] Creating (Rooms, Spaces, and DMs)
|
||||
- [x] Joining
|
||||
- [x] Parse vias
|
||||
- [x] Using a text/uri/link
|
||||
- [x] Plain text
|
||||
- [x] `matrix:` Uri
|
||||
- [x] Matrix.to link
|
||||
- [ ] From space
|
||||
- [ ] From directory
|
||||
- [x] Leaving
|
||||
- [x] Subspaces
|
||||
- [x] Messages
|
||||
- [x] Encryption
|
||||
- [x] Restoring crypto identity from a recovery passphrase/key
|
||||
- [x] Sending
|
||||
- [x] Plain text
|
||||
- [x] HTML/Markdown
|
||||
- [x] Replies
|
||||
- [x] Choose ping on/off
|
||||
- [x] Per message profiles
|
||||
- [x] Attachments
|
||||
- [ ] Commands with [MSC4391](https://github.com/matrix-org/matrix-spec-proposals/pull/4391)
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Rooms
|
||||
- [ ] Inline emoji picker (Putting this here since it'll be implemented the same way as mentions)
|
||||
- [ ] Custom emojis/stickers
|
||||
- [ ] GIFs using Gomuks' GIF proxies
|
||||
- [x] Receiving
|
||||
- [x] Plain text
|
||||
- [x] Per message profiles
|
||||
- [x] HTML
|
||||
- [x] URL Previews
|
||||
- [x] Replies
|
||||
- [x] Viewing
|
||||
- [ ] Jump to original message
|
||||
- [x] In loaded timeline
|
||||
- [ ] Out of loaded timeline
|
||||
- [x] Edits
|
||||
- [x] Attachments
|
||||
- [x] Unencrypted
|
||||
- [x] Encrypted
|
||||
- [x] Blurhashing
|
||||
- [ ] Downloading attachments
|
||||
- [x] Opening attachments in their own view
|
||||
- [ ] Polls
|
||||
- [x] Mentions
|
||||
- [x] Users
|
||||
- [x] Clickable
|
||||
- [x] Rooms
|
||||
- [ ] Clickable
|
||||
- [x] Matrix URIs
|
||||
- [x] Matrix.to links
|
||||
- [x] Events
|
||||
- [ ] Render more nicely
|
||||
- [ ] Clickable
|
||||
- [x] Custom emojis/stickers
|
||||
- [x] History loading
|
||||
- [x] Editing
|
||||
- [x] Deleting
|
||||
- [x] Reactions
|
||||
- [x] Pins
|
||||
- [x] Displaying
|
||||
- [x] Pinning/Unpinning
|
||||
- [ ] Threads
|
||||
- [x] Profile popouts
|
||||
- [x] Working actions
|
||||
- [x] Copy link to:
|
||||
- [x] Room
|
||||
- [x] Space
|
||||
- [x] Message
|
||||
- [ ] Reporting
|
||||
- [x] Events
|
||||
- [ ] Rooms
|
||||
- [x] Member list
|
||||
- [x] Sort by power level
|
||||
- [ ] Colors based off of power level
|
||||
- [ ] Notifications using UnifiedPush ([#35](https://git.federated.nexus/Nexus/nexus/issues/35))
|
||||
- [ ] Group calls using [MSC4195](https://github.com/matrix-org/matrix-spec-proposals/pull/4195)
|
||||
- [ ] Invites
|
||||
- [x] Settings
|
||||
|
||||
## Build Instructions
|
||||
## Try it out
|
||||
|
||||
First, clone and open the repo:
|
||||
If you want to try out Nexus, grab one of the following artifacts from CI:
|
||||
|
||||
```sh
|
||||
git clone https://git.federated.nexus/Henry-Hiles/nexus
|
||||
cd nexus
|
||||
```
|
||||
- [Android APK](https://nightly.link/Henry-Hiles/nexus/workflows/android/main/APK.zip)
|
||||
- [Windows EXE](https://nightly.link/Henry-Hiles/nexus/workflows/windows/main/windows-installer.zip)
|
||||
- [Unsigned iOS IPA](https://nightly.link/Henry-Hiles/nexus/workflows/ios/main/Nexus.ipa.zip)
|
||||
- [Unsigned MacOS DMG](https://nightly.link/Henry-Hiles/nexus/workflows/macos/main/nexus.dmg.zip)
|
||||
- [Windows EXE](https://nightly.link/Henry-Hiles/nexus/workflows/windows/main/windows-installer.zip)
|
||||
- Flatpak
|
||||
- [AArch64/Arm64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-aarch64.zip)
|
||||
- [x86_64/AMD64](https://nightly.link/Henry-Hiles/nexus/workflows/flatpak/main/flatpak-x86_64.zip)
|
||||
|
||||
## Build it yourself
|
||||
|
||||
### Prerequisites
|
||||
|
||||
#### Linux
|
||||
|
||||
- With Nix: Either use direnv, or `nix flake develop`
|
||||
- Without Nix: Install Flutter, Go, Olm, Git, Clang, and GLibc.
|
||||
- On NixOS: Either use direnv and `direnv allow`, or `nix flake develop`
|
||||
- On other distros: Install Flutter, Go, Git, Libclang, Libass, MPV, and Glibc. Do not use any Snap packages, they cause various compilation issues.
|
||||
|
||||
#### Windows / MacOS
|
||||
#### Windows
|
||||
|
||||
I don't really know. You will need Flutter, Git, Olm, Go, and Visual Studio tools, and otherwise I guess just keep installing stuff until there aren't any errors. I will look into this sometimeTM.
|
||||
You will need:
|
||||
|
||||
- Flutter
|
||||
- Git
|
||||
- Libass
|
||||
- MPV
|
||||
- Go
|
||||
- Visual Studio 2022 (Desktop development with C++)
|
||||
- [MSYS2/MinGW-w64 GCC](https://www.msys2.org/) (for CGO)
|
||||
- [LLVM/Clang + libclang](https://clang.llvm.org/get_started.html) (for `ffigen`)
|
||||
|
||||
On Windows, make sure these are available in your shell `PATH`:
|
||||
|
||||
- `C:\msys64\ucrt64\bin` (or your MinGW bin path containing `x86_64-w64-mingw32-gcc.exe`)
|
||||
- `C:\Program Files\LLVM\bin` (contains `clang.exe` and `libclang.dll`)
|
||||
|
||||
For `dart scripts/generate.dart`, you may also need:
|
||||
|
||||
```powershell
|
||||
$env:CPATH = "C:\msys64\ucrt64\include"
|
||||
```
|
||||
|
||||
#### MacOS
|
||||
|
||||
Similar prerequisites apply (Flutter, Git, Go, C toolchain, LLVM/libclang), but exact setup has not been fully documented yet.
|
||||
|
||||
### Clone repo
|
||||
|
||||
First, clone and open the repo:
|
||||
|
||||
```sh
|
||||
git clone --recurse-submodules https://git.federated.nexus/Nexus/nexus
|
||||
cd nexus
|
||||
```
|
||||
|
||||
### Set up Flutter
|
||||
|
||||
|
|
@ -153,22 +177,23 @@ Get dependencies:
|
|||
flutter pub get
|
||||
```
|
||||
|
||||
Get dependencies:
|
||||
Generate Gomuks bindings:
|
||||
|
||||
```sh
|
||||
flutter pub get
|
||||
dart scripts/generate.dart
|
||||
```
|
||||
|
||||
Clone Gomuks and generate bindings:
|
||||
|
||||
```sh
|
||||
scripts/generate.sh
|
||||
```
|
||||
> [!NOTE]
|
||||
> If you are having issues with `stddef.h` not being found, try setting CPATH manually:
|
||||
>
|
||||
> ```sh
|
||||
> export CPATH="$(clang -v 2>&1 | grep "Selected GCC installation" | rev | cut -d' ' -f1 | rev)/include"
|
||||
> ```
|
||||
|
||||
Build generated files, and watch for new changes:
|
||||
|
||||
```sh
|
||||
flutter pub run build_runner watch --delete-conflicting-outputs
|
||||
flutter pub run build_runner watch
|
||||
```
|
||||
|
||||
Run the app:
|
||||
|
|
@ -177,6 +202,13 @@ Run the app:
|
|||
flutter run
|
||||
```
|
||||
|
||||
Development instructions can be found in [DEVELOPMENT.md](./DEVELOPMENT.md).
|
||||
|
||||
## Community
|
||||
|
||||
Join the [Nexus Client Matrix Room](https://matrix.to/#/#nexus:federated.nexus) for questions or help with developing or using Nexus Client.
|
||||
Join the [Nexus Client Matrix room](https://matrix.to/#/#nexus:federated.nexus) for questions or help with developing or using Nexus Client.
|
||||
|
||||
# Credits
|
||||
|
||||
Thank you Hylke Bons (https://planetpeanut.studio) for making the amazing icon for Nexus!
|
||||
Thank you Tulir Asokan for making [Gomuks](https://github.com/gomuks/gomuks), and helping us integrate it into Nexus!
|
||||
|
|
|
|||
22
altstore-source.json
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
{
|
||||
"name": "Nexus",
|
||||
"identifier": "nexus.federated.nexus.source",
|
||||
"subtitle": "Nexus for iOS",
|
||||
"description": "Nexus iOS builds for AltStore and SideStore.",
|
||||
"iconURL": "https://git.federated.nexus/Nexus/nexus/raw/branch/main/assets/icon.png",
|
||||
"website": "https://git.federated.nexus/Nexus/nexus",
|
||||
"apps": [
|
||||
{
|
||||
"name": "Nexus",
|
||||
"bundleIdentifier": "nexus.federated.nexus",
|
||||
"developerName": "Nexus",
|
||||
"subtitle": "A Matrix client",
|
||||
"localizedDescription": "Nexus for iOS. Unsigned builds, resigned at install by AltStore/SideStore.",
|
||||
"iconURL": "https://git.federated.nexus/Nexus/nexus/raw/branch/main/assets/icon.png",
|
||||
"category": "social",
|
||||
"screenshots": [],
|
||||
"versions": []
|
||||
}
|
||||
],
|
||||
"news": []
|
||||
}
|
||||
|
|
@ -30,7 +30,7 @@ if (keystorePropertiesFile.exists()) {
|
|||
}
|
||||
|
||||
android {
|
||||
namespace = "nexus.federated.Nexus"
|
||||
namespace = "nexus.federated.nexus"
|
||||
ndkVersion = flutter.ndkVersion
|
||||
compileSdk = 34
|
||||
|
||||
|
|
@ -39,8 +39,12 @@ android {
|
|||
targetCompatibility = JavaVersion.VERSION_17
|
||||
}
|
||||
|
||||
kotlinOptions {
|
||||
jvmTarget = "17"
|
||||
}
|
||||
|
||||
defaultConfig {
|
||||
applicationId = "nexus.federated.Nexus"
|
||||
applicationId = "nexus.federated.nexus"
|
||||
minSdk = 29
|
||||
targetSdkVersion flutter.targetSdkVersion
|
||||
versionCode = flutterVersionCode.toInteger()
|
||||
|
|
@ -50,7 +54,8 @@ android {
|
|||
signingConfigs {
|
||||
release {
|
||||
keyAlias "key"
|
||||
storeFile keystoreProperties['path'] ? file(keystoreProperties['path']) : file(System.getenv("KEYSTORE_PATH"))
|
||||
def storePath = keystoreProperties['path'] ?: System.getenv("KEYSTORE_PATH")
|
||||
storeFile storePath ? file(storePath) : null
|
||||
keyPassword keystoreProperties['password'] ?: System.getenv("KEYSTORE_PASSWORD")
|
||||
storePassword keystoreProperties['password'] ?: System.getenv("KEYSTORE_PASSWORD")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -10,7 +10,7 @@
|
|||
android:label="Nexus"
|
||||
android:name="${applicationName}"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:roundIcon="@mipmap/nexus_round"
|
||||
android:roundIcon="@mipmap/ic_launcher"
|
||||
android:allowBackup="false"
|
||||
android:fullBackupContent="false">
|
||||
<activity
|
||||
|
|
@ -22,6 +22,14 @@
|
|||
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
|
||||
android:hardwareAccelerated="true"
|
||||
android:windowSoftInputMode="adjustResize">
|
||||
<meta-data android:name="flutter_deeplinking_enabled" android:value="false" />
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.VIEW" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<category android:name="android.intent.category.BROWSABLE" />
|
||||
|
||||
<data android:scheme="nexus.federated.nexus" />
|
||||
</intent-filter>
|
||||
<meta-data
|
||||
android:name="io.flutter.embedding.android.NormalTheme"
|
||||
android:resource="@style/NormalTheme"
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
package nexus.federated.Nexus
|
||||
package nexus.federated.nexus
|
||||
|
||||
import io.flutter.embedding.android.FlutterActivity
|
||||
|
||||
|
|
|
|||
|
After Width: | Height: | Size: 5.5 KiB |
|
Before Width: | Height: | Size: 8.7 KiB After Width: | Height: | Size: 3.5 KiB |
|
After Width: | Height: | Size: 2.9 KiB |
|
After Width: | Height: | Size: 3.2 KiB |
|
Before Width: | Height: | Size: 5.7 KiB After Width: | Height: | Size: 2.3 KiB |
|
After Width: | Height: | Size: 1.9 KiB |
|
After Width: | Height: | Size: 7.1 KiB |
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 4.9 KiB |
|
After Width: | Height: | Size: 3.9 KiB |
|
After Width: | Height: | Size: 12 KiB |
|
Before Width: | Height: | Size: 18 KiB After Width: | Height: | Size: 7.4 KiB |
|
After Width: | Height: | Size: 5.9 KiB |
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 34 KiB After Width: | Height: | Size: 10 KiB |
|
After Width: | Height: | Size: 8.2 KiB |
|
|
@ -1,9 +1,14 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<background android:drawable="@color/ic_launcher_background"/>
|
||||
<background android:drawable="@drawable/ic_launcher_background"/>
|
||||
<foreground>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_foreground"
|
||||
android:inset="16%" />
|
||||
</foreground>
|
||||
<monochrome>
|
||||
<inset
|
||||
android:drawable="@drawable/ic_launcher_monochrome"
|
||||
android:inset="16%" />
|
||||
</monochrome>
|
||||
</adaptive-icon>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 4.1 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 8.9 KiB After Width: | Height: | Size: 4.7 KiB |
|
Before Width: | Height: | Size: 15 KiB After Width: | Height: | Size: 7.3 KiB |
|
Before Width: | Height: | Size: 19 KiB After Width: | Height: | Size: 9.8 KiB |
|
|
@ -1,3 +1,7 @@
|
|||
org.gradle.jvmargs=-Xmx4G -XX:+HeapDumpOnOutOfMemoryError
|
||||
android.useAndroidX=true
|
||||
android.enableJetifier=true
|
||||
# This builtInKotlin flag was added automatically by Flutter migrator
|
||||
android.builtInKotlin=false
|
||||
# This newDsl flag was added automatically by Flutter migrator
|
||||
android.newDsl=false
|
||||
|
|
|
|||
BIN
assets/background.png
Normal file
|
After Width: | Height: | Size: 21 KiB |
257
assets/background.svg
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="background.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
inkscape:export-filename="background.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="0.69191503"
|
||||
inkscape:cx="-71.540576"
|
||||
inkscape:cy="281.10388"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg11" />
|
||||
<defs
|
||||
id="defs11">
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,80,52.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath11">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect12"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath12">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect13"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath13">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath15">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect16"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath16">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect17"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8-3"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,174.26633,65.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10-6" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11-7" />
|
||||
</radialGradient>
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8-35"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,80,52.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10-62" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11-9" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8-1"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9-2" />
|
||||
</mask>
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8-9"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10-3" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11-6" />
|
||||
</radialGradient>
|
||||
</defs>
|
||||
<rect
|
||||
width="512"
|
||||
height="512"
|
||||
fill="#ffffff"
|
||||
id="rect1"
|
||||
x="0"
|
||||
y="0"
|
||||
style="stroke-width:4" />
|
||||
<rect
|
||||
x="-1.5384758"
|
||||
y="-122.66472"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#9141ac"
|
||||
id="rect2"
|
||||
clip-path="url(#clipPath16)" />
|
||||
<rect
|
||||
x="34.018467"
|
||||
y="-122.66468"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#62a0ea"
|
||||
id="rect3"
|
||||
clip-path="url(#clipPath15)" />
|
||||
<rect
|
||||
x="60.68605"
|
||||
y="-122.66468"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#57e389"
|
||||
id="rect4"
|
||||
clip-path="url(#clipPath14)" />
|
||||
<rect
|
||||
x="87.353859"
|
||||
y="-122.66468"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#f5c211"
|
||||
id="rect5"
|
||||
clip-path="url(#clipPath13)" />
|
||||
<rect
|
||||
x="114.02161"
|
||||
y="-122.66477"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#ff7800"
|
||||
id="rect6"
|
||||
clip-path="url(#clipPath12)" />
|
||||
<rect
|
||||
x="140.68942"
|
||||
y="-122.66477"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="matrix(3.4641016,2,-2,3.4641016,0,0)"
|
||||
fill="#ed333b"
|
||||
id="rect7"
|
||||
clip-path="url(#clipPath11)" />
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 6.7 KiB |
BIN
assets/fonts/NotoColorEmoji.ttf
Normal file
BIN
assets/fonts/Roboto.ttf
Normal file
|
Before Width: | Height: | Size: 20 KiB After Width: | Height: | Size: 11 KiB |
|
|
@ -1,20 +1,19 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
sodipodi:docname="nexus.svg"
|
||||
id="svg11"
|
||||
sodipodi:docname="foreground.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
|
|
@ -22,105 +21,137 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.0847363"
|
||||
inkscape:cx="58.07863"
|
||||
inkscape:cy="214.3378"
|
||||
inkscape:window-width="1896"
|
||||
inkscape:window-height="987"
|
||||
inkscape:zoom="0.87695313"
|
||||
inkscape:cx="152.23163"
|
||||
inkscape:cy="347.22494"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs1" /><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 19.377906,68.106953 80.937684,32.43771"
|
||||
id="path10" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="m 19.044488,32.469148 61.61782,35.569625"
|
||||
id="path9" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 50,85.574911 V 14.425087"
|
||||
id="path8" /><circle
|
||||
style="fill:none;stroke:#ffffff;stroke-width:7.11498;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="path1"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="35.574913" /><circle
|
||||
style="fill:#09bd05;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="path2"
|
||||
cx="50"
|
||||
cy="84.604881"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe1e24;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle2"
|
||||
cx="50"
|
||||
cy="15.395123"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe941d;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle3"
|
||||
cx="-68.30127"
|
||||
cy="52.906147"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#001996;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle4"
|
||||
cx="-68.30127"
|
||||
cy="-16.30361"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#ffff04;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle5"
|
||||
cx="-18.301271"
|
||||
cy="102.90615"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:#770287;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle6"
|
||||
cx="-18.301271"
|
||||
cy="33.696392"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:6.75;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path7"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="9.7918472" /><g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-3"
|
||||
transform="matrix(0.08246781,0,0,0.08246781,38.828362,38.828362)"
|
||||
style="stroke:#ffffff"><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><circle
|
||||
style="fill:#354b5f;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path342"
|
||||
cx="135.46666"
|
||||
cy="135.46666"
|
||||
r="135.46666" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817-5"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><g
|
||||
aria-label="❯"
|
||||
id="text2827-6"
|
||||
style="font-size:132.452px;line-height:0;font-family:PowerlineSymbols;-inkscape-font-specification:'PowerlineSymbols, Normal';text-align:end;text-anchor:end;fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0"><path
|
||||
d="M 95.096912,209.8167 143.88912,135.46666 95.096912,61.116629 h 32.818568 l 47.92093,74.350031 -47.92093,74.35004 z"
|
||||
id="path2883-2"
|
||||
style="fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0" /></g></g></g></svg>
|
||||
inkscape:current-layer="svg11" />
|
||||
<path
|
||||
d="m 256,92 c 90.5748,0 164,73.4252 164,164 0,90.5748 -73.4252,164 -164,164 -34.5828,0 -66.6592,-10.712 -93.1092,-28.9884 l -39.2072,8.7656 c -6.8668,1.5348 -12.9952,-4.594 -11.4608,-11.4608 l 8.7616,-39.2108 C 102.7104,322.6564 92,290.5808 92,256 92,165.4252 165.4252,92 256,92 Z"
|
||||
fill="#ffffff"
|
||||
id="path7"
|
||||
style="stroke-width:4" />
|
||||
<path
|
||||
d="m 304.9188,251.4672 c 1.8572,2.732 1.844,6.3248 -0.0332,9.0432 L 260.6664,324.546 C 259.1728,326.7088 256.712,328 254.0836,328 H 234.948 c -6.3896,0 -10.2004,-7.1212 -6.6564,-12.4376 l 36.75,-55.1248 c 1.7916,-2.6872 1.7916,-6.188 0,-8.8752 l -36.75,-55.1248 C 224.7476,191.1212 228.5584,184 234.948,184 h 19.8748 c 2.6492,0 5.1268,1.3116 6.616,3.5028 z"
|
||||
fill="url(#paint0_radial_4033_8)"
|
||||
id="path8"
|
||||
style="fill:url(#paint0_radial_4033_8);stroke-width:4" />
|
||||
<g
|
||||
mask="url(#mask0_4033_8)"
|
||||
id="g9"
|
||||
transform="scale(4)">
|
||||
<rect
|
||||
x="52"
|
||||
y="46"
|
||||
width="17"
|
||||
height="4"
|
||||
fill="#2779dd"
|
||||
id="rect9" />
|
||||
</g>
|
||||
<defs
|
||||
id="defs11">
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath11">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect12"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath12">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect13"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath13">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath15">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect16"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath16">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect17"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 6 KiB After Width: | Height: | Size: 4.5 KiB |
BIN
assets/icon.png
|
Before Width: | Height: | Size: 35 KiB After Width: | Height: | Size: 26 KiB |
448
assets/icon.svg
|
|
@ -1,21 +1,22 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Created with Inkscape (http://www.inkscape.org/) -->
|
||||
|
||||
<svg
|
||||
width="100mm"
|
||||
height="100mm"
|
||||
viewBox="0 0 100 100"
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg1"
|
||||
xml:space="preserve"
|
||||
inkscape:version="1.4.2 (ebf0e940d0, 2025-05-08)"
|
||||
id="svg35"
|
||||
sodipodi:docname="icon.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
inkscape:export-filename="icon.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg"><sodipodi:namedview
|
||||
id="namedview1"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview35"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
|
|
@ -23,128 +24,311 @@
|
|||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:document-units="mm"
|
||||
inkscape:zoom="1.0847363"
|
||||
inkscape:cx="57.61769"
|
||||
inkscape:cy="214.33781"
|
||||
inkscape:window-width="1896"
|
||||
inkscape:window-height="963"
|
||||
inkscape:zoom="1.321682"
|
||||
inkscape:cx="69.608271"
|
||||
inkscape:cy="120.67956"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="layer1" /><defs
|
||||
id="defs1"><linearGradient
|
||||
id="linearGradient10"
|
||||
inkscape:collect="always"><stop
|
||||
style="stop-color:#c7a312;stop-opacity:1;"
|
||||
offset="0"
|
||||
id="stop10" /><stop
|
||||
style="stop-color:#26a0b3;stop-opacity:1;"
|
||||
inkscape:current-layer="svg35" />
|
||||
<mask
|
||||
id="mask0_4023_558"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="12"
|
||||
y="100"
|
||||
width="88"
|
||||
height="16">
|
||||
<path
|
||||
d="m 100,104 c 0,6.627 -5.3726,12 -12,12 H 24 c -6.6274,0 -12,-5.373 -12,-12 v -4 c 0,6.627 5.3726,12 12,12 h 64 c 6.6274,0 12,-5.373 12,-12 z"
|
||||
fill="#d9d9d9"
|
||||
id="path6" />
|
||||
</mask>
|
||||
<mask
|
||||
id="mask1_4023_558"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="77"
|
||||
y="27"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 97.4223,44.1501 c 0.3482,0.5122 0.3457,1.1859 -0.0063,1.6956 L 86.0175,62.3523 C 85.7375,62.7579 85.2761,63 84.7832,63 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.3321 l 9.8906,-14.8358 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6642 L 78.0729,30.1094 C 77.1869,28.7803 78.1396,27 79.737,27 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6567 z"
|
||||
fill="#2779dd"
|
||||
id="path14" />
|
||||
</mask>
|
||||
<g
|
||||
id="g36"
|
||||
transform="scale(4)">
|
||||
<g
|
||||
clip-path="url(#clip0_4023_558)"
|
||||
id="g6">
|
||||
<rect
|
||||
x="62.0205"
|
||||
y="-52.425598"
|
||||
width="24"
|
||||
height="197"
|
||||
transform="rotate(30,62.0205,-52.4256)"
|
||||
fill="#9141ac"
|
||||
id="rect1" />
|
||||
<rect
|
||||
x="82.805099"
|
||||
y="-40.425598"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,82.8051,-40.4256)"
|
||||
fill="#62a0ea"
|
||||
id="rect2" />
|
||||
<rect
|
||||
x="98.3936"
|
||||
y="-31.4256"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,98.3936,-31.4256)"
|
||||
fill="#57e389"
|
||||
id="rect3" />
|
||||
<rect
|
||||
x="113.982"
|
||||
y="-22.4256"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,113.982,-22.4256)"
|
||||
fill="#f5c211"
|
||||
id="rect4" />
|
||||
<rect
|
||||
x="129.57001"
|
||||
y="-13.4256"
|
||||
width="18"
|
||||
height="197"
|
||||
transform="rotate(30,129.57,-13.4256)"
|
||||
fill="#ff7800"
|
||||
id="rect5" />
|
||||
<rect
|
||||
x="145.159"
|
||||
y="-4.4256301"
|
||||
width="24"
|
||||
height="197"
|
||||
transform="rotate(30,145.159,-4.42563)"
|
||||
fill="#ed333b"
|
||||
id="rect6" />
|
||||
</g>
|
||||
<g
|
||||
mask="url(#mask0_4023_558)"
|
||||
id="g10">
|
||||
<path
|
||||
d="m 12,100 h 24 v 16 H 12 Z"
|
||||
fill="url(#paint0_linear_4023_558)"
|
||||
id="path7"
|
||||
style="fill:url(#paint0_linear_4023_558)" />
|
||||
<path
|
||||
d="m 12,100 h 5 v 16 h -5 z"
|
||||
fill="url(#paint1_linear_4023_558)"
|
||||
id="path8"
|
||||
style="fill:url(#paint1_linear_4023_558)" />
|
||||
<rect
|
||||
x="36"
|
||||
y="100"
|
||||
width="21"
|
||||
height="16"
|
||||
fill="#ca9005"
|
||||
id="rect8" />
|
||||
<rect
|
||||
x="57"
|
||||
y="100"
|
||||
width="21"
|
||||
height="16"
|
||||
fill="#c64600"
|
||||
id="rect9" />
|
||||
<rect
|
||||
x="78"
|
||||
y="100"
|
||||
width="22"
|
||||
height="16"
|
||||
fill="url(#paint2_linear_4023_558)"
|
||||
id="rect10"
|
||||
style="fill:url(#paint2_linear_4023_558)" />
|
||||
</g>
|
||||
<rect
|
||||
opacity="0.2"
|
||||
x="24.5"
|
||||
y="110.5"
|
||||
width="63"
|
||||
height="1"
|
||||
stroke="url(#paint3_linear_4023_558)"
|
||||
id="rect11"
|
||||
style="stroke:url(#paint3_linear_4023_558)" />
|
||||
<path
|
||||
d="m 85,4 c 22.644,0 41,18.3563 41,41 v 4 c 0,22.6437 -18.356,41 -41,41 -8.3322,0 -16.0825,-2.4875 -22.5526,-6.7576 -0.4653,-0.3071 -1.0341,-0.4203 -1.5783,-0.2987 l -8.8369,1.9749 C 52.0134,84.9228 52,84.9395 52,84.9588 52,84.9816 51.9816,85 51.9588,85 h -0.4617 c -0.0787,0.0036 -0.1564,0.004 -0.2334,0 H 51 c -1.1046,0 -2,-0.8954 -2,-2 v -0.2617 c -0.0043,-0.0811 -0.0042,-0.1632 0,-0.2461 V 78.9749 C 49,78.7126 49.2126,78.5 49.4749,78.5 c 0.2224,0 0.4151,-0.1543 0.4635,-0.3714 l 1.117,-4.9987 C 51.177,72.5857 51.0638,72.017 50.7567,71.5517 46.487,65.0818 44,57.3317 44,49 V 45 C 44,22.3563 62.3563,4 85,4 Z"
|
||||
fill="url(#paint4_linear_4023_558)"
|
||||
id="path11"
|
||||
style="fill:url(#paint4_linear_4023_558)" />
|
||||
<path
|
||||
d="m 85,4 c 22.644,0 41,18.3563 41,41 0,22.6437 -18.356,41 -41,41 -8.6457,0 -16.6648,-2.6781 -23.2773,-7.2471 l -9.8018,2.1914 c -1.7167,0.3836 -3.2488,-1.1485 -2.8652,-2.8652 l 2.1904,-9.8027 C 46.6776,61.6641 44,53.6452 44,45 44,22.3563 62.3563,4 85,4 Z"
|
||||
fill="#ffffff"
|
||||
id="path12" />
|
||||
<path
|
||||
d="m 97.2297,43.8668 c 0.4642,0.683 0.4609,1.5812 -0.0083,2.2608 L 86.1666,62.1365 C 85.7932,62.6772 85.178,63 84.5209,63 H 79.737 c -1.5974,0 -2.5502,-1.7803 -1.6641,-3.1094 l 9.1875,-13.7812 c 0.4478,-0.6718 0.4478,-1.547 0,-2.2188 L 78.0729,30.1094 C 77.1868,28.7803 78.1396,27 79.737,27 h 4.9687 c 0.6623,0 1.2817,0.3279 1.654,0.8757 z"
|
||||
fill="url(#paint5_radial_4023_558)"
|
||||
id="path13"
|
||||
style="fill:url(#paint5_radial_4023_558)" />
|
||||
<g
|
||||
mask="url(#mask1_4023_558)"
|
||||
id="g14">
|
||||
<rect
|
||||
x="73"
|
||||
y="27"
|
||||
width="17"
|
||||
height="4"
|
||||
fill="#2779dd"
|
||||
id="rect14" />
|
||||
</g>
|
||||
</g>
|
||||
<defs
|
||||
id="defs35">
|
||||
<linearGradient
|
||||
id="paint0_linear_4023_558"
|
||||
x1="34"
|
||||
y1="108"
|
||||
x2="12"
|
||||
y2="108"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0.401381"
|
||||
stop-color="#26A269"
|
||||
id="stop14" />
|
||||
<stop
|
||||
offset="0.801049"
|
||||
stop-color="#8AEB52"
|
||||
id="stop15" />
|
||||
<stop
|
||||
offset="1"
|
||||
id="stop11" /></linearGradient><linearGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#linearGradient10"
|
||||
id="linearGradient11"
|
||||
x1="20.031296"
|
||||
y1="32.697563"
|
||||
x2="90.709213"
|
||||
y2="66.3423"
|
||||
gradientUnits="userSpaceOnUse" /></defs><g
|
||||
inkscape:label="Layer 1"
|
||||
inkscape:groupmode="layer"
|
||||
id="layer1"><rect
|
||||
style="fill:url(#linearGradient11);fill-opacity:1;stroke:none;stroke-width:7.99999;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="rect10"
|
||||
width="100"
|
||||
height="100"
|
||||
x="0"
|
||||
y="0"
|
||||
ry="28.294127" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 19.377906,68.106953 80.937684,32.43771"
|
||||
id="path10" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="m 19.044488,32.469148 61.61782,35.569625"
|
||||
id="path9" /><path
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:8;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
d="M 50,85.574911 V 14.425087"
|
||||
id="path8" /><circle
|
||||
style="fill:none;stroke:#ffffff;stroke-width:7.11498;stroke-linecap:round;stroke-linejoin:round"
|
||||
id="path1"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="35.574913" /><circle
|
||||
style="fill:#09bd05;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="path2"
|
||||
cx="50"
|
||||
cy="84.604881"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe1e24;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle2"
|
||||
cx="50"
|
||||
cy="15.395123"
|
||||
r="8.2508707" /><circle
|
||||
style="fill:#fe941d;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle3"
|
||||
cx="-68.30127"
|
||||
cy="52.906147"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#001996;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle4"
|
||||
cx="-68.30127"
|
||||
cy="-16.30361"
|
||||
r="8.2508707"
|
||||
transform="rotate(-120)" /><circle
|
||||
style="fill:#ffff04;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle5"
|
||||
cx="-18.301271"
|
||||
cy="102.90615"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:#770287;stroke:#ffffff;stroke-width:5;stroke-linecap:round;stroke-linejoin:round;fill-opacity:1;stroke-dasharray:none"
|
||||
id="circle6"
|
||||
cx="-18.301271"
|
||||
cy="33.696392"
|
||||
r="8.2508707"
|
||||
transform="rotate(-60)" /><circle
|
||||
style="fill:none;fill-opacity:1;stroke:#ffffff;stroke-width:6.75;stroke-linecap:round;stroke-linejoin:round;stroke-dasharray:none"
|
||||
id="path7"
|
||||
cx="50"
|
||||
cy="50"
|
||||
r="9.7918472" /><g
|
||||
inkscape:label="Layer 1"
|
||||
id="layer1-3"
|
||||
transform="matrix(0.08246781,0,0,0.08246781,38.828362,38.828362)"
|
||||
style="stroke:#ffffff"><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><circle
|
||||
style="fill:#354b5f;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
id="path342"
|
||||
cx="135.46666"
|
||||
cy="135.46666"
|
||||
r="135.46666" /><text
|
||||
xml:space="preserve"
|
||||
style="font-style:normal;font-variant:normal;font-weight:900;font-stretch:normal;font-size:96.3615px;line-height:0;font-family:'Noto Serif';-inkscape-font-specification:'Noto Serif, Heavy';font-variant-ligatures:normal;font-variant-caps:normal;font-variant-numeric:normal;font-variant-east-asian:normal;text-align:end;text-anchor:end;fill:#ffffff;fill-opacity:1;stroke:#ffffff;stroke-width:0;stroke-dasharray:none;stroke-opacity:1"
|
||||
x="-305.64749"
|
||||
y="194.14493"
|
||||
id="text2819-3"><tspan
|
||||
sodipodi:role="line"
|
||||
id="tspan2817-5"
|
||||
style="stroke:#ffffff;stroke-width:0"
|
||||
x="-305.64749"
|
||||
y="194.14493" /></text><g
|
||||
aria-label="❯"
|
||||
id="text2827-6"
|
||||
style="font-size:132.452px;line-height:0;font-family:PowerlineSymbols;-inkscape-font-specification:'PowerlineSymbols, Normal';text-align:end;text-anchor:end;fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0"><path
|
||||
d="M 95.096912,209.8167 143.88912,135.46666 95.096912,61.116629 h 32.818568 l 47.92093,74.350031 -47.92093,74.35004 z"
|
||||
id="path2883-2"
|
||||
style="fill:#4e94e4;fill-opacity:1;stroke:#ffffff;stroke-width:0" /></g></g></g></svg>
|
||||
stop-color="#26A269"
|
||||
id="stop16" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint1_linear_4023_558"
|
||||
x1="12"
|
||||
y1="108"
|
||||
x2="17"
|
||||
y2="108"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#1A5FB4"
|
||||
id="stop17" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#35E0F6"
|
||||
id="stop18" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint2_linear_4023_558"
|
||||
x1="100"
|
||||
y1="108"
|
||||
x2="78"
|
||||
y2="108"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#A51D2D"
|
||||
id="stop19" />
|
||||
<stop
|
||||
offset="0.195858"
|
||||
stop-color="#E5673C"
|
||||
id="stop20" />
|
||||
<stop
|
||||
offset="0.5983"
|
||||
stop-color="#A51D2D"
|
||||
id="stop21" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint3_linear_4023_558"
|
||||
x1="88"
|
||||
y1="111.329"
|
||||
x2="24"
|
||||
y2="111.329"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
offset="0.102371"
|
||||
stop-color="white"
|
||||
stop-opacity="0"
|
||||
id="stop22" />
|
||||
<stop
|
||||
offset="0.253808"
|
||||
stop-color="white"
|
||||
id="stop23" />
|
||||
<stop
|
||||
offset="0.747697"
|
||||
stop-color="white"
|
||||
id="stop24" />
|
||||
<stop
|
||||
offset="0.895556"
|
||||
stop-color="white"
|
||||
stop-opacity="0"
|
||||
id="stop25" />
|
||||
</linearGradient>
|
||||
<linearGradient
|
||||
id="paint4_linear_4023_558"
|
||||
x1="44"
|
||||
y1="48.036098"
|
||||
x2="126"
|
||||
y2="48.036098"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#DBEBF4"
|
||||
id="stop26" />
|
||||
<stop
|
||||
offset="0.147387"
|
||||
stop-color="#B1D4E7"
|
||||
id="stop27" />
|
||||
<stop
|
||||
offset="0.186621"
|
||||
stop-color="#8DC0DC"
|
||||
id="stop28" />
|
||||
<stop
|
||||
offset="0.203755"
|
||||
stop-color="#49AEE7"
|
||||
id="stop29" />
|
||||
<stop
|
||||
offset="0.276122"
|
||||
stop-color="#7AB5D7"
|
||||
id="stop30" />
|
||||
<stop
|
||||
offset="0.399628"
|
||||
stop-color="#B3D6E7"
|
||||
id="stop31" />
|
||||
<stop
|
||||
offset="0.507537"
|
||||
stop-color="#B3D6E7"
|
||||
id="stop32" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#DBEBF4"
|
||||
id="stop33" />
|
||||
</linearGradient>
|
||||
<radialGradient
|
||||
id="paint5_radial_4023_558"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,101,33.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop34" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop35" />
|
||||
</radialGradient>
|
||||
<clipPath
|
||||
id="clip0_4023_558">
|
||||
<rect
|
||||
x="12"
|
||||
y="36"
|
||||
width="88"
|
||||
height="80"
|
||||
rx="12"
|
||||
fill="#ffffff"
|
||||
id="rect35" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 6.8 KiB After Width: | Height: | Size: 9.2 KiB |
BIN
assets/mobile.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
156
assets/mobile.svg
Normal file
|
|
@ -0,0 +1,156 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="mobile.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="30.03125"
|
||||
inkscape:cx="14.51821"
|
||||
inkscape:cy="11.038502"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg11" />
|
||||
<g
|
||||
id="g11"
|
||||
transform="scale(4)">
|
||||
<g
|
||||
clip-path="url(#clip0_4033_8)"
|
||||
id="g10">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect1"
|
||||
x="0"
|
||||
y="0" />
|
||||
<rect
|
||||
x="60"
|
||||
y="-107"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="rotate(30,60,-107)"
|
||||
fill="#9141ac"
|
||||
id="rect2" />
|
||||
<rect
|
||||
x="90.793198"
|
||||
y="-89.221497"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,90.7932,-89.2215)"
|
||||
fill="#62a0ea"
|
||||
id="rect3" />
|
||||
<rect
|
||||
x="113.888"
|
||||
y="-75.887703"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,113.888,-75.8877)"
|
||||
fill="#57e389"
|
||||
id="rect4" />
|
||||
<rect
|
||||
x="136.983"
|
||||
y="-62.553799"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,136.983,-62.5538)"
|
||||
fill="#f5c211"
|
||||
id="rect5" />
|
||||
<rect
|
||||
x="160.078"
|
||||
y="-49.220001"
|
||||
width="26.6677"
|
||||
height="291.86301"
|
||||
transform="rotate(30,160.078,-49.22)"
|
||||
fill="#ff7800"
|
||||
id="rect6" />
|
||||
<rect
|
||||
x="183.173"
|
||||
y="-35.886101"
|
||||
width="35.5569"
|
||||
height="291.86301"
|
||||
transform="rotate(30,183.173,-35.8861)"
|
||||
fill="#ed333b"
|
||||
id="rect7" />
|
||||
<path
|
||||
d="m 64,23 c 22.6437,0 41,18.3563 41,41 0,22.6437 -18.3563,41 -41,41 -8.6457,0 -16.6648,-2.678 -23.2773,-7.2471 l -9.8018,2.1914 c -1.7167,0.3837 -3.2488,-1.1485 -2.8652,-2.8652 l 2.1904,-9.8027 C 25.6776,80.6641 23,72.6452 23,64 23,41.3563 41.3563,23 64,23 Z"
|
||||
fill="#ffffff"
|
||||
id="path7" />
|
||||
<path
|
||||
d="m 76.2297,62.8668 c 0.4643,0.683 0.461,1.5812 -0.0083,2.2608 L 65.1666,81.1365 C 64.7932,81.6772 64.178,82 63.5209,82 H 58.737 c -1.5974,0 -2.5501,-1.7803 -1.6641,-3.1094 l 9.1875,-13.7812 c 0.4479,-0.6718 0.4479,-1.547 0,-2.2188 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 4.9687 c 0.6623,0 1.2817,0.3279 1.654,0.8757 z"
|
||||
fill="url(#paint0_radial_4033_8)"
|
||||
id="path8"
|
||||
style="fill:url(#paint0_radial_4033_8)" />
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<g
|
||||
mask="url(#mask0_4033_8)"
|
||||
id="g9">
|
||||
<rect
|
||||
x="52"
|
||||
y="46"
|
||||
width="17"
|
||||
height="4"
|
||||
fill="#2779dd"
|
||||
id="rect9" />
|
||||
</g>
|
||||
</g>
|
||||
</g>
|
||||
<defs
|
||||
id="defs11">
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(3.5,24.5214,-15.8099,2.26053,80,52.9904)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<clipPath
|
||||
id="clip0_4033_8">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect11"
|
||||
x="0"
|
||||
y="0" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 4.6 KiB |
BIN
assets/monochrome.png
Normal file
|
After Width: | Height: | Size: 9.1 KiB |
178
assets/monochrome.svg
Normal file
|
|
@ -0,0 +1,178 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<svg
|
||||
width="512"
|
||||
height="512"
|
||||
viewBox="0 0 512 512"
|
||||
fill="none"
|
||||
version="1.1"
|
||||
id="svg11"
|
||||
sodipodi:docname="monochrome.svg"
|
||||
inkscape:version="1.4.3 (0d15f75042, 2025-12-25)"
|
||||
inkscape:export-filename="foreground.png"
|
||||
inkscape:export-xdpi="96"
|
||||
inkscape:export-ydpi="96"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:xlink="http://www.w3.org/1999/xlink"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
xmlns:svg="http://www.w3.org/2000/svg">
|
||||
<sodipodi:namedview
|
||||
id="namedview11"
|
||||
pagecolor="#505050"
|
||||
bordercolor="#eeeeee"
|
||||
borderopacity="1"
|
||||
inkscape:showpageshadow="0"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pagecheckerboard="0"
|
||||
inkscape:deskcolor="#505050"
|
||||
inkscape:zoom="1.240199"
|
||||
inkscape:cx="156.02335"
|
||||
inkscape:cy="321.3194"
|
||||
inkscape:window-width="2544"
|
||||
inkscape:window-height="1363"
|
||||
inkscape:window-x="35"
|
||||
inkscape:window-y="32"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="svg11" />
|
||||
<path
|
||||
d="m 256,92 c 90.5748,0 164,73.4252 164,164 0,90.5748 -73.4252,164 -164,164 -34.5828,0 -66.6592,-10.712 -93.1092,-28.9884 l -39.2072,8.7656 c -6.8668,1.5348 -12.9952,-4.594 -11.4608,-11.4608 l 8.7616,-39.2108 C 102.7104,322.6564 92,290.5808 92,256 92,165.4252 165.4252,92 256,92 Z"
|
||||
fill="#ffffff"
|
||||
id="path7"
|
||||
style="stroke-width:4"
|
||||
clip-path="url(#clipPath1)"
|
||||
inkscape:path-effect="#path-effect1" />
|
||||
<defs
|
||||
id="defs11">
|
||||
<inkscape:path-effect
|
||||
effect="powerclip"
|
||||
message=""
|
||||
id="path-effect1"
|
||||
is_visible="true"
|
||||
lpeversion="1"
|
||||
inverse="true"
|
||||
flatten="false"
|
||||
hide_clip="false" />
|
||||
<radialGradient
|
||||
id="paint0_radial_4033_8"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
gradientUnits="userSpaceOnUse">
|
||||
<stop
|
||||
stop-color="#72AAEE"
|
||||
id="stop10" />
|
||||
<stop
|
||||
offset="1"
|
||||
stop-color="#3584E4"
|
||||
id="stop11" />
|
||||
</radialGradient>
|
||||
<mask
|
||||
id="mask0_4033_8"
|
||||
maskUnits="userSpaceOnUse"
|
||||
x="56"
|
||||
y="46"
|
||||
width="21"
|
||||
height="36">
|
||||
<path
|
||||
d="m 76.4223,63.1501 c 0.3482,0.5123 0.3457,1.1859 -0.0063,1.6956 L 65.0175,81.3524 C 64.7375,81.7579 64.2761,82 63.7832,82 h -5.9804 c -1.1981,0 -1.9127,-1.3352 -1.2481,-2.332 l 9.8906,-14.8359 c 0.3359,-0.5039 0.3359,-1.1603 0,-1.6641 L 57.0729,49.1094 C 56.1869,47.7803 57.1396,46 58.737,46 h 5.2334 c 0.4967,0 0.9613,0.2459 1.2405,0.6568 z"
|
||||
fill="#2779dd"
|
||||
id="path9" />
|
||||
</mask>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath11">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect12"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath12">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect13"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath13">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect14"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath14">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect15"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath15">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect16"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath16">
|
||||
<rect
|
||||
width="128"
|
||||
height="128"
|
||||
fill="#ffffff"
|
||||
id="rect17"
|
||||
x="0"
|
||||
y="0"
|
||||
transform="rotate(-30)" />
|
||||
</clipPath>
|
||||
<clipPath
|
||||
clipPathUnits="userSpaceOnUse"
|
||||
id="clipPath1">
|
||||
<path
|
||||
d="m 304.9188,251.4672 c 1.8572,2.732 1.844,6.3248 -0.0332,9.0432 L 260.6664,324.546 C 259.1728,326.7088 256.712,328 254.0836,328 H 234.948 c -6.3896,0 -10.2004,-7.1212 -6.6564,-12.4376 l 36.75,-55.1248 c 1.7916,-2.6872 1.7916,-6.188 0,-8.8752 l -36.75,-55.1248 C 224.7476,191.1212 228.5584,184 234.948,184 h 19.8748 c 2.6492,0 5.1268,1.3116 6.616,3.5028 z"
|
||||
fill="url(#paint0_radial_4033_8)"
|
||||
id="path1"
|
||||
style="display:none;fill:url(#radialGradient1);stroke-width:4" />
|
||||
<path
|
||||
id="lpe_path-effect1"
|
||||
style="fill:url(#radialGradient1);stroke-width:4"
|
||||
class="powerclip"
|
||||
d="M 87,87 H 425 V 425 H 87 Z m 217.9188,164.4672 -43.48,-63.9644 C 259.9496,185.3116 257.472,184 254.8228,184 H 234.948 c -6.3896,0 -10.2004,7.1212 -6.6564,12.4376 l 36.75,55.1248 c 1.7916,2.6872 1.7916,6.188 0,8.8752 l -36.75,55.1248 C 224.7476,320.8788 228.5584,328 234.948,328 h 19.1356 c 2.6284,0 5.0892,-1.2912 6.5828,-3.454 l 44.2192,-64.0356 c 1.8772,-2.7184 1.8904,-6.3112 0.0332,-9.0432 z" />
|
||||
</clipPath>
|
||||
<radialGradient
|
||||
inkscape:collect="always"
|
||||
xlink:href="#paint0_radial_4033_8"
|
||||
id="radialGradient1"
|
||||
gradientUnits="userSpaceOnUse"
|
||||
gradientTransform="matrix(14,98.0856,-63.2396,9.04212,320,211.9616)"
|
||||
cx="0"
|
||||
cy="0"
|
||||
r="1" />
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 423 KiB After Width: | Height: | Size: 616 KiB |
|
Before Width: | Height: | Size: 425 KiB After Width: | Height: | Size: 616 KiB |
BIN
assets/twim/oauth.webp
Normal file
|
After Width: | Height: | Size: 1.2 MiB |
BIN
assets/twim/settings.png
Normal file
|
After Width: | Height: | Size: 130 KiB |
113
flake.lock
generated
|
|
@ -5,11 +5,11 @@
|
|||
"nixpkgs-lib": "nixpkgs-lib"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1767609335,
|
||||
"narHash": "sha256-feveD98mQpptwrAEggBQKJTYbvwwglSbOv53uCfH9PY=",
|
||||
"lastModified": 1785627969,
|
||||
"narHash": "sha256-4dtXQk/NMePegK/nWp5NSeuZKLATItOq61lpEvmXqGw=",
|
||||
"owner": "hercules-ci",
|
||||
"repo": "flake-parts",
|
||||
"rev": "250481aafeb741edfe23d29195671c19b36b6dca",
|
||||
"rev": "427bf4bd9435fdf21321c8cc628c24efc14c0f7a",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -18,13 +18,81 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"flake-utils": {
|
||||
"inputs": {
|
||||
"systems": "systems"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1731533236,
|
||||
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "numtide",
|
||||
"repo": "flake-utils",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nix2flatpak": {
|
||||
"inputs": {
|
||||
"flake-utils": "flake-utils",
|
||||
"nixpkgs": "nixpkgs"
|
||||
},
|
||||
"locked": {
|
||||
"lastModified": 1774860670,
|
||||
"narHash": "sha256-YjJkQrvxrErXtfDi3obUn6rNmkA+CIAZ3f5NgL5xuYE=",
|
||||
"owner": "neobrain",
|
||||
"repo": "nix2flatpak",
|
||||
"rev": "61d68e21e3fbc2d57590051f48736bea271f4aba",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "neobrain",
|
||||
"repo": "nix2flatpak",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs": {
|
||||
"locked": {
|
||||
"lastModified": 1767640445,
|
||||
"narHash": "sha256-UWYqmD7JFBEDBHWYcqE6s6c77pWdcU/i+bwD6XxMb8A=",
|
||||
"lastModified": 1773389992,
|
||||
"narHash": "sha256-wvfdLLWJ2I9oEpDd9PfMA8osfIZicoQ5MT1jIwNs9Tk=",
|
||||
"owner": "NixOS",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "c06b4ae3d6599a672a6210b7021d699c351eebda",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "NixOS",
|
||||
"ref": "nixos-unstable",
|
||||
"repo": "nixpkgs",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1785031560,
|
||||
"narHash": "sha256-OmshNvn2vupOFpYinLUu+1Dnpu4n7Q5N3ggGVNHpkUI=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "0e79af5e3d4dcfcd676ab5ba3f95d2e3352e078c",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs_2": {
|
||||
"locked": {
|
||||
"lastModified": 1785967620,
|
||||
"narHash": "sha256-IItrdb7Puk05RqOBWZYFC5X6Wl1sJmCfh5MWVHw5iMM=",
|
||||
"owner": "nixos",
|
||||
"repo": "nixpkgs",
|
||||
"rev": "9f0c42f8bc7151b8e7e5840fb3bd454ad850d8c5",
|
||||
"rev": "b7c2ada94fe99c15b0dbcf4d11fd7850b957a436",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
|
|
@ -34,25 +102,26 @@
|
|||
"type": "github"
|
||||
}
|
||||
},
|
||||
"nixpkgs-lib": {
|
||||
"locked": {
|
||||
"lastModified": 1765674936,
|
||||
"narHash": "sha256-k00uTP4JNfmejrCLJOwdObYC9jHRrr/5M/a/8L2EIdo=",
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"rev": "2075416fcb47225d9b68ac469a5c4801a9c4dd85",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-community",
|
||||
"repo": "nixpkgs.lib",
|
||||
"type": "github"
|
||||
}
|
||||
},
|
||||
"root": {
|
||||
"inputs": {
|
||||
"flake-parts": "flake-parts",
|
||||
"nixpkgs": "nixpkgs"
|
||||
"nix2flatpak": "nix2flatpak",
|
||||
"nixpkgs": "nixpkgs_2"
|
||||
}
|
||||
},
|
||||
"systems": {
|
||||
"locked": {
|
||||
"lastModified": 1681028828,
|
||||
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
|
||||
"type": "github"
|
||||
},
|
||||
"original": {
|
||||
"owner": "nix-systems",
|
||||
"repo": "default",
|
||||
"type": "github"
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
|||
45
flake.nix
|
|
@ -2,8 +2,10 @@
|
|||
description = "Nexus Flutter Flake";
|
||||
|
||||
inputs = {
|
||||
self.submodules = true;
|
||||
nixpkgs.url = "github:nixos/nixpkgs/nixos-unstable";
|
||||
flake-parts.url = "github:hercules-ci/flake-parts";
|
||||
nix2flatpak.url = "github:neobrain/nix2flatpak";
|
||||
};
|
||||
|
||||
outputs =
|
||||
|
|
@ -33,36 +35,43 @@
|
|||
_module.args.pkgs = import nixpkgs {
|
||||
inherit system;
|
||||
config = {
|
||||
permittedInsecurePackages = [ "olm-3.2.16" ];
|
||||
android_sdk.accept_license = true;
|
||||
allowUnfree = true;
|
||||
};
|
||||
};
|
||||
|
||||
devShells =
|
||||
packages =
|
||||
let
|
||||
packages = with pkgs; [
|
||||
go
|
||||
olm
|
||||
git
|
||||
];
|
||||
|
||||
env = {
|
||||
LIBCLANG_PATH = lib.makeLibraryPath [ pkgs.libclang ];
|
||||
LD_LIBRARY_PATH = "./build/native_assets/linux:${lib.makeLibraryPath [ pkgs.zlib ]}";
|
||||
CPATH = lib.makeSearchPath "include" [ pkgs.glibc.dev ];
|
||||
default = pkgs.callPackage ./linux/nix/pkg {
|
||||
src = self;
|
||||
};
|
||||
in
|
||||
{
|
||||
default = pkgs.mkShell {
|
||||
inherit env;
|
||||
packages = packages ++ [
|
||||
pkgs.flutter
|
||||
];
|
||||
inherit default;
|
||||
|
||||
flatpak = inputs.nix2flatpak.lib.${system}.mkFlatpak {
|
||||
appName = "Nexus";
|
||||
developer = "QuadRadical";
|
||||
appId = "nexus.federated.nexus";
|
||||
package = default;
|
||||
runtime = "org.gnome.Platform/49";
|
||||
permissions = {
|
||||
share = [ "network" ];
|
||||
sockets = [
|
||||
"pulseaudio"
|
||||
"fallback-x11"
|
||||
"wayland"
|
||||
];
|
||||
devices = [ "dri" ];
|
||||
};
|
||||
};
|
||||
|
||||
nix = pkgs.mkShell { inherit packages env; };
|
||||
gomuks = pkgs.callPackage ./linux/nix/pkg/gomuks.nix {
|
||||
src = self;
|
||||
};
|
||||
};
|
||||
|
||||
devShells.default = pkgs.callPackage ./linux/nix/devshell.nix { };
|
||||
};
|
||||
};
|
||||
}
|
||||
|
|
|
|||
1
gomuks
Submodule
|
|
@ -0,0 +1 @@
|
|||
Subproject commit 9444dd293664c300c6e710bb6cddcd9c6cab365d
|
||||
181
hook/build.dart
|
|
@ -1,40 +1,193 @@
|
|||
import "dart:io";
|
||||
import "package:collection/collection.dart";
|
||||
import "package:hooks/hooks.dart";
|
||||
import "package:code_assets/code_assets.dart";
|
||||
import "package:nexus/helpers/extensions/get_xcode_sdk.dart";
|
||||
import "package:path/path.dart";
|
||||
|
||||
Future<void> main(List<String> args) => build(args, (input, output) async {
|
||||
final buildDir = input.packageRoot.resolve("src/");
|
||||
if (await File(buildDir.resolve("lock").toFilePath()).exists()) return;
|
||||
if (!input.config.buildCodeAssets) return;
|
||||
final codeConfig = input.config.code;
|
||||
final targetOS = codeConfig.targetOS;
|
||||
final targetArch = codeConfig.targetArchitecture;
|
||||
|
||||
final targetOS = input.config.code.targetOS;
|
||||
String libFileName;
|
||||
Map<String, String> extraEnv = {};
|
||||
IOSSdk? iosSdk;
|
||||
String? iosSdkPath;
|
||||
String? iosTargetTriple;
|
||||
switch (targetOS) {
|
||||
case OS.linux:
|
||||
libFileName = "libgomuks.so";
|
||||
break;
|
||||
case OS.iOS:
|
||||
// Go only supports buildmode=c-archive for ios, not c-shared, so the
|
||||
// archive built below gets linked into a dylib via a separate clang
|
||||
// invocation before being registered as a normal asset like macOS.
|
||||
libFileName = "libgomuks.dylib";
|
||||
final iosConfig = codeConfig.iOS;
|
||||
iosSdk = iosConfig.targetSdk;
|
||||
final minVersion = iosConfig.targetVersion;
|
||||
iosSdkPath = await getXCodeTool(sdkType: iosSdk.type);
|
||||
|
||||
final archTriple = switch (targetArch) {
|
||||
Architecture.arm64 => "arm64",
|
||||
Architecture.x64 => "x86_64",
|
||||
_ => throw UnsupportedError(
|
||||
"Unsupported iOS architecture: $targetArch",
|
||||
),
|
||||
};
|
||||
|
||||
iosTargetTriple = iosSdk == IOSSdk.iPhoneSimulator
|
||||
? "$archTriple-apple-ios$minVersion.0-simulator"
|
||||
: "$archTriple-apple-ios$minVersion.0";
|
||||
extraEnv = {
|
||||
"GOOS": "ios",
|
||||
"CC": await getXCodeTool(sdkType: iosSdk.type, findTool: "clang"),
|
||||
"CGO_CFLAGS": "-isysroot $iosSdkPath -target $iosTargetTriple",
|
||||
"CGO_LDFLAGS": "-isysroot $iosSdkPath -target $iosTargetTriple",
|
||||
};
|
||||
break;
|
||||
case OS.macOS:
|
||||
libFileName = "libgomuks.dylib";
|
||||
extraEnv = {
|
||||
"SDKROOT": await getXCodeTool(),
|
||||
"MACOSX_DEPLOYMENT_TARGET": codeConfig.macOS.targetVersion.toString(),
|
||||
};
|
||||
break;
|
||||
case OS.windows:
|
||||
libFileName = "libgomuks.dll";
|
||||
break;
|
||||
case OS.android:
|
||||
libFileName = "libgomuks.so";
|
||||
|
||||
final targetNdkApi = codeConfig.android.targetNdkApi;
|
||||
|
||||
Future<String?> findNdkFromSdk() async {
|
||||
final androidHome =
|
||||
Platform.environment["ANDROID_HOME"] ??
|
||||
Platform.environment["ANDROID_SDK_ROOT"];
|
||||
if (androidHome == null) return null;
|
||||
|
||||
final ndkDir = Directory(join(androidHome, "ndk"));
|
||||
if (!await ndkDir.exists()) return null;
|
||||
|
||||
final versions = await ndkDir.list().toList();
|
||||
return versions.sortedBy((file) => file.path).lastOrNull?.path;
|
||||
}
|
||||
|
||||
final ndkHome =
|
||||
Platform.environment["ANDROID_NDK_HOME"] ??
|
||||
Platform.environment["ANDROID_NDK_ROOT"] ??
|
||||
Platform.environment["NDK_HOME"] ??
|
||||
await findNdkFromSdk();
|
||||
|
||||
if (ndkHome == null) {
|
||||
throw Exception(
|
||||
"Could not find Android NDK. Set ANDROID_NDK_HOME or install via sdkmanager.",
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: Someone please give me a way to detect host architecture so I can change this
|
||||
final hostTag =
|
||||
Platform.environment["ANDROID_HOST_TAG"] ??
|
||||
"${Platform.operatingSystem}-x86_64";
|
||||
final ccTriple = switch (targetArch) {
|
||||
Architecture.arm64 => "aarch64-linux-android",
|
||||
Architecture.arm => "armv7a-linux-androideabi",
|
||||
Architecture.x64 => "x86_64-linux-android",
|
||||
Architecture.ia32 => "i686-linux-android",
|
||||
_ => throw UnsupportedError(
|
||||
"Unsupported Android architecture: $targetArch",
|
||||
),
|
||||
};
|
||||
final cc =
|
||||
"$ndkHome/toolchains/llvm/prebuilt/$hostTag/bin/$ccTriple$targetNdkApi-clang";
|
||||
|
||||
extraEnv = {"GOOS": "android", "CC": cc};
|
||||
break;
|
||||
default:
|
||||
throw UnsupportedError("Unsupported OS: $targetOS");
|
||||
}
|
||||
|
||||
final gomuksBuildDir = buildDir.resolve("gomuks/");
|
||||
final libFile = gomuksBuildDir.resolve(libFileName);
|
||||
var libFile = input.packageRoot.resolve(libFileName);
|
||||
final gomuksBuildDir = input.packageRoot.resolve("gomuks/");
|
||||
|
||||
print("Building Gomuks shared library $libFileName from source...");
|
||||
final result = await Process.run("go", [
|
||||
"build",
|
||||
"-o",
|
||||
libFile.path,
|
||||
"-buildmode=c-shared",
|
||||
], workingDirectory: gomuksBuildDir.resolve("source/pkg/ffi/").toFilePath());
|
||||
if (!(await File.fromUri(libFile).exists())) {
|
||||
final buildDir = input.packageRoot.resolve("build/");
|
||||
libFile = buildDir.resolve("${targetArch.name}/$libFileName");
|
||||
|
||||
if (result.exitCode != 0) {
|
||||
throw Exception("Failed to build Gomuks shared library\n${result.stderr}");
|
||||
final tags = [
|
||||
"sqlite_fts5",
|
||||
"goolm",
|
||||
// goheif/dav1d is not supported on Android or iOS, would need to be fixed upstream
|
||||
if (targetOS == OS.android || targetOS == OS.iOS) "noheic",
|
||||
].join(",");
|
||||
|
||||
final archiveFile = targetOS == OS.iOS
|
||||
? buildDir.resolve("${targetArch.name}/libgomuks.a")
|
||||
: libFile;
|
||||
print(
|
||||
"Building Gomuks shared library $libFileName (${targetOS.name}/${targetArch.name}) to ${archiveFile.path}...",
|
||||
);
|
||||
final result = await Process.run(
|
||||
"go",
|
||||
[
|
||||
"build",
|
||||
"-tags",
|
||||
tags,
|
||||
"-o",
|
||||
archiveFile.path,
|
||||
"-buildmode=${targetOS == OS.iOS ? "c-archive" : "c-shared"}",
|
||||
],
|
||||
workingDirectory: gomuksBuildDir.resolve("pkg/ffi/").toFilePath(),
|
||||
environment: {
|
||||
"CGO_ENABLED": "1",
|
||||
"GOARCH": switch (targetArch) {
|
||||
Architecture.arm64 => "arm64",
|
||||
Architecture.arm => "arm",
|
||||
Architecture.x64 => "amd64",
|
||||
Architecture.ia32 => "386",
|
||||
_ => throw UnsupportedError("Unsupported architecture: $targetArch"),
|
||||
},
|
||||
...extraEnv,
|
||||
},
|
||||
);
|
||||
|
||||
if (result.exitCode != 0) {
|
||||
throw Exception(
|
||||
"Failed to build Gomuks shared library\n${result.stderr}",
|
||||
);
|
||||
}
|
||||
|
||||
if (targetOS == OS.iOS) {
|
||||
print("Linking $archiveFile into $libFile...");
|
||||
final linkResult = await Process.run("xcrun", [
|
||||
"--sdk",
|
||||
iosSdk!.type,
|
||||
"clang",
|
||||
"-dynamiclib",
|
||||
"-isysroot",
|
||||
iosSdkPath!,
|
||||
"-target",
|
||||
iosTargetTriple!,
|
||||
"-install_name",
|
||||
"@rpath/libgomuks.dylib",
|
||||
"-framework",
|
||||
"Security",
|
||||
"-framework",
|
||||
"CoreFoundation",
|
||||
"-framework",
|
||||
"SystemConfiguration",
|
||||
"-force_load",
|
||||
archiveFile.path,
|
||||
"-o",
|
||||
libFile.path,
|
||||
]);
|
||||
if (linkResult.exitCode != 0) {
|
||||
throw Exception("Failed to link Gomuks dylib\n${linkResult.stderr}");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
final generatedFile = "src/third_party/gomuks.g.dart";
|
||||
|
|
|
|||
|
|
@ -2,25 +2,23 @@
|
|||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>nexus.federated.Nexus</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
<key>MinimumOSVersion</key>
|
||||
<string>15.5</string>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>en</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>App</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>io.flutter.flutter.app</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>App</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>FMWK</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>1.0</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>1.0</string>
|
||||
</dict>
|
||||
</plist>
|
||||
|
|
|
|||
30
ios/Podfile
|
|
@ -1,4 +1,7 @@
|
|||
platform :ios, 16
|
||||
# Uncomment this line to define a global platform for your project
|
||||
# platform :ios, '13.0'
|
||||
|
||||
# CocoaPods analytics sends network stats synchronously affecting flutter build latency.
|
||||
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
|
||||
|
||||
project 'Runner', {
|
||||
|
|
@ -26,30 +29,15 @@ flutter_ios_podfile_setup
|
|||
|
||||
target 'Runner' do
|
||||
use_frameworks!
|
||||
use_modular_headers!
|
||||
|
||||
|
||||
flutter_install_all_ios_pods File.dirname(File.realpath(__FILE__))
|
||||
target 'RunnerTests' do
|
||||
inherit! :search_paths
|
||||
end
|
||||
end
|
||||
|
||||
post_install do |installer|
|
||||
installer.pods_project.targets.each do |target|
|
||||
target.build_configurations.each do |config|
|
||||
if config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] == '8.0'
|
||||
config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '11.0'
|
||||
end
|
||||
end
|
||||
flutter_additional_ios_build_settings target
|
||||
flutter_additional_ios_build_settings(target)
|
||||
end
|
||||
|
||||
################ Awesome Notifications pod modification 1 ###################
|
||||
awesome_pod_file = File.expand_path(File.join('plugins', 'awesome_notifications', 'ios', 'Scripts', 'AwesomePodFile'), '.symlinks')
|
||||
require awesome_pod_file
|
||||
update_awesome_pod_build_settings(installer)
|
||||
################ Awesome Notifications pod modification 1 ###################
|
||||
end
|
||||
|
||||
################ Awesome Notifications pod modification 2 ###################
|
||||
awesome_pod_file = File.expand_path(File.join('plugins', 'awesome_notifications', 'ios', 'Scripts', 'AwesomePodFile'), '.symlinks')
|
||||
require awesome_pod_file
|
||||
update_awesome_main_target_settings('Runner', File.dirname(File.realpath(__FILE__)), flutter_root)
|
||||
################ Awesome Notifications pod modification 2 ###################
|
||||
|
|
|
|||
28
ios/Podfile.lock
Normal file
|
|
@ -0,0 +1,28 @@
|
|||
PODS:
|
||||
- Flutter (1.0.0)
|
||||
- media_kit_libs_ios_video (1.0.4):
|
||||
- Flutter
|
||||
- media_kit_video (0.0.1):
|
||||
- Flutter
|
||||
|
||||
DEPENDENCIES:
|
||||
- Flutter (from `Flutter`)
|
||||
- media_kit_libs_ios_video (from `.symlinks/plugins/media_kit_libs_ios_video/ios`)
|
||||
- media_kit_video (from `.symlinks/plugins/media_kit_video/ios`)
|
||||
|
||||
EXTERNAL SOURCES:
|
||||
Flutter:
|
||||
:path: Flutter
|
||||
media_kit_libs_ios_video:
|
||||
:path: ".symlinks/plugins/media_kit_libs_ios_video/ios"
|
||||
media_kit_video:
|
||||
:path: ".symlinks/plugins/media_kit_video/ios"
|
||||
|
||||
SPEC CHECKSUMS:
|
||||
Flutter: cabc95a1d2626b1b06e7179b784ebcf0c0cde467
|
||||
media_kit_libs_ios_video: 5a18affdb97d1f5d466dc79988b13eff6c5e2854
|
||||
media_kit_video: 1746e198cb697d1ffb734b1d05ec429d1fcd1474
|
||||
|
||||
PODFILE CHECKSUM: 3c63482e143d1b91d2d2560aee9fb04ecc74ac7e
|
||||
|
||||
COCOAPODS: 1.17.0
|
||||
|
|
@ -8,14 +8,28 @@
|
|||
|
||||
/* Begin PBXBuildFile section */
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */ = {isa = PBXBuildFile; fileRef = 1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */; };
|
||||
3965FF1D950A2B2E051F6219 /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 5E598BBDD2ED0112E344B590 /* Pods_Runner.framework */; };
|
||||
2ADFEE6C745FFB2100CC9AFD /* Pods_RunnerTests.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8156A45F510382D558AED93A /* Pods_RunnerTests.framework */; };
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 331C807B294A618700263BE5 /* RunnerTests.swift */; };
|
||||
3B3967161E833CAA004F5970 /* AppFrameworkInfo.plist in Resources */ = {isa = PBXBuildFile; fileRef = 3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */; };
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 74858FAE1ED2DC5600515810 /* AppDelegate.swift */; };
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */; };
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */ = {isa = PBXBuildFile; productRef = 78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */; };
|
||||
88D55A5F1C7625122EBEE29D /* Pods_Runner.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 82F9A3759658343C81A0EA4C /* Pods_Runner.framework */; };
|
||||
97C146FC1CF9000F007C117D /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FA1CF9000F007C117D /* Main.storyboard */; };
|
||||
97C146FE1CF9000F007C117D /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FD1CF9000F007C117D /* Assets.xcassets */; };
|
||||
97C147011CF9000F007C117D /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 97C146FF1CF9000F007C117D /* LaunchScreen.storyboard */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
331C8085294A63A400263BE5 /* PBXContainerItemProxy */ = {
|
||||
isa = PBXContainerItemProxy;
|
||||
containerPortal = 97C146E61CF9000F007C117D /* Project object */;
|
||||
proxyType = 1;
|
||||
remoteGlobalIDString = 97C146ED1CF9000F007C117D;
|
||||
remoteInfo = Runner;
|
||||
};
|
||||
/* End PBXContainerItemProxy section */
|
||||
|
||||
/* Begin PBXCopyFilesBuildPhase section */
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */ = {
|
||||
isa = PBXCopyFilesBuildPhase;
|
||||
|
|
@ -32,12 +46,19 @@
|
|||
/* Begin PBXFileReference section */
|
||||
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>"; };
|
||||
22DE4310DAFBE211CDF700B1 /* 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>"; };
|
||||
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; };
|
||||
363A89F6FA09BCCBDED440CE /* 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>"; };
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = AppFrameworkInfo.plist; path = Flutter/AppFrameworkInfo.plist; sourceTree = "<group>"; };
|
||||
5E598BBDD2ED0112E344B590 /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
6A2D47C573B065AD356C7183 /* 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>"; };
|
||||
63516CF65A79A5DDDE64B0D1 /* 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>"; };
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = "Runner-Bridging-Header.h"; sourceTree = "<group>"; };
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = "<group>"; };
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SceneDelegate.swift; sourceTree = "<group>"; };
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */ = {isa = PBXFileReference; lastKnownFileType = wrapper; name = FlutterGeneratedPluginSwiftPackage; path = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage; sourceTree = "<group>"; };
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */ = {isa = PBXFileReference; lastKnownFileType = text.xcconfig; name = Release.xcconfig; path = Flutter/Release.xcconfig; sourceTree = "<group>"; };
|
||||
8156A45F510382D558AED93A /* Pods_RunnerTests.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RunnerTests.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
82F9A3759658343C81A0EA4C /* Pods_Runner.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_Runner.framework; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
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>"; };
|
||||
97C146EE1CF9000F007C117D /* Runner.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Runner.app; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
|
|
@ -45,35 +66,67 @@
|
|||
97C146FD1CF9000F007C117D /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = "<group>"; };
|
||||
97C147001CF9000F007C117D /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = "<group>"; };
|
||||
97C147021CF9000F007C117D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
CA00A9F43BB1AB7D908E180A /* 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>"; };
|
||||
DFFCB3F45BF495277AE4D3EE /* 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>"; };
|
||||
AEB96D8976BD46D6860C7041 /* 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>"; };
|
||||
B8B599FDB72E4713FB7B5A44 /* Pods-RunnerTests.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RunnerTests.debug.xcconfig"; path = "Target Support Files/Pods-RunnerTests/Pods-RunnerTests.debug.xcconfig"; sourceTree = "<group>"; };
|
||||
FE5E4162842555A83F8A7FD7 /* 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>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
8C0A36760DA8B873D8F6DDCE /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
2ADFEE6C745FFB2100CC9AFD /* Pods_RunnerTests.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EB1CF9000F007C117D /* Frameworks */ = {
|
||||
isa = PBXFrameworksBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
3965FF1D950A2B2E051F6219 /* Pods_Runner.framework in Frameworks */,
|
||||
78A318202AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage in Frameworks */,
|
||||
88D55A5F1C7625122EBEE29D /* Pods_Runner.framework in Frameworks */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXFrameworksBuildPhase section */
|
||||
|
||||
/* Begin PBXGroup section */
|
||||
7226BEAE3D25CA120A434CC9 /* Pods */ = {
|
||||
1CFFAE23B502BCCEB2B191A3 /* Pods */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
DFFCB3F45BF495277AE4D3EE /* Pods-Runner.debug.xcconfig */,
|
||||
CA00A9F43BB1AB7D908E180A /* Pods-Runner.release.xcconfig */,
|
||||
6A2D47C573B065AD356C7183 /* Pods-Runner.profile.xcconfig */,
|
||||
AEB96D8976BD46D6860C7041 /* Pods-Runner.debug.xcconfig */,
|
||||
363A89F6FA09BCCBDED440CE /* Pods-Runner.release.xcconfig */,
|
||||
22DE4310DAFBE211CDF700B1 /* Pods-Runner.profile.xcconfig */,
|
||||
B8B599FDB72E4713FB7B5A44 /* Pods-RunnerTests.debug.xcconfig */,
|
||||
FE5E4162842555A83F8A7FD7 /* Pods-RunnerTests.release.xcconfig */,
|
||||
63516CF65A79A5DDDE64B0D1 /* Pods-RunnerTests.profile.xcconfig */,
|
||||
);
|
||||
name = Pods;
|
||||
path = Pods;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
331C8082294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
331C807B294A618700263BE5 /* RunnerTests.swift */,
|
||||
);
|
||||
path = RunnerTests;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
594EB1F65336CF9C7958F6FA /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
82F9A3759658343C81A0EA4C /* Pods_Runner.framework */,
|
||||
8156A45F510382D558AED93A /* Pods_RunnerTests.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
9740EEB11CF90186004384FC /* Flutter */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
78E0A7A72DC9AD7400C4905E /* FlutterGeneratedPluginSwiftPackage */,
|
||||
3B3967151E833CAA004F5970 /* AppFrameworkInfo.plist */,
|
||||
9740EEB21CF90195004384FC /* Debug.xcconfig */,
|
||||
7AFA3C8E1D35360C0083082E /* Release.xcconfig */,
|
||||
|
|
@ -88,8 +141,9 @@
|
|||
9740EEB11CF90186004384FC /* Flutter */,
|
||||
97C146F01CF9000F007C117D /* Runner */,
|
||||
97C146EF1CF9000F007C117D /* Products */,
|
||||
7226BEAE3D25CA120A434CC9 /* Pods */,
|
||||
E396C277672D83FCFDB51CCB /* Frameworks */,
|
||||
331C8082294A63A400263BE5 /* RunnerTests */,
|
||||
1CFFAE23B502BCCEB2B191A3 /* Pods */,
|
||||
594EB1F65336CF9C7958F6FA /* Frameworks */,
|
||||
);
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
|
|
@ -97,6 +151,7 @@
|
|||
isa = PBXGroup;
|
||||
children = (
|
||||
97C146EE1CF9000F007C117D /* Runner.app */,
|
||||
331C8081294A63A400263BE5 /* RunnerTests.xctest */,
|
||||
);
|
||||
name = Products;
|
||||
sourceTree = "<group>";
|
||||
|
|
@ -111,41 +166,55 @@
|
|||
1498D2321E8E86230040F4C2 /* GeneratedPluginRegistrant.h */,
|
||||
1498D2331E8E89220040F4C2 /* GeneratedPluginRegistrant.m */,
|
||||
74858FAE1ED2DC5600515810 /* AppDelegate.swift */,
|
||||
7884E8672EC3CC0400C636F2 /* SceneDelegate.swift */,
|
||||
74858FAD1ED2DC5600515810 /* Runner-Bridging-Header.h */,
|
||||
);
|
||||
path = Runner;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E396C277672D83FCFDB51CCB /* Frameworks */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
5E598BBDD2ED0112E344B590 /* Pods_Runner.framework */,
|
||||
);
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
/* End PBXGroup section */
|
||||
|
||||
/* Begin PBXNativeTarget section */
|
||||
331C8080294A63A400263BE5 /* RunnerTests */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */;
|
||||
buildPhases = (
|
||||
EE82EC529EB6C0F1FA480659 /* [CP] Check Pods Manifest.lock */,
|
||||
331C807D294A63A400263BE5 /* Sources */,
|
||||
331C807F294A63A400263BE5 /* Resources */,
|
||||
8C0A36760DA8B873D8F6DDCE /* Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */,
|
||||
);
|
||||
name = RunnerTests;
|
||||
productName = RunnerTests;
|
||||
productReference = 331C8081294A63A400263BE5 /* RunnerTests.xctest */;
|
||||
productType = "com.apple.product-type.bundle.unit-test";
|
||||
};
|
||||
97C146ED1CF9000F007C117D /* Runner */ = {
|
||||
isa = PBXNativeTarget;
|
||||
buildConfigurationList = 97C147051CF9000F007C117D /* Build configuration list for PBXNativeTarget "Runner" */;
|
||||
buildPhases = (
|
||||
A3B5CB395514F4BF9CDF304E /* [CP] Check Pods Manifest.lock */,
|
||||
0830C6758DA3ECA81FB12386 /* [CP] Check Pods Manifest.lock */,
|
||||
9740EEB61CF901F6004384FC /* Run Script */,
|
||||
97C146EA1CF9000F007C117D /* Sources */,
|
||||
97C146EB1CF9000F007C117D /* Frameworks */,
|
||||
97C146EC1CF9000F007C117D /* Resources */,
|
||||
9705A1C41CF9048500538489 /* Embed Frameworks */,
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */,
|
||||
C3C8545BDAC52D360D298A29 /* [CP] Embed Pods Frameworks */,
|
||||
F46F66CC32F585BBF2FB675E /* [CP] Copy Pods Resources */,
|
||||
1D165FDFB9D0D939B041966D /* [CP] Embed Pods Frameworks */,
|
||||
);
|
||||
buildRules = (
|
||||
);
|
||||
dependencies = (
|
||||
);
|
||||
name = Runner;
|
||||
packageProductDependencies = (
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */,
|
||||
);
|
||||
productName = Runner;
|
||||
productReference = 97C146EE1CF9000F007C117D /* Runner.app */;
|
||||
productType = "com.apple.product-type.application";
|
||||
|
|
@ -160,6 +229,10 @@
|
|||
LastUpgradeCheck = 1510;
|
||||
ORGANIZATIONNAME = "";
|
||||
TargetAttributes = {
|
||||
331C8080294A63A400263BE5 = {
|
||||
CreatedOnToolsVersion = 14.0;
|
||||
TestTargetID = 97C146ED1CF9000F007C117D;
|
||||
};
|
||||
97C146ED1CF9000F007C117D = {
|
||||
CreatedOnToolsVersion = 7.3.1;
|
||||
LastSwiftMigration = 1100;
|
||||
|
|
@ -175,16 +248,27 @@
|
|||
Base,
|
||||
);
|
||||
mainGroup = 97C146E51CF9000F007C117D;
|
||||
packageReferences = (
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */,
|
||||
);
|
||||
productRefGroup = 97C146EF1CF9000F007C117D /* Products */;
|
||||
projectDirPath = "";
|
||||
projectRoot = "";
|
||||
targets = (
|
||||
97C146ED1CF9000F007C117D /* Runner */,
|
||||
331C8080294A63A400263BE5 /* RunnerTests */,
|
||||
);
|
||||
};
|
||||
/* End PBXProject section */
|
||||
|
||||
/* Begin PBXResourcesBuildPhase section */
|
||||
331C807F294A63A400263BE5 /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EC1CF9000F007C117D /* Resources */ = {
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
|
|
@ -199,6 +283,45 @@
|
|||
/* End PBXResourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXShellScriptBuildPhase section */
|
||||
0830C6758DA3ECA81FB12386 /* [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-Runner-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;
|
||||
};
|
||||
1D165FDFB9D0D939B041966D /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
alwaysOutOfDate = 1;
|
||||
|
|
@ -230,7 +353,7 @@
|
|||
shellPath = /bin/sh;
|
||||
shellScript = "/bin/sh \"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh\" build";
|
||||
};
|
||||
A3B5CB395514F4BF9CDF304E /* [CP] Check Pods Manifest.lock */ = {
|
||||
EE82EC529EB6C0F1FA480659 /* [CP] Check Pods Manifest.lock */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
|
|
@ -245,61 +368,44 @@
|
|||
outputFileListPaths = (
|
||||
);
|
||||
outputPaths = (
|
||||
"$(DERIVED_FILE_DIR)/Pods-Runner-checkManifestLockResult.txt",
|
||||
"$(DERIVED_FILE_DIR)/Pods-RunnerTests-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;
|
||||
};
|
||||
C3C8545BDAC52D360D298A29 /* [CP] Embed Pods Frameworks */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Embed Pods Frameworks";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-frameworks.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
F46F66CC32F585BBF2FB675E /* [CP] Copy Pods Resources */ = {
|
||||
isa = PBXShellScriptBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
);
|
||||
inputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-input-files.xcfilelist",
|
||||
);
|
||||
name = "[CP] Copy Pods Resources";
|
||||
outputFileListPaths = (
|
||||
"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources-${CONFIGURATION}-output-files.xcfilelist",
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
shellPath = /bin/sh;
|
||||
shellScript = "\"${PODS_ROOT}/Target Support Files/Pods-Runner/Pods-Runner-resources.sh\"\n";
|
||||
showEnvVarsInLog = 0;
|
||||
};
|
||||
/* End PBXShellScriptBuildPhase section */
|
||||
|
||||
/* Begin PBXSourcesBuildPhase section */
|
||||
331C807D294A63A400263BE5 /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
331C808B294A63AB00263BE5 /* RunnerTests.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
97C146EA1CF9000F007C117D /* Sources */ = {
|
||||
isa = PBXSourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
74858FAF1ED2DC5600515810 /* AppDelegate.swift in Sources */,
|
||||
1498D2341E8E89220040F4C2 /* GeneratedPluginRegistrant.m in Sources */,
|
||||
7884E8682EC3CC0700C636F2 /* SceneDelegate.swift in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* End PBXSourcesBuildPhase section */
|
||||
|
||||
/* Begin PBXTargetDependency section */
|
||||
331C8086294A63A400263BE5 /* PBXTargetDependency */ = {
|
||||
isa = PBXTargetDependency;
|
||||
target = 97C146ED1CF9000F007C117D /* Runner */;
|
||||
targetProxy = 331C8085294A63A400263BE5 /* PBXContainerItemProxy */;
|
||||
};
|
||||
/* End PBXTargetDependency section */
|
||||
|
||||
/* Begin PBXVariantGroup section */
|
||||
97C146FA1CF9000F007C117D /* Main.storyboard */ = {
|
||||
isa = PBXVariantGroup;
|
||||
|
|
@ -324,6 +430,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = YES;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -353,6 +460,7 @@
|
|||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
|
@ -374,13 +482,10 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = P3ZD9TNSKZ;
|
||||
DEVELOPMENT_TEAM = PK66NJM372;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -395,10 +500,61 @@
|
|||
};
|
||||
name = Profile;
|
||||
};
|
||||
331C8088294A63A400263BE5 /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = B8B599FDB72E4713FB7B5A44 /* Pods-RunnerTests.debug.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG;
|
||||
SWIFT_OPTIMIZATION_LEVEL = "-Onone";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Debug;
|
||||
};
|
||||
331C8089294A63A400263BE5 /* Release */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = FE5E4162842555A83F8A7FD7 /* Pods-RunnerTests.release.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Release;
|
||||
};
|
||||
331C808A294A63A400263BE5 /* Profile */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 63516CF65A79A5DDDE64B0D1 /* Pods-RunnerTests.profile.xcconfig */;
|
||||
buildSettings = {
|
||||
BUNDLE_LOADER = "$(TEST_HOST)";
|
||||
CODE_SIGN_STYLE = Automatic;
|
||||
CURRENT_PROJECT_VERSION = 1;
|
||||
GENERATE_INFOPLIST_FILE = YES;
|
||||
MARKETING_VERSION = 1.0;
|
||||
PRODUCT_BUNDLE_IDENTIFIER = nexus.federated.nexus.RunnerTests;
|
||||
PRODUCT_NAME = "$(TARGET_NAME)";
|
||||
SWIFT_VERSION = 5.0;
|
||||
TEST_HOST = "$(BUILT_PRODUCTS_DIR)/Runner.app/$(BUNDLE_EXECUTABLE_FOLDER_PATH)/Runner";
|
||||
};
|
||||
name = Profile;
|
||||
};
|
||||
97C147031CF9000F007C117D /* Debug */ = {
|
||||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -428,6 +584,7 @@
|
|||
DEBUG_INFORMATION_FORMAT = dwarf;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_TESTABILITY = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_DYNAMIC_NO_PIC = NO;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
|
|
@ -454,6 +611,7 @@
|
|||
isa = XCBuildConfiguration;
|
||||
buildSettings = {
|
||||
ALWAYS_SEARCH_USER_PATHS = NO;
|
||||
ASSETCATALOG_COMPILER_GENERATE_SWIFT_ASSET_SYMBOL_EXTENSIONS = AppIcon;
|
||||
CLANG_ANALYZER_NONNULL = YES;
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
|
|
@ -483,6 +641,7 @@
|
|||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
ENABLE_NS_ASSERTIONS = NO;
|
||||
ENABLE_STRICT_OBJC_MSGSEND = YES;
|
||||
ENABLE_USER_SCRIPT_SANDBOXING = NO;
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_NO_COMMON_BLOCKS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
|
|
@ -506,13 +665,10 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 9740EEB21CF90195004384FC /* Debug.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = P3ZD9TNSKZ;
|
||||
DEVELOPMENT_TEAM = PK66NJM372;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -532,13 +688,10 @@
|
|||
isa = XCBuildConfiguration;
|
||||
baseConfigurationReference = 7AFA3C8E1D35360C0083082E /* Release.xcconfig */;
|
||||
buildSettings = {
|
||||
APPLICATION_EXTENSION_API_ONLY = NO;
|
||||
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon;
|
||||
ASSETCATALOG_COMPILER_INCLUDE_ALL_APPICON_ASSETS = AppIcon;
|
||||
BUILD_LIBRARY_FOR_DISTRIBUTION = NO;
|
||||
CLANG_ENABLE_MODULES = YES;
|
||||
CURRENT_PROJECT_VERSION = "$(FLUTTER_BUILD_NUMBER)";
|
||||
DEVELOPMENT_TEAM = P3ZD9TNSKZ;
|
||||
DEVELOPMENT_TEAM = PK66NJM372;
|
||||
ENABLE_BITCODE = NO;
|
||||
INFOPLIST_FILE = Runner/Info.plist;
|
||||
LD_RUNPATH_SEARCH_PATHS = (
|
||||
|
|
@ -556,6 +709,16 @@
|
|||
/* End XCBuildConfiguration section */
|
||||
|
||||
/* Begin XCConfigurationList section */
|
||||
331C8087294A63A400263BE5 /* Build configuration list for PBXNativeTarget "RunnerTests" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
331C8088294A63A400263BE5 /* Debug */,
|
||||
331C8089294A63A400263BE5 /* Release */,
|
||||
331C808A294A63A400263BE5 /* Profile */,
|
||||
);
|
||||
defaultConfigurationIsVisible = 0;
|
||||
defaultConfigurationName = Release;
|
||||
};
|
||||
97C146E91CF9000F007C117D /* Build configuration list for PBXProject "Runner" */ = {
|
||||
isa = XCConfigurationList;
|
||||
buildConfigurations = (
|
||||
|
|
@ -577,6 +740,20 @@
|
|||
defaultConfigurationName = Release;
|
||||
};
|
||||
/* End XCConfigurationList section */
|
||||
|
||||
/* Begin XCLocalSwiftPackageReference section */
|
||||
781AD8BC2B33823900A9FFBB /* XCLocalSwiftPackageReference "FlutterGeneratedPluginSwiftPackage" */ = {
|
||||
isa = XCLocalSwiftPackageReference;
|
||||
relativePath = Flutter/ephemeral/Packages/FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCLocalSwiftPackageReference section */
|
||||
|
||||
/* Begin XCSwiftPackageProductDependency section */
|
||||
78A3181F2AECB46A00862997 /* FlutterGeneratedPluginSwiftPackage */ = {
|
||||
isa = XCSwiftPackageProductDependency;
|
||||
productName = FlutterGeneratedPluginSwiftPackage;
|
||||
};
|
||||
/* End XCSwiftPackageProductDependency section */
|
||||
};
|
||||
rootObject = 97C146E61CF9000F007C117D /* Project object */;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -5,6 +5,24 @@
|
|||
<BuildAction
|
||||
parallelizeBuildables = "YES"
|
||||
buildImplicitDependencies = "YES">
|
||||
<PreActions>
|
||||
<ExecutionAction
|
||||
ActionType = "Xcode.IDEStandardExecutionActionsCore.ExecutionActionType.ShellScriptAction">
|
||||
<ActionContent
|
||||
title = "Run Prepare Flutter Framework Script"
|
||||
scriptText = "/bin/sh "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" prepare ">
|
||||
<EnvironmentBuildable>
|
||||
<BuildableReference
|
||||
BuildableIdentifier = "primary"
|
||||
BlueprintIdentifier = "97C146ED1CF9000F007C117D"
|
||||
BuildableName = "Runner.app"
|
||||
BlueprintName = "Runner"
|
||||
ReferencedContainer = "container:Runner.xcodeproj">
|
||||
</BuildableReference>
|
||||
</EnvironmentBuildable>
|
||||
</ActionContent>
|
||||
</ExecutionAction>
|
||||
</PreActions>
|
||||
<BuildActionEntries>
|
||||
<BuildActionEntry
|
||||
buildForTesting = "YES"
|
||||
|
|
|
|||
|
|
@ -1,13 +1,16 @@
|
|||
import UIKit
|
||||
import Flutter
|
||||
import UIKit
|
||||
|
||||
@main
|
||||
@objc class AppDelegate: FlutterAppDelegate {
|
||||
@objc class AppDelegate: FlutterAppDelegate, FlutterImplicitEngineDelegate {
|
||||
override func application(
|
||||
_ application: UIApplication,
|
||||
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
|
||||
) -> Bool {
|
||||
GeneratedPluginRegistrant.register(with: self)
|
||||
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
|
||||
}
|
||||
|
||||
func didInitializeImplicitFlutterEngine(_ engineBridge: FlutterImplicitEngineBridge) {
|
||||
GeneratedPluginRegistrant.register(with: engineBridge.pluginRegistry)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
Before Width: | Height: | Size: 176 KiB After Width: | Height: | Size: 78 KiB |
|
Before Width: | Height: | Size: 1.2 KiB After Width: | Height: | Size: 846 B |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 4.8 KiB After Width: | Height: | Size: 2.6 KiB |
|
Before Width: | Height: | Size: 2 KiB After Width: | Height: | Size: 1.2 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 7.3 KiB After Width: | Height: | Size: 3.6 KiB |
|
Before Width: | Height: | Size: 2.9 KiB After Width: | Height: | Size: 1.7 KiB |
|
Before Width: | Height: | Size: 6.6 KiB After Width: | Height: | Size: 4 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 3.9 KiB After Width: | Height: | Size: 2.2 KiB |
|
Before Width: | Height: | Size: 8.6 KiB After Width: | Height: | Size: 4.2 KiB |
|
Before Width: | Height: | Size: 4.6 KiB After Width: | Height: | Size: 2.4 KiB |
|
Before Width: | Height: | Size: 10 KiB After Width: | Height: | Size: 5 KiB |
|
Before Width: | Height: | Size: 11 KiB After Width: | Height: | Size: 5.3 KiB |
|
Before Width: | Height: | Size: 17 KiB After Width: | Height: | Size: 8.3 KiB |
|
Before Width: | Height: | Size: 5.9 KiB After Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 13 KiB After Width: | Height: | Size: 6.5 KiB |
|
Before Width: | Height: | Size: 6.2 KiB After Width: | Height: | Size: 3.8 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 6.9 KiB |
|
Before Width: | Height: | Size: 16 KiB After Width: | Height: | Size: 7.5 KiB |
|
|
@ -3,7 +3,7 @@
|
|||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||
<true/>
|
||||
<false/>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
|
|
@ -22,30 +22,40 @@
|
|||
<string>$(FLUTTER_BUILD_NAME)</string>
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleURLTypes</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>CFBundleURLSchemes</key>
|
||||
<array>
|
||||
<string>nexus.federated.nexus</string>
|
||||
</array>
|
||||
</dict>
|
||||
</array>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>$(FLUTTER_BUILD_NUMBER)</string>
|
||||
<key>LSSupportsOpeningDocumentsInPlace</key>
|
||||
<true/>
|
||||
<key>LSApplicationQueriesSchemes</key>
|
||||
<array>
|
||||
<string>file</string>
|
||||
<string>https</string>
|
||||
<string>http</string>
|
||||
<string>mailto</string>
|
||||
<string>tel</string>
|
||||
</array>
|
||||
<key>UIFileSharingEnabled</key>
|
||||
<true/>
|
||||
<key>ITSAppUsesNonExemptEncryption</key>
|
||||
<false/>
|
||||
<key>LSRequiresIPhoneOS</key>
|
||||
<true/>
|
||||
<key>NSCameraUsageDescription</key>
|
||||
<string>This app needs camera access to scan asset QR codes</string>
|
||||
<key>NSMicrophoneUsageDescription</key>
|
||||
<string>This app doesn't use your microphone.</string>
|
||||
<key>NSPhotoLibraryUsageDescription</key>
|
||||
<string>This app doesn't use your photo library.</string>
|
||||
<key>UIApplicationSceneManifest</key>
|
||||
<dict>
|
||||
<key>UIApplicationSupportsMultipleScenes</key>
|
||||
<false/>
|
||||
<key>UISceneConfigurations</key>
|
||||
<dict>
|
||||
<key>UIWindowSceneSessionRoleApplication</key>
|
||||
<array>
|
||||
<dict>
|
||||
<key>UISceneClassName</key>
|
||||
<string>UIWindowScene</string>
|
||||
<key>UISceneConfigurationName</key>
|
||||
<string>flutter</string>
|
||||
<key>UISceneDelegateClassName</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).SceneDelegate</string>
|
||||
<key>UISceneStoryboardFile</key>
|
||||
<string>Main</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>
|
||||
</dict>
|
||||
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||
<true/>
|
||||
<key>UILaunchStoryboardName</key>
|
||||
|
|
|
|||
6
ios/Runner/SceneDelegate.swift
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
import Flutter
|
||||
import UIKit
|
||||
|
||||
class SceneDelegate: FlutterSceneDelegate {
|
||||
|
||||
}
|
||||
12
ios/RunnerTests/RunnerTests.swift
Normal file
|
|
@ -0,0 +1,12 @@
|
|||
import Flutter
|
||||
import UIKit
|
||||
import XCTest
|
||||
|
||||
class RunnerTests: XCTestCase {
|
||||
|
||||
func testExample() {
|
||||
// If you add code to the Runner application, consider adding tests here.
|
||||
// See https://developer.apple.com/documentation/xctest for more information about using XCTest.
|
||||
}
|
||||
|
||||
}
|
||||
22
lib/controllers/account_data.dart
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
import "dart:convert";
|
||||
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/models/account_data.dart";
|
||||
|
||||
class AccountDataController extends Notifier<AccountData> {
|
||||
@override
|
||||
AccountData build() => .new();
|
||||
|
||||
void update(IMap<String, IMap<String, dynamic>> newAccountData) =>
|
||||
state = .fromJson({
|
||||
...json.decode(json.encode(state.toJson())),
|
||||
...newAccountData
|
||||
.map((key, value) => MapEntry(key, value["content"]))
|
||||
.unlock,
|
||||
});
|
||||
|
||||
static final provider = NotifierProvider<AccountDataController, AccountData>(
|
||||
AccountDataController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,16 +0,0 @@
|
|||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/models/account_data.dart";
|
||||
|
||||
class AccountDataController extends Notifier<IMap<String, AccountData>> {
|
||||
@override
|
||||
IMap<String, AccountData> build() => const IMap.empty();
|
||||
|
||||
void update(IMap<String, AccountData> newData) =>
|
||||
state = IMap({...state.unlock, ...newData.unlock});
|
||||
|
||||
static final provider =
|
||||
NotifierProvider<AccountDataController, IMap<String, AccountData>>(
|
||||
AccountDataController.new,
|
||||
);
|
||||
}
|
||||
38
lib/controllers/attachment.dart
Normal file
|
|
@ -0,0 +1,38 @@
|
|||
import "package:file_selector/file_selector.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/models/content/content.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
import "package:path/path.dart";
|
||||
|
||||
class AttachmentController extends Notifier<(String, MessageContent?)?> {
|
||||
final String roomId;
|
||||
AttachmentController(this.roomId);
|
||||
|
||||
@override
|
||||
Null build() => null;
|
||||
|
||||
Future<void> add(XFile file) async {
|
||||
final filename = basename(file.path);
|
||||
state = (filename, null);
|
||||
|
||||
final isEncrypted = ref.read(
|
||||
RoomsController.provider.select(
|
||||
(value) =>
|
||||
value[roomId]?.state[EventType.encryption.type]?.isNotEmpty == true,
|
||||
),
|
||||
);
|
||||
|
||||
final content = await ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.uploadMedia(.new(path: file.path, encrypt: isEncrypted));
|
||||
|
||||
state = (filename, content);
|
||||
}
|
||||
|
||||
static final provider = NotifierProvider.family
|
||||
.autoDispose<AttachmentController, (String, MessageContent?)?, String>(
|
||||
AttachmentController.new,
|
||||
);
|
||||
}
|
||||
30
lib/controllers/auth_url.dart
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/client_id.dart";
|
||||
import "package:nexus/models/oauth_auth_code_response.dart";
|
||||
import "package:nexus/models/requests/oauth/get_auth_url.dart";
|
||||
|
||||
class AuthUrlController extends AsyncNotifier<OAuthAuthCodeResponse> {
|
||||
final Uri homeserver;
|
||||
AuthUrlController(this.homeserver);
|
||||
|
||||
@override
|
||||
Future<OAuthAuthCodeResponse> build() async => ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.getAuthUrl(
|
||||
.new(
|
||||
homeserverUrl: homeserver,
|
||||
redirectUri: .new(scheme: "nexus.federated.nexus", path: "/"),
|
||||
responseMode: .query,
|
||||
scopes: .new([Scope.clientApi, Scope.device]),
|
||||
clientId: await ref.watch(
|
||||
ClientIdController.provider(homeserver).future,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
static final provider = AsyncNotifierProvider.family
|
||||
.autoDispose<AuthUrlController, OAuthAuthCodeResponse, Uri>(
|
||||
AuthUrlController.new,
|
||||
);
|
||||
}
|
||||
30
lib/controllers/author.dart
Normal file
|
|
@ -0,0 +1,30 @@
|
|||
import "dart:async";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/user.dart";
|
||||
import "package:nexus/models/content/membership.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
|
||||
class AuthorController extends AsyncNotifier<MembershipContent> {
|
||||
final Event event;
|
||||
AuthorController(this.event);
|
||||
|
||||
@override
|
||||
Future<MembershipContent> build() async {
|
||||
final member = await ref.watch(
|
||||
UserController.provider(
|
||||
.new(roomId: event.roomId, userId: event.sender),
|
||||
).future,
|
||||
);
|
||||
|
||||
return .new(
|
||||
status: member.status,
|
||||
avatarUrl: event.pmp?.avatarUrl ?? member.avatarUrl,
|
||||
displayName: event.pmp?.displayName ?? member.displayName,
|
||||
);
|
||||
}
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider.family<AuthorController, MembershipContent, Event>(
|
||||
AuthorController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
import "dart:async";
|
||||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/members_controller.dart";
|
||||
import "package:nexus/models/configs/author_config.dart";
|
||||
import "package:nexus/models/membership.dart";
|
||||
|
||||
class AuthorController extends AsyncNotifier<Membership> {
|
||||
final AuthorConfig config;
|
||||
AuthorController(this.config);
|
||||
|
||||
@override
|
||||
Future<Membership> build() async {
|
||||
var member = await ref.watch(
|
||||
MembersController.provider(config.room).selectAsync(
|
||||
(value) => value.firstWhereOrNull(
|
||||
(membership) => membership.userId == config.message.authorId,
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final pmp = config.message.metadata?["pmp"] == null
|
||||
? null
|
||||
: Membership.fromContent(
|
||||
IMap(config.message.metadata?["pmp"]),
|
||||
config.message.authorId,
|
||||
);
|
||||
|
||||
return Membership(
|
||||
avatarUrl: pmp?.avatarUrl ?? member?.avatarUrl,
|
||||
displayName:
|
||||
pmp?.displayName ??
|
||||
member?.displayName ??
|
||||
config.message.authorId.substring(1).split(":").first,
|
||||
userId: config.message.authorId,
|
||||
);
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider.family
|
||||
.autoDispose<AuthorController, Membership, AuthorConfig>(
|
||||
AuthorController.new,
|
||||
);
|
||||
}
|
||||
327
lib/controllers/client.dart
Normal file
|
|
@ -0,0 +1,327 @@
|
|||
import "dart:ffi";
|
||||
import "dart:io";
|
||||
import "dart:isolate";
|
||||
import "dart:math";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:ffi/ffi.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:nexus/controllers/account_data.dart";
|
||||
import "package:nexus/controllers/client_state.dart";
|
||||
import "package:nexus/controllers/init_complete.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/controllers/space_edges.dart";
|
||||
import "package:nexus/controllers/sync_status.dart";
|
||||
import "package:nexus/controllers/top_level_spaces.dart";
|
||||
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
||||
import "package:nexus/main.dart";
|
||||
import "package:nexus/models/content/message.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/oauth_auth_code_response.dart";
|
||||
import "package:nexus/models/open_graph_data.dart";
|
||||
import "package:nexus/models/paginate.dart";
|
||||
import "package:nexus/models/requests/download_media.dart";
|
||||
import "package:nexus/models/requests/get_event.dart";
|
||||
import "package:nexus/models/requests/get_related_events.dart";
|
||||
import "package:nexus/models/requests/get_room_state.dart";
|
||||
import "package:nexus/models/requests/join_room.dart";
|
||||
import "package:nexus/models/profile_response.dart";
|
||||
import "package:nexus/models/requests/oauth/exchange_token.dart";
|
||||
import "package:nexus/models/requests/oauth/get_auth_url.dart";
|
||||
import "package:nexus/models/requests/oauth/register_client.dart";
|
||||
import "package:nexus/models/requests/paginate.dart";
|
||||
import "package:nexus/models/requests/redact_event.dart";
|
||||
import "package:nexus/models/requests/report.dart";
|
||||
import "package:nexus/models/requests/send_event.dart";
|
||||
import "package:nexus/models/requests/send_message.dart";
|
||||
import "package:nexus/models/requests/set_account_data.dart";
|
||||
import "package:nexus/models/requests/set_membership.dart";
|
||||
import "package:nexus/models/requests/set_state.dart";
|
||||
import "package:nexus/models/requests/upload_media.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
import "package:nexus/models/room_summary.dart";
|
||||
import "package:nexus/models/spec_versions_response.dart";
|
||||
import "package:nexus/models/sync_data.dart";
|
||||
import "package:nexus/src/third_party/gomuks.g.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:path_provider/path_provider.dart";
|
||||
|
||||
class ClientController extends AsyncNotifier<int> {
|
||||
@override
|
||||
Future<int> build() async {
|
||||
final Pointer<Char> root;
|
||||
if (Platform.isAndroid || Platform.isIOS) {
|
||||
final dir = await getApplicationSupportDirectory();
|
||||
root = "${dir.path}/gomuks".toNativeUtf8().cast();
|
||||
} else {
|
||||
root = nullptr.cast();
|
||||
}
|
||||
|
||||
final handle = GomuksInit(root);
|
||||
|
||||
final callable =
|
||||
NativeCallable<
|
||||
Void Function(Pointer<Char>, Int64, GomuksOwnedBuffer)
|
||||
>.listener((
|
||||
Pointer<Char> command,
|
||||
int requestId,
|
||||
GomuksOwnedBuffer data,
|
||||
) {
|
||||
try {
|
||||
final muksEventType = command.cast<Utf8>().toDartString();
|
||||
debugPrint("Handling $muksEventType...");
|
||||
final decodedMuksEvent = data.toJson();
|
||||
|
||||
switch (muksEventType) {
|
||||
case "client_state":
|
||||
ref
|
||||
.watch(ClientStateController.provider.notifier)
|
||||
.set(.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_status":
|
||||
ref
|
||||
.watch(SyncStatusController.provider.notifier)
|
||||
.set(.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "init_complete":
|
||||
ref.watch(InitCompleteController.provider.notifier).complete();
|
||||
break;
|
||||
case "send_complete":
|
||||
final event = Event.fromJson(decodedMuksEvent["event"]);
|
||||
ref
|
||||
.watch(RoomsController.provider.notifier)
|
||||
.update(
|
||||
.new({
|
||||
event.roomId: .new(events: .new({event.rowId: event})),
|
||||
}),
|
||||
.new(),
|
||||
);
|
||||
|
||||
break;
|
||||
case "sync_complete":
|
||||
final syncData = SyncData.fromJson(decodedMuksEvent);
|
||||
final roomProvider = RoomsController.provider;
|
||||
final accountDataProvider = AccountDataController.provider;
|
||||
|
||||
if (syncData.clearState) {
|
||||
ref.invalidate(roomProvider);
|
||||
ref.invalidate(accountDataProvider);
|
||||
}
|
||||
|
||||
ref
|
||||
.watch(roomProvider.notifier)
|
||||
.update(syncData.rooms, syncData.leftRooms);
|
||||
ref
|
||||
.watch(accountDataProvider.notifier)
|
||||
.update(syncData.accountData);
|
||||
|
||||
if (syncData.topLevelSpaces != null) {
|
||||
ref
|
||||
.watch(TopLevelSpacesController.provider.notifier)
|
||||
.set(syncData.topLevelSpaces!);
|
||||
}
|
||||
|
||||
if (syncData.spaceEdges != null) {
|
||||
ref
|
||||
.watch(SpaceEdgesController.provider.notifier)
|
||||
.set(syncData.spaceEdges!);
|
||||
}
|
||||
|
||||
// ref
|
||||
// .watch(SyncStatusController.provider.notifier)
|
||||
// .set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
default:
|
||||
debugPrint("Unhandled event: $muksEventType");
|
||||
}
|
||||
debugPrint("Finished handling $muksEventType...");
|
||||
} catch (error, stackTrace) {
|
||||
if (kDebugMode) {
|
||||
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
||||
rethrow;
|
||||
} else {
|
||||
showError(error, stackTrace);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
ref.onDispose(() => GomuksDestroy(handle));
|
||||
ref.onDispose(callable.close);
|
||||
|
||||
final errorCode = GomuksStart(handle, callable.nativeFunction);
|
||||
|
||||
if (errorCode == 0) return handle;
|
||||
throw Exception("GomuksStart returned error code $errorCode");
|
||||
}
|
||||
|
||||
Future<dynamic> _sendCommand(
|
||||
String command, [
|
||||
Map<String, dynamic> data = const {},
|
||||
]) async {
|
||||
final bufferPointer = data.toGomuksBufferPtr();
|
||||
final handle = await future;
|
||||
final response = await Isolate.run(
|
||||
() => GomuksSubmitCommand(
|
||||
handle,
|
||||
command.toNativeUtf8().cast<Char>(),
|
||||
bufferPointer.ref,
|
||||
),
|
||||
);
|
||||
|
||||
calloc.free(bufferPointer);
|
||||
|
||||
final json = response.buf.toJson();
|
||||
if (response.command.cast<Utf8>().toDartString() == "error") {
|
||||
throw json;
|
||||
}
|
||||
|
||||
return json;
|
||||
}
|
||||
|
||||
Future<void> redactEvent(RedactEventRequest report) =>
|
||||
_sendCommand("redact_event", report.toJson());
|
||||
|
||||
Future<Event> sendMessage(SendMessageRequest request) async =>
|
||||
Event.fromJson(await _sendCommand("send_message", request.toJson()));
|
||||
|
||||
Future<Event> sendEvent(SendEventRequest request) async {
|
||||
final json = request.toJson();
|
||||
final content = request.content.toJson();
|
||||
|
||||
return Event.fromJson(
|
||||
await _sendCommand("send_event", {
|
||||
...json,
|
||||
"content": {
|
||||
...content,
|
||||
"m.relates_to": {
|
||||
...((content["m.relates_to"] as Map<String, dynamic>?) ?? {}),
|
||||
"event_id": request.relatesTo,
|
||||
"rel_type": request.relationType,
|
||||
},
|
||||
},
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
Future<String?> setState(SetStateRequest request) async =>
|
||||
await _sendCommand("set_state", request.toJson());
|
||||
|
||||
Future<String?> verify(String recoveryKey) async {
|
||||
try {
|
||||
await _sendCommand("verify", {"recovery_key": recoveryKey});
|
||||
return null;
|
||||
} catch (error) {
|
||||
return error.toString();
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> joinRoom(JoinRoomRequest request) async =>
|
||||
(await _sendCommand("join_room", request.toJson()))["room_id"];
|
||||
|
||||
Future<RoomSummary> getRoomSummary(JoinRoomRequest request) async =>
|
||||
.fromJson(await _sendCommand("get_room_summary", request.toJson()));
|
||||
|
||||
Future<void> leaveRoom(Room room) async {
|
||||
if (room.metadata == null) return;
|
||||
await _sendCommand("leave_room", {"room_id": room.metadata!.id});
|
||||
}
|
||||
|
||||
// (await _sendCommand("get_event_context", {
|
||||
// "room_id": request.roomId,
|
||||
// "event_id": r"$OqZT4NuTj0J1-771IOEEWRI4XdumRNu6ighlvO3K3gc",
|
||||
// }));
|
||||
|
||||
Future<IList<Event>> getRoomState(GetRoomStateRequest request) async {
|
||||
Future<List?> getState(GetRoomStateRequest request) async =>
|
||||
(await _sendCommand("get_room_state", request.toJson())) as List?;
|
||||
final response = await getState(request);
|
||||
|
||||
return .new(
|
||||
(response ?? await getState(request.copyWith(refetch: true)) ?? []).map(
|
||||
(event) => .fromJson(event),
|
||||
),
|
||||
);
|
||||
}
|
||||
|
||||
Future<IList<Event>?> getRelatedEvents(
|
||||
GetRelatedEventsRequest request,
|
||||
) async {
|
||||
final response =
|
||||
(await _sendCommand("get_related_events", request.toJson())) as List?;
|
||||
return .new(response?.map((event) => .fromJson(event)));
|
||||
}
|
||||
|
||||
Future<Event?> getEvent(GetEventRequest request) async {
|
||||
final json = await _sendCommand("get_event", request.toJson());
|
||||
return json == null ? null : .fromJson(json);
|
||||
}
|
||||
|
||||
Future<OpenGraphData> getUrlPreview(Uri url) async =>
|
||||
.fromJson(await _sendCommand("get_url_preview", {"url": url.toString()}));
|
||||
|
||||
Future<Paginate> paginate(PaginateRequest request) async =>
|
||||
.fromJson(await _sendCommand("paginate", request.toJson()));
|
||||
|
||||
Future<ProfileResponse> getProfile(String userId) async =>
|
||||
.fromJson(await _sendCommand("get_profile", {"user_id": userId}));
|
||||
|
||||
Future<void> reportEvent(ReportRequest request) =>
|
||||
_sendCommand("report_event", request.toJson());
|
||||
|
||||
Future<void> setMembership(SetMembershipRequest request) =>
|
||||
_sendCommand("set_membership", request.toJson());
|
||||
|
||||
Future<void> setAccountData(SetAccountDataRequest request) =>
|
||||
_sendCommand("set_account_data", request.toJson());
|
||||
|
||||
Future<MessageContent> uploadMedia(UploadMediaRequest request) async =>
|
||||
.fromJson(await _sendCommand("upload_media", request.toJson()));
|
||||
|
||||
Future<File> downloadMedia(DownloadMediaRequest request) async =>
|
||||
.new((await _sendCommand("download_media", request.toJson()))["path"]);
|
||||
|
||||
Future<void> logout() => _sendCommand("logout");
|
||||
|
||||
Future<void> markRead(Room room) async {
|
||||
final eventRowId = room.timeline[room.timeline.keys.reduce(max)];
|
||||
final event = eventRowId == null ? null : room.events[eventRowId];
|
||||
if (event == null || room.metadata == null) return;
|
||||
|
||||
await _sendCommand("mark_read", {
|
||||
"room_id": room.metadata!.id,
|
||||
"receipt_type": "m.read",
|
||||
"event_id": event.eventId,
|
||||
});
|
||||
}
|
||||
|
||||
Future<String> registerClient(OAuthRegisterClientRequest request) async =>
|
||||
(await _sendCommand(
|
||||
"oauth_register_client",
|
||||
request.toJson(),
|
||||
))["client_id"];
|
||||
|
||||
Future<OAuthAuthCodeResponse> getAuthUrl(OAuthGetAuthUrl request) async =>
|
||||
.fromJson(
|
||||
await _sendCommand("oauth_get_authorization_url", request.toJson()),
|
||||
);
|
||||
|
||||
Future<void> exchangeToken(OAuthExchangeTokenRequest request) async =>
|
||||
await _sendCommand("oauth_exchange_token", request.toJson());
|
||||
|
||||
Future<SpecVersionsResponse> getSpecVersions() async =>
|
||||
.fromJson(await _sendCommand("get_versions"));
|
||||
|
||||
Future<Uri?> discoverHomeserver(Uri homeserver) async {
|
||||
try {
|
||||
final response = await _sendCommand("discover_homeserver", {
|
||||
"user_id": "@fake-user:${homeserver.authority}",
|
||||
});
|
||||
return Uri.parse(response["m.homeserver"]?["base_url"]);
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<ClientController, int>(
|
||||
ClientController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -1,244 +0,0 @@
|
|||
import "dart:developer";
|
||||
import "dart:ffi";
|
||||
import "dart:isolate";
|
||||
import "package:collection/collection.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:ffi/ffi.dart";
|
||||
import "package:flutter/foundation.dart";
|
||||
import "package:nexus/controllers/account_data_controller.dart";
|
||||
import "package:nexus/controllers/client_state_controller.dart";
|
||||
import "package:nexus/controllers/init_complete_controller.dart";
|
||||
import "package:nexus/controllers/rooms_controller.dart";
|
||||
import "package:nexus/controllers/space_edges_controller.dart";
|
||||
import "package:nexus/controllers/sync_status_controller.dart";
|
||||
import "package:nexus/controllers/top_level_spaces_controller.dart";
|
||||
import "package:nexus/helpers/extensions/gomuks_buffer.dart";
|
||||
import "package:nexus/models/client_state.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/paginate.dart";
|
||||
import "package:nexus/models/requests/get_event_request.dart";
|
||||
import "package:nexus/models/requests/get_related_events_request.dart";
|
||||
import "package:nexus/models/requests/get_room_state_request.dart";
|
||||
import "package:nexus/models/requests/join_room_request.dart";
|
||||
import "package:nexus/models/requests/login_request.dart";
|
||||
import "package:nexus/models/profile.dart";
|
||||
import "package:nexus/models/requests/paginate_request.dart";
|
||||
import "package:nexus/models/requests/redact_event_request.dart";
|
||||
import "package:nexus/models/requests/report_request.dart";
|
||||
import "package:nexus/models/requests/send_message_request.dart";
|
||||
import "package:nexus/models/room.dart";
|
||||
import "package:nexus/models/sync_data.dart";
|
||||
import "package:nexus/models/sync_status.dart";
|
||||
import "package:nexus/src/third_party/gomuks.g.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class ClientController extends AsyncNotifier<int> {
|
||||
@override
|
||||
Future<int> build() async {
|
||||
final handle = await Isolate.run(GomuksInit);
|
||||
|
||||
final callable =
|
||||
NativeCallable<
|
||||
Void Function(Pointer<Char>, Int64, GomuksOwnedBuffer)
|
||||
>.listener((
|
||||
Pointer<Char> command,
|
||||
int requestId,
|
||||
GomuksOwnedBuffer data,
|
||||
) {
|
||||
try {
|
||||
final muksEventType = command.cast<Utf8>().toDartString();
|
||||
debugPrint("Handling $muksEventType...");
|
||||
final decodedMuksEvent = data.toJson();
|
||||
|
||||
switch (muksEventType) {
|
||||
case "client_state":
|
||||
ref
|
||||
.watch(ClientStateController.provider.notifier)
|
||||
.set(ClientState.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "sync_status":
|
||||
ref
|
||||
.watch(SyncStatusController.provider.notifier)
|
||||
.set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
case "init_complete":
|
||||
ref.watch(InitCompleteController.provider.notifier).complete();
|
||||
break;
|
||||
case "sync_complete":
|
||||
final syncData = SyncData.fromJson(decodedMuksEvent);
|
||||
final roomProvider = RoomsController.provider;
|
||||
final accountDataProvider = AccountDataController.provider;
|
||||
|
||||
if (syncData.clearState) {
|
||||
ref.invalidate(roomProvider);
|
||||
ref.invalidate(accountDataProvider);
|
||||
}
|
||||
|
||||
ref
|
||||
.watch(roomProvider.notifier)
|
||||
.update(syncData.rooms, syncData.leftRooms);
|
||||
ref
|
||||
.watch(accountDataProvider.notifier)
|
||||
.update(syncData.accountData);
|
||||
|
||||
if (syncData.topLevelSpaces != null) {
|
||||
ref
|
||||
.watch(TopLevelSpacesController.provider.notifier)
|
||||
.set(syncData.topLevelSpaces!);
|
||||
}
|
||||
|
||||
if (syncData.spaceEdges != null) {
|
||||
ref
|
||||
.watch(SpaceEdgesController.provider.notifier)
|
||||
.set(syncData.spaceEdges!);
|
||||
}
|
||||
|
||||
// ref
|
||||
// .watch(SyncStatusController.provider.notifier)
|
||||
// .set(SyncStatus.fromJson(decodedMuksEvent));
|
||||
break;
|
||||
default:
|
||||
debugPrint("Unhandled event: $muksEventType");
|
||||
}
|
||||
debugPrint("Finished handling $muksEventType...");
|
||||
} catch (error, stackTrace) {
|
||||
debugger();
|
||||
debugPrintStack(stackTrace: stackTrace, label: error.toString());
|
||||
}
|
||||
});
|
||||
|
||||
ref.onDispose(() => GomuksDestroy(handle));
|
||||
ref.onDispose(callable.close);
|
||||
|
||||
final errorCode = GomuksStart(handle, callable.nativeFunction);
|
||||
|
||||
if (errorCode == 0) return handle;
|
||||
throw Exception("GomuksStart returned error code $errorCode");
|
||||
}
|
||||
|
||||
Future<dynamic> _sendCommand(
|
||||
String command, [
|
||||
Map<String, dynamic> data = const {},
|
||||
]) async {
|
||||
final bufferPointer = data.toGomuksBufferPtr();
|
||||
final handle = await future;
|
||||
final response = await Isolate.run(
|
||||
() => GomuksSubmitCommand(
|
||||
handle,
|
||||
command.toNativeUtf8().cast<Char>(),
|
||||
bufferPointer.ref,
|
||||
),
|
||||
);
|
||||
|
||||
calloc.free(bufferPointer);
|
||||
|
||||
final json = response.buf.toJson();
|
||||
if (json is String) throw json;
|
||||
return json;
|
||||
}
|
||||
|
||||
Future<void> redactEvent(RedactEventRequest report) =>
|
||||
_sendCommand("redact_event", report.toJson());
|
||||
|
||||
Future<void> sendMessage(SendMessageRequest request) =>
|
||||
_sendCommand("send_message", request.toJson());
|
||||
|
||||
Future<bool> verify(String recoveryKey) async {
|
||||
try {
|
||||
await _sendCommand("verify", {"recovery_key": recoveryKey});
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String> joinRoom(JoinRoomRequest request) async {
|
||||
final response = await _sendCommand("join_room", request.toJson());
|
||||
return response["room_id"];
|
||||
}
|
||||
|
||||
Future<String?> getAccessToken() async {
|
||||
final response = await _sendCommand("get_account_info", {});
|
||||
return response?["access_token"];
|
||||
}
|
||||
|
||||
Future<void> leaveRoom(Room room) async {
|
||||
if (room.metadata == null) return;
|
||||
await _sendCommand("leave_room", {"room_id": room.metadata!.id});
|
||||
}
|
||||
|
||||
// (await _sendCommand("get_event_context", {
|
||||
// "room_id": request.roomId,
|
||||
// "event_id": r"$OqZT4NuTj0J1-771IOEEWRI4XdumRNu6ighlvO3K3gc",
|
||||
// }));
|
||||
|
||||
Future<IList<Event>> getRoomState(GetRoomStateRequest request) async {
|
||||
final response =
|
||||
(await _sendCommand("get_room_state", request.toJson())) as List;
|
||||
return response.map((event) => Event.fromJson(event)).toIList();
|
||||
}
|
||||
|
||||
Future<IList<Event>?> getRelatedEvents(
|
||||
GetRelatedEventsRequest request,
|
||||
) async {
|
||||
final response =
|
||||
(await _sendCommand("get_related_events", request.toJson())) as List?;
|
||||
return response?.map((event) => Event.fromJson(event)).toIList();
|
||||
}
|
||||
|
||||
Future<Event?> getEvent(GetEventRequest request) async {
|
||||
final event = request.room.events.firstWhereOrNull(
|
||||
(event) => event.eventId == request.eventId,
|
||||
);
|
||||
if (event != null) return event;
|
||||
|
||||
final json = await _sendCommand("get_event", request.toJson());
|
||||
return json == null ? null : Event.fromJson(json);
|
||||
}
|
||||
|
||||
Future<Paginate> paginate(PaginateRequest request) async =>
|
||||
Paginate.fromJson(await _sendCommand("paginate", request.toJson()));
|
||||
|
||||
Future<Profile> getProfile(String userId) async =>
|
||||
Profile.fromJson(await _sendCommand("get_profile", {"user_id": userId}));
|
||||
|
||||
Future<void> reportEvent(ReportRequest report) =>
|
||||
_sendCommand("report_event", report.toJson());
|
||||
|
||||
Future<void> markRead(Room room) async {
|
||||
final event = room.events.firstWhereOrNull(
|
||||
(event) => event.rowId == room.timeline.last.eventRowId,
|
||||
);
|
||||
if (event == null || room.metadata == null) return;
|
||||
|
||||
await _sendCommand("mark_read", {
|
||||
"room_id": room.metadata!.id,
|
||||
"receipt_type": "m.read",
|
||||
"event_id": event.eventId,
|
||||
});
|
||||
}
|
||||
|
||||
Future<bool> login(LoginRequest login) async {
|
||||
try {
|
||||
await _sendCommand("login", login.toJson());
|
||||
return true;
|
||||
} catch (error) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
Future<String?> discoverHomeserver(Uri homeserver) async {
|
||||
try {
|
||||
final response = await _sendCommand("discover_homeserver", {
|
||||
"user_id": "@fakeuser:${homeserver.host}",
|
||||
});
|
||||
return response["m.homeserver"]?["base_url"];
|
||||
} catch (error) {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<ClientController, int>(
|
||||
ClientController.new,
|
||||
);
|
||||
}
|
||||
33
lib/controllers/client_id.dart
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
|
||||
class ClientIdController extends AsyncNotifier<String> {
|
||||
final Uri homeserver;
|
||||
ClientIdController(this.homeserver);
|
||||
|
||||
@override
|
||||
Future<String> build() => ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.registerClient(
|
||||
.new(
|
||||
clientName: "Nexus",
|
||||
applicationType: .native,
|
||||
grantTypes: .new([.authorizationCode, .refreshToken]),
|
||||
responseTypes: .new([.code]),
|
||||
logoUri: Uri.https(
|
||||
"nexus.federated.nexus",
|
||||
"raw/branch/main/assets/mobile.svg",
|
||||
),
|
||||
homeserverUrl: homeserver,
|
||||
clientUri: Uri.https("nexus.federated.nexus"),
|
||||
redirectUris: .new([
|
||||
.new(scheme: "nexus.federated.nexus", path: "/"),
|
||||
]),
|
||||
),
|
||||
);
|
||||
|
||||
static final provider =
|
||||
AsyncNotifierProvider.family<ClientIdController, String, Uri>(
|
||||
ClientIdController.new,
|
||||
);
|
||||
}
|
||||
|
|
@ -5,9 +5,7 @@ class ClientStateController extends Notifier<ClientState?> {
|
|||
@override
|
||||
Null build() => null;
|
||||
|
||||
void set(ClientState newState) {
|
||||
state = newState;
|
||||
}
|
||||
void set(ClientState newState) => state = newState;
|
||||
|
||||
static final provider = NotifierProvider<ClientStateController, ClientState?>(
|
||||
ClientStateController.new,
|
||||
|
|
@ -1,14 +0,0 @@
|
|||
import "package:cross_cache/cross_cache.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
|
||||
class CrossCacheController extends Notifier<CrossCache> {
|
||||
static const String spaceKey = "space";
|
||||
static const String roomKey = "room";
|
||||
|
||||
@override
|
||||
CrossCache build() => CrossCache();
|
||||
|
||||
static final provider = NotifierProvider<CrossCacheController, CrossCache>(
|
||||
CrossCacheController.new,
|
||||
);
|
||||
}
|
||||
84
lib/controllers/emoji.dart
Normal file
|
|
@ -0,0 +1,84 @@
|
|||
import "dart:convert";
|
||||
import "package:emoji_text_field/models/emoji_category.dart";
|
||||
import "package:fast_immutable_collections/fast_immutable_collections.dart";
|
||||
import "package:flutter/material.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:http/http.dart";
|
||||
import "package:nexus/models/emoji.dart";
|
||||
|
||||
typedef EmojiTuple = (IMap<String, EmojiCategory>, IMap<String, List<String>>);
|
||||
|
||||
class EmojiController extends AsyncNotifier<EmojiTuple> {
|
||||
@override
|
||||
Future<EmojiTuple> build() async {
|
||||
final response = await get(
|
||||
.https("github.com", "github/gemoji/raw/refs/heads/master/db/emoji.json"),
|
||||
);
|
||||
|
||||
if (response.statusCode != 200) {
|
||||
throw Exception("Failed to load emoji data");
|
||||
}
|
||||
|
||||
final data = json.decode(response.body);
|
||||
|
||||
final entries = (data as List)
|
||||
.cast<Map<String, dynamic>>()
|
||||
.map(Emoji.fromJson)
|
||||
.toIList();
|
||||
|
||||
final categoryMap = entries.fold<IMap<String, IList<String>>>(
|
||||
.new(),
|
||||
(acc, entry) => acc.update(
|
||||
entry.category,
|
||||
(list) => list.add(entry.emoji),
|
||||
ifAbsent: () => .new([entry.emoji]),
|
||||
),
|
||||
);
|
||||
|
||||
final keywordMap = entries.fold<IMap<String, IList<String>>>(
|
||||
.new(),
|
||||
(acc, entry) => acc.add(
|
||||
entry.emoji,
|
||||
.new([...entry.tags, ...entry.aliases, entry.description]),
|
||||
),
|
||||
);
|
||||
|
||||
final customCategories = IMap.fromEntries(
|
||||
categoryMap.entries.map(
|
||||
(entry) => MapEntry(
|
||||
entry.key,
|
||||
EmojiCategory(
|
||||
name: entry.key,
|
||||
icon: switch (entry.key) {
|
||||
"Smileys & Emotion" => Icons.emoji_emotions,
|
||||
"People & Body" => Icons.emoji_people,
|
||||
"Animals & Nature" => Icons.emoji_nature,
|
||||
"Food & Drink" => Icons.emoji_food_beverage,
|
||||
"Travel & Places" => Icons.travel_explore,
|
||||
"Activities" => Icons.sports_soccer,
|
||||
"Objects" => Icons.emoji_objects,
|
||||
"Symbols" => Icons.emoji_symbols,
|
||||
"Flags" => Icons.emoji_flags,
|
||||
_ => Icons.category,
|
||||
},
|
||||
emojis: entry.value.toList(growable: false),
|
||||
),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
final customKeywords = IMap(
|
||||
.fromEntries(
|
||||
keywordMap.entries.map(
|
||||
(e) => .new(e.key, e.value.toList(growable: false)),
|
||||
),
|
||||
),
|
||||
);
|
||||
|
||||
return (customCategories, customKeywords);
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider<EmojiController, EmojiTuple>(
|
||||
EmojiController.new,
|
||||
);
|
||||
}
|
||||
32
lib/controllers/event.dart
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
import "package:collection/collection.dart";
|
||||
import "package:flutter_riverpod/flutter_riverpod.dart";
|
||||
import "package:nexus/controllers/client.dart";
|
||||
import "package:nexus/controllers/rooms.dart";
|
||||
import "package:nexus/models/event.dart";
|
||||
import "package:nexus/models/requests/get_event.dart";
|
||||
|
||||
class EventController extends AsyncNotifier<Event?> {
|
||||
final GetEventRequest request;
|
||||
EventController(this.request);
|
||||
|
||||
@override
|
||||
Future<Event?> build() async {
|
||||
final room = ref.watch(
|
||||
RoomsController.provider.select((value) => value[request.roomId]),
|
||||
);
|
||||
final event = room?.events.values.firstWhereOrNull(
|
||||
(event) => event.eventId == request.eventId,
|
||||
);
|
||||
|
||||
return event ??
|
||||
await ref
|
||||
.watch(ClientController.provider.notifier)
|
||||
.getEvent(request)
|
||||
.onError((_, _) => null);
|
||||
}
|
||||
|
||||
static final provider = AsyncNotifierProvider.family
|
||||
.autoDispose<EventController, Event?, GetEventRequest>(
|
||||
EventController.new,
|
||||
);
|
||||
}
|
||||