Compare commits
459 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
b4fcb5b0d9 | ||
|
|
1911004d05 | ||
|
|
5d67564445 | ||
|
|
be04c5a46e | ||
|
|
bd7a4c9dfb | ||
|
|
10ee57722e | ||
|
|
ff5f7ab50e | ||
|
|
277885a61e | ||
|
|
6633ebc376 | ||
|
|
b2d9986cd3 | ||
|
|
a0b9bb277f | ||
|
|
d381705cdd | ||
| 3820d4264a | |||
|
|
cf4e2d3fad | ||
|
|
002dc87577 | ||
|
|
922e7ad0ff | ||
|
|
5d7be8a672 | ||
|
|
431b357cfa | ||
|
|
2938acf152 | ||
|
|
4127f70e4d | ||
|
|
c07221cc12 | ||
|
|
33b2f95e3f | ||
|
|
2a5cd9b218 | ||
|
|
a15fed034d | ||
|
|
b9641ac021 | ||
|
|
2145bd8846 | ||
|
|
672b97b310 | ||
|
|
974da6ec90 | ||
|
|
f19bbcd010 | ||
|
|
a1468c92c8 | ||
|
|
6dd125a087 | ||
|
|
842ecc4235 | ||
|
|
db66793d28 | ||
|
|
324da027e9 | ||
|
|
f2f45e53a8 | ||
|
|
cacab45fe3 | ||
|
|
908d428220 | ||
|
|
8a6d726b8c | ||
|
|
40275d3d14 | ||
|
|
5039f1ba3b | ||
|
|
299aac134d | ||
|
|
044171c002 | ||
|
|
ec9155d8f0 | ||
|
|
221fe3edcc | ||
|
|
e166f17cae | ||
|
|
640fe0d476 | ||
|
|
3942de3222 | ||
|
|
b00111381a | ||
|
|
715dca561f | ||
|
|
44d7f61788 | ||
|
|
518739e29f | ||
|
|
06e6e9c5b1 | ||
|
|
17cfff153b | ||
|
|
9f224b9839 | ||
|
|
56e1bb6bfd | ||
|
|
6529ce0d0f | ||
|
|
81c7f7decd | ||
|
|
85868cc0bd | ||
|
|
1d0c842bad | ||
|
|
02bcc98037 | ||
|
|
1a1c166ab0 | ||
|
|
692d6042c5 | ||
|
|
fa2ed930eb | ||
|
|
9785b0023c | ||
|
|
313c94a4f1 | ||
|
|
2bb0dce7a1 | ||
|
|
b1785d4b8a | ||
|
|
3f15fa365f | ||
|
|
a56ebb245e | ||
|
|
d300cdb58f | ||
|
|
d88a1cd2d6 | ||
|
|
3070b38d2e | ||
|
|
38db3b35aa | ||
|
|
c4447adf8c | ||
|
|
0b91d3cecc | ||
|
|
3b3d20f250 | ||
|
|
0376e7f4b8 | ||
|
|
77f43fbde0 | ||
|
|
e203508c42 | ||
|
|
8b6745763a | ||
|
|
8c4b2ade88 | ||
|
|
4e5f2ff05f | ||
|
|
fd1b62fc8d | ||
|
|
f53d17eab7 | ||
|
|
c3b3f762eb | ||
|
|
d288603c07 | ||
|
|
e61682ef46 | ||
|
|
3b228bb58b | ||
|
|
b62c41ce57 | ||
|
|
a4397e9cec | ||
|
|
981d69706c | ||
|
|
0a4683d8a6 | ||
|
|
43f6284ada | ||
|
|
8cf6297560 | ||
|
|
1f42d7dff0 | ||
|
|
abbf18e1dc | ||
|
|
102f3bba8e | ||
|
|
8faba7bdf2 | ||
|
|
d41d21f8e1 | ||
|
|
298cd6245c | ||
|
|
8bd88c4845 | ||
|
|
e3bf76d8e2 | ||
|
|
3445d5be21 | ||
|
|
a838ba3000 | ||
|
|
15b655413d | ||
|
|
2418c61498 | ||
|
|
dfacbf9e32 | ||
|
|
85f5b69d6e | ||
|
|
08797da53d | ||
|
|
d3bd2c3a08 | ||
|
|
1086c0e5cd | ||
|
|
60df0761a5 | ||
|
|
650d878649 | ||
|
|
06f399c76d | ||
|
|
7c5b60474f | ||
|
|
d81f92f2e2 | ||
|
|
1a8038e51d | ||
|
|
54a6ce8391 | ||
|
|
b1c38d766f | ||
|
|
f44e24aec1 | ||
|
|
325dcf901a | ||
|
|
77e1da8318 | ||
|
|
b0a58d8524 | ||
|
|
623c3bfc2e | ||
|
|
5cd6cf79a2 | ||
|
|
e1d54fa992 | ||
|
|
b1c481c4d1 | ||
|
|
64821e4ec5 | ||
|
|
88585fb192 | ||
|
|
25f5d5f4fd | ||
|
|
d0d33ce2c8 | ||
|
|
32d8791fe9 | ||
|
|
e76f42a706 | ||
|
|
32f4e471cf | ||
|
|
dd86a0fb00 | ||
|
|
a603597b20 | ||
|
|
23b14e8730 | ||
|
|
c4a7650e39 | ||
|
|
c4bb5fa523 | ||
|
|
fa684d265d | ||
|
|
3eeaad17f0 | ||
|
|
8d2697ffc6 | ||
|
|
150ba308e9 | ||
|
|
ce18cfdf2a | ||
|
|
17bccc0dea | ||
|
|
f8b7a6fef5 | ||
|
|
a68f7e8936 | ||
|
|
74ef50af49 | ||
|
|
70698cf4ec | ||
|
|
9bed679568 | ||
|
|
99595caee5 | ||
|
|
b39018e454 | ||
|
|
08bed5d668 | ||
|
|
b78868397c | ||
|
|
cbb4553fc0 | ||
|
|
3ddd661fb5 | ||
|
|
4e8f2c3040 | ||
|
|
52ee4b923a | ||
|
|
166fcce8ba | ||
|
|
92072904e6 | ||
|
|
9ace2fe07b | ||
|
|
8913b42803 | ||
|
|
253a3afbdd | ||
|
|
af2907b946 | ||
|
|
02a0c4760a | ||
|
|
e9899fce8e | ||
|
|
63a9f9ca90 | ||
|
|
b5364e1619 | ||
|
|
742dcb8f41 | ||
|
|
dda90c85a4 | ||
|
|
16455da39f | ||
|
|
b69e3969cb | ||
|
|
14c904b214 | ||
|
|
0d12c31393 | ||
|
|
d6b3482ce2 | ||
|
|
f4eb6318cc | ||
|
|
c8b421d43e | ||
|
|
87280a0e21 | ||
|
|
96d3f83933 | ||
|
|
bb3eddb021 | ||
|
|
59c403603b | ||
|
|
fd7d732762 | ||
|
|
fc8fe60613 | ||
|
|
2acf49a12b | ||
|
|
2f6799470c | ||
|
|
507cd1f17e | ||
|
|
f1a8716832 | ||
|
|
f99aad5a18 | ||
|
|
caa816beec | ||
|
|
605ba186d6 | ||
|
|
8fa14659be | ||
|
|
e1fe8c2ed5 | ||
|
|
2e73051b81 | ||
|
|
1a61ed5d85 | ||
|
|
9ad8550449 | ||
|
|
8422c2bf3c | ||
|
|
bf2e6b2787 | ||
|
|
9e01d51520 | ||
|
|
07b92bf876 | ||
|
|
4863c4a8f3 | ||
|
|
9def8de5a8 | ||
|
|
f08968800e | ||
|
|
d8dee5905d | ||
|
|
c2768ae40a | ||
|
|
a4a852ede8 | ||
|
|
ede1e289ce | ||
|
|
d211dd4aeb | ||
|
|
20c1dbd00a | ||
|
|
fa02384808 | ||
|
|
dd4f2fcc35 | ||
|
|
1b2708f4b0 | ||
|
|
7c9e2bfe3c | ||
|
|
13365488b4 | ||
|
|
02f564f7ed | ||
|
|
0222e6ecd5 | ||
|
|
df91290a18 | ||
|
|
57618417a1 | ||
|
|
5e3c47a433 | ||
|
|
b30622c1b9 | ||
|
|
eb651212e6 | ||
|
|
78aa686699 | ||
|
|
156217c3ae | ||
|
|
644ef388de | ||
|
|
71eac7078e | ||
|
|
511dd41d30 | ||
|
|
f24b3ee09b | ||
|
|
3b6321383e | ||
|
|
8888fd5884 | ||
|
|
0accfe4a26 | ||
|
|
535081b483 | ||
|
|
0f10dfaf91 | ||
|
|
f0ac88c9ee | ||
|
|
f4d13e86b6 | ||
|
|
303ccbe965 | ||
|
|
ade164d824 | ||
|
|
e40c86c7e6 | ||
|
|
a87946a34b | ||
|
|
863c5f1c13 | ||
|
|
6d21b54c62 | ||
|
|
c984a272b3 | ||
|
|
6cf0903af3 | ||
|
|
16a533cf40 | ||
|
|
3e8d14a53f | ||
|
|
1925578a86 | ||
|
|
fc62ff3eaa | ||
|
|
15dbe4433d | ||
|
|
a8d6dadf84 | ||
|
|
ee2b55ca78 | ||
|
|
090b026b92 | ||
|
|
e461cb1f53 | ||
|
|
5212d7ce4d | ||
|
|
ed9e58d0bf | ||
|
|
2b2c230fcf | ||
|
|
ecf5adcdea | ||
|
|
6851d34d35 | ||
|
|
006f2f527f | ||
|
|
1cb20c9ec5 | ||
|
|
ec49c5a541 | ||
|
|
7bbd898131 | ||
|
|
031da77da6 | ||
|
|
bfd76fdb79 | ||
|
|
0c28169043 | ||
|
|
fc1b49cf69 | ||
|
|
2b701cf56c | ||
|
|
8b386142cf | ||
|
|
cd7e27a6e0 | ||
|
|
9ab3332824 | ||
|
|
a60e1435c2 | ||
|
|
d56ca697ea | ||
|
|
9eaaef1048 | ||
|
|
a95cd85eb0 | ||
|
|
32f347ee6f | ||
|
|
d9645480ac | ||
|
|
73174003a9 | ||
|
|
3c17d812b3 | ||
|
|
e08f601bfd | ||
|
|
799bec5ad9 | ||
|
|
a602dc08d5 | ||
|
|
a48e42dfcf | ||
|
|
9384ef0503 | ||
|
|
d8d9df4e50 | ||
|
|
db2c768029 | ||
|
|
3353eef728 | ||
|
|
fba6f60500 | ||
|
|
10fcf2bac4 | ||
|
|
1cbfb592e9 | ||
|
|
dfc933115f | ||
|
|
2d0e7a491e | ||
|
|
e49408e5b0 | ||
|
|
69e0c48c8e | ||
|
|
4345ab9772 | ||
|
|
a76ea48d84 | ||
|
|
78a5206ba7 | ||
|
|
ac11341677 | ||
|
|
446fa75a90 | ||
|
|
d52bba3523 | ||
|
|
55c8475eba | ||
|
|
80b5a2b3d4 | ||
|
|
da91c2bd9f | ||
|
|
116b4ca361 | ||
|
|
5fc4230f9b | ||
|
|
cf88eb1fd7 | ||
|
|
cef5fbe3c8 | ||
|
|
2ccc30879b | ||
|
|
c670dc2700 | ||
|
|
d3240fd261 | ||
| 9cfffdfa66 | |||
|
|
564d1180ed | ||
|
|
ca03042ff8 | ||
|
|
50dc19b0de | ||
|
|
72767f0716 | ||
|
|
59d3793060 | ||
|
|
a090346046 | ||
|
|
ede5fdc348 | ||
|
|
90482009fc | ||
|
|
4c91ea6002 | ||
|
|
92fa8e1ca5 | ||
|
|
3442e44a07 | ||
|
|
2cab1fb03b | ||
|
|
13a3321bab | ||
|
|
0f69a1fefb | ||
|
|
ab5aea4caf | ||
|
|
8eba2b2a1f | ||
|
|
44ea0a9da5 | ||
|
|
538715843b | ||
|
|
0c07b2967a | ||
|
|
0262d776d5 | ||
|
|
9bad93c2df | ||
|
|
5c10e96a7b | ||
|
|
a309cb78ac | ||
|
|
918acb9beb | ||
|
|
ecd549cd9e | ||
|
|
bd41fa3873 | ||
|
|
b493f18e54 | ||
|
|
215e78f3d5 | ||
|
|
ad9e34a49e | ||
|
|
8503bbd33c | ||
|
|
426ca2480f | ||
|
|
1d1710302a | ||
|
|
972df73dd9 | ||
|
|
ce889e2c23 | ||
|
|
1eca7c9b07 | ||
|
|
85d3a11030 | ||
|
|
bf084f1ccc | ||
|
|
4afb9a4790 | ||
|
|
ddb7cc841b | ||
|
|
a1f60b7ff9 | ||
|
|
8632154832 | ||
|
|
1f71227221 | ||
|
|
3d9e94f08d | ||
|
|
b76f270e24 | ||
|
|
8f9e1a9142 | ||
|
|
fbb68686ea | ||
|
|
9eee50dbae | ||
|
|
3be35991b5 | ||
|
|
1aa0ea2cea | ||
|
|
a7dd62c721 | ||
|
|
1542a4b66c | ||
|
|
d39bcbafde | ||
|
|
8513d74cc1 | ||
|
|
22abd54176 | ||
|
|
ba885ca69e | ||
|
|
754b919531 | ||
|
|
8fd2d3918c | ||
|
|
d000f6e5a7 | ||
|
|
66858cdf12 | ||
|
|
4fb1a76060 | ||
|
|
de23cb0f5b | ||
|
|
cf7053f338 | ||
|
|
20e26b3747 | ||
|
|
ed075a35b6 | ||
|
|
6b3252b6ad | ||
|
|
5e5132c290 | ||
|
|
b4df8c129d | ||
|
|
37bf943ac7 | ||
|
|
264f36ea59 | ||
|
|
b894a4542a | ||
|
|
6e9e3d05d2 | ||
|
|
d0b32e44ce | ||
|
|
caa3823c26 | ||
|
|
df33df35da | ||
|
|
63abbf403a | ||
|
|
6ff4f480ac | ||
|
|
fd152baa28 | ||
|
|
09a74bf3ee | ||
|
|
5df709e12b | ||
|
|
cba5fa2daf | ||
|
|
cab78f3571 | ||
|
|
4cd501d00c | ||
|
|
edfd8f36ab | ||
|
|
7635104505 | ||
|
|
835d97f439 | ||
|
|
c9f4904d99 | ||
|
|
bd5a6e5578 | ||
|
|
29ec1735e9 | ||
|
|
7436cb4aa8 | ||
|
|
ee3351f643 | ||
|
|
fff3dc9946 | ||
|
|
1e1e591d27 | ||
|
|
abb99df271 | ||
|
|
6616314d77 | ||
|
|
3cb7842a7b | ||
|
|
77aca413fb | ||
|
|
04f34a4301 | ||
|
|
d3e3252de8 | ||
|
|
ca203608fa | ||
|
|
e9d02336e1 | ||
|
|
b3ad9a3a70 | ||
|
|
d2f472e86c | ||
|
|
338331d6e1 | ||
|
|
b65357576c | ||
|
|
99b0ee194c | ||
|
|
d930b569fc | ||
|
|
7da70ebeba | ||
|
|
54303ef635 | ||
|
|
05285b46d8 | ||
|
|
220dda715a | ||
|
|
a702a12c71 | ||
|
|
17f8eda6e4 | ||
|
|
139d1f01ca | ||
|
|
7b3cfe875f | ||
|
|
3b455d7801 | ||
|
|
ed68fc55fc | ||
|
|
108c620326 | ||
|
|
accd4b9a23 | ||
|
|
0a4f7c9d26 | ||
|
|
2512630172 | ||
|
|
30b17beaa7 | ||
|
|
e368227780 | ||
|
|
f9e4b9356a | ||
|
|
b24a7d9510 | ||
|
|
6084d36ed2 | ||
|
|
781a02cea7 | ||
|
|
fbb9f40f01 | ||
|
|
c19946c184 | ||
|
|
2ba6e15e59 | ||
|
|
0052b6d42f | ||
|
|
94b19cf6a6 | ||
|
|
b1699cfa16 | ||
|
|
c7dcceb7dd | ||
|
|
496bb0dbd4 | ||
|
|
1294479974 | ||
|
|
ca7bf8bd0d | ||
|
|
8f89d539d0 | ||
|
|
7cdeb98671 | ||
|
|
bb74754851 | ||
|
|
4680a1c507 | ||
|
|
51a5e7f9cc | ||
|
|
c4f601f651 | ||
|
|
f6c2fa8588 | ||
|
|
576d46eb4c | ||
|
|
b21ab55451 | ||
|
|
56b3297610 | ||
|
|
43b408fe5e | ||
|
|
12cc876b83 | ||
|
|
1d53fccfe6 | ||
|
|
857eea428e | ||
|
|
715e98cae2 | ||
|
|
bb9410accb |
3
.gitignore
vendored
@ -10,7 +10,6 @@
|
|||||||
.buildlog/
|
.buildlog/
|
||||||
.history
|
.history
|
||||||
.svn/
|
.svn/
|
||||||
lib/generated_plugin_registrant.dart
|
|
||||||
prime
|
prime
|
||||||
|
|
||||||
# libolm package
|
# libolm package
|
||||||
@ -38,7 +37,6 @@ prime
|
|||||||
/build/
|
/build/
|
||||||
|
|
||||||
# Web related
|
# Web related
|
||||||
lib/generated_plugin_registrant.dart
|
|
||||||
docs/build/
|
docs/build/
|
||||||
docs/.jekyll-cache/
|
docs/.jekyll-cache/
|
||||||
docs/_site/
|
docs/_site/
|
||||||
@ -62,3 +60,4 @@ ios/Podfile.lock
|
|||||||
/linux/out
|
/linux/out
|
||||||
/macos/out
|
/macos/out
|
||||||
.vs
|
.vs
|
||||||
|
olm
|
||||||
|
|||||||
172
.gitlab-ci.yml
@ -1,7 +1,7 @@
|
|||||||
variables:
|
variables:
|
||||||
FLUTTER_VERSION: 3.3.9
|
FLUTTER_VERSION: 3.10.0
|
||||||
|
|
||||||
image: cirrusci/flutter:${FLUTTER_VERSION}
|
image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
|
||||||
|
|
||||||
.shared_windows_runners:
|
.shared_windows_runners:
|
||||||
tags:
|
tags:
|
||||||
@ -16,20 +16,22 @@ stages:
|
|||||||
|
|
||||||
code_analyze:
|
code_analyze:
|
||||||
stage: test
|
stage: test
|
||||||
script: [./scripts/code_analyze.sh]
|
script:
|
||||||
|
- flutter pub get
|
||||||
|
- dart run import_sorter:main --no-comments --exit-if-changed
|
||||||
|
- dart format lib/ test/ --set-exit-if-changed
|
||||||
|
- flutter analyze
|
||||||
|
- git apply ./scripts/enable-android-google-services.patch
|
||||||
|
- flutter pub get
|
||||||
|
- flutter analyze
|
||||||
|
- flutter pub run dart_code_metrics:metrics lib -r gitlab > code-quality-report.json || true
|
||||||
artifacts:
|
artifacts:
|
||||||
reports:
|
reports:
|
||||||
codequality: code-quality-report.json
|
codequality: code-quality-report.json
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- famedly
|
|
||||||
|
|
||||||
widget_test:
|
widget_test:
|
||||||
stage: test
|
stage: test
|
||||||
script: [flutter test]
|
script: [flutter test]
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- famedly
|
|
||||||
|
|
||||||
# the basic integration test configuration testing FLOSS builds on Synapse
|
# the basic integration test configuration testing FLOSS builds on Synapse
|
||||||
.integration_test:
|
.integration_test:
|
||||||
@ -49,15 +51,13 @@ widget_test:
|
|||||||
FF_NETWORK_PER_BUILD: "true"
|
FF_NETWORK_PER_BUILD: "true"
|
||||||
# Tell docker CLI how to talk to Docker daemon.
|
# Tell docker CLI how to talk to Docker daemon.
|
||||||
DOCKER_HOST: tcp://docker:2375/
|
DOCKER_HOST: tcp://docker:2375/
|
||||||
# Use the overlayfs driver for improved performance.
|
# Use the btrfs driver for improved performance.
|
||||||
DOCKER_DRIVER: overlay2
|
DOCKER_DRIVER: btrfs
|
||||||
# Disable TLS since we're running inside local network.
|
# Disable TLS since we're running inside local network.
|
||||||
DOCKER_TLS_CERTDIR: ""
|
DOCKER_TLS_CERTDIR: ""
|
||||||
HOMESERVER: "docker"
|
HOMESERVER: docker
|
||||||
before_script:
|
before_script:
|
||||||
# start AVD and keep running in background
|
- scripts/integration-prepare-host.sh
|
||||||
- scripts/integration-start-avd.sh &
|
|
||||||
- scripts/integration-prepare-alpine.sh
|
|
||||||
# create test user environment variables
|
# create test user environment variables
|
||||||
- source scripts/integration-create-environment-variables.sh
|
- source scripts/integration-create-environment-variables.sh
|
||||||
# create Synapse instance
|
# create Synapse instance
|
||||||
@ -65,31 +65,57 @@ widget_test:
|
|||||||
# properly set the homeserver IP and create test users
|
# properly set the homeserver IP and create test users
|
||||||
- scripts/integration-prepare-homeserver.sh
|
- scripts/integration-prepare-homeserver.sh
|
||||||
script:
|
script:
|
||||||
|
# start AVD and keep running in background
|
||||||
|
- scripts/integration-start-avd.sh &
|
||||||
- flutter pub get
|
- flutter pub get
|
||||||
- flutter test integration_test
|
- scrcpy --no-display --record video.mkv &
|
||||||
timeout: 20m
|
- flutter test integration_test --dart-define=HOMESERVER=$HOMESERVER --dart-define=USER1_NAME=$USER1_NAME --dart-define=USER2_NAME=$USER2_NAME --dart-define=USER1_PW=$USER1_PW --dart-define=USER2_PW=$USER2_PW || ( sleep 10 && exit 1 )
|
||||||
|
after_script:
|
||||||
|
- ffmpeg -i video.mkv -vf scale=iw/2:-2 -crf 40 -b:v 2000k -preset fast video.mp4 || true
|
||||||
|
timeout: 30m
|
||||||
|
retry: 2
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
|
artifacts:
|
||||||
|
when: always
|
||||||
|
paths:
|
||||||
|
- video.mp4
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
|
|
||||||
|
|
||||||
# integration tests for Linux builds
|
# integration tests for Linux builds
|
||||||
|
### disabled because of Linux headless issues
|
||||||
.integration_test_linux:
|
.integration_test_linux:
|
||||||
extends: .integration_test
|
extends: .integration_test
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- HOMESERVER_IMPLEMENTATION:
|
||||||
|
- conduit
|
||||||
script:
|
script:
|
||||||
- apk add cmake ninja gtk+3.0-dev clang pkgconf xz-dev libsecret-dev jsoncpp-dev
|
- apt-get update
|
||||||
|
- apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev libsecret-1-dev libjsoncpp-dev
|
||||||
- flutter pub get
|
- flutter pub get
|
||||||
- flutter test integration_test -d linux
|
- flutter test integration_test -d linux --dart-define=HOMESERVER=$HOMESERVER --dart-define=USER1_NAME=$USER1_NAME --dart-define=USER2_NAME=$USER2_NAME --dart-define=USER1_PW=$USER1_PW --dart-define=USER2_PW=$USER2_PW || ( sleep 10 && exit 1 )
|
||||||
|
after_script: []
|
||||||
|
artifacts:
|
||||||
|
|
||||||
# extending the default tests to test the Google-flavored builds
|
# extending the default tests to test the Google-flavored builds
|
||||||
.integration_test_proprietary:
|
.integration_test_proprietary:
|
||||||
extends: .integration_test
|
extends: .integration_test
|
||||||
|
parallel:
|
||||||
|
matrix:
|
||||||
|
- HOMESERVER_IMPLEMENTATION:
|
||||||
|
- conduit
|
||||||
script:
|
script:
|
||||||
|
# start AVD and keep running in background
|
||||||
|
- scripts/integration-start-avd.sh &
|
||||||
- git apply ./scripts/enable-android-google-services.patch
|
- git apply ./scripts/enable-android-google-services.patch
|
||||||
- flutter pub get
|
- flutter pub get
|
||||||
- flutter test integration_test
|
- scrcpy --no-display --record video.mkv &
|
||||||
|
- flutter test integration_test --dart-define=HOMESERVER=$HOMESERVER --dart-define=USER1_NAME=$USER1_NAME --dart-define=USER2_NAME=$USER2_NAME --dart-define=USER1_PW=$USER1_PW --dart-define=USER2_PW=$USER2_PW || ( sleep 10 && exit 1 )
|
||||||
|
|
||||||
.release_mode_launches:
|
release_mode_launches:
|
||||||
parallel:
|
parallel:
|
||||||
matrix:
|
matrix:
|
||||||
- FLAVOR:
|
- FLAVOR:
|
||||||
@ -99,15 +125,17 @@ widget_test:
|
|||||||
stage: test
|
stage: test
|
||||||
before_script:
|
before_script:
|
||||||
- |
|
- |
|
||||||
if [ "$FLAVOR" == "proprietary" ]; then
|
if [ "$FLAVOR" == "proprietary" ]; then
|
||||||
git apply ./scripts/enable-android-google-services.patch
|
git apply ./scripts/enable-android-google-services.patch
|
||||||
fi
|
fi
|
||||||
script:
|
script:
|
||||||
# start AVD and keep running in background
|
# start AVD and keep running in background
|
||||||
- scripts/integration-start-avd.sh &
|
- scripts/integration-start-avd.sh &
|
||||||
# generate temporary release build configuration and ensure app launches
|
# generate temporary release build configuration and ensure app launches
|
||||||
- scripts/integration-check-release-build.sh
|
- scripts/integration-check-release-build.sh
|
||||||
timeout: 20m
|
timeout: 20m
|
||||||
|
only:
|
||||||
|
- tags
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
@ -116,20 +144,46 @@ build_web:
|
|||||||
stage: build
|
stage: build
|
||||||
before_script:
|
before_script:
|
||||||
[sudo apt update && sudo apt install curl -y, ./scripts/prepare-web.sh]
|
[sudo apt update && sudo apt install curl -y, ./scripts/prepare-web.sh]
|
||||||
script: [./scripts/build-web.sh]
|
script:
|
||||||
|
- flutter build web --release --verbose --source-maps
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build/web/
|
- build/web/
|
||||||
tags:
|
|
||||||
- docker
|
# yes, we *do* build a Windows DLL on Linux. More reliable.
|
||||||
- famedly
|
build_olm_windows:
|
||||||
|
image: archlinux:latest
|
||||||
|
stage: test
|
||||||
|
before_script:
|
||||||
|
- pacman-key --init
|
||||||
|
- pacman --noconfirm -Sy mingw-w64 cmake git base-devel
|
||||||
|
script:
|
||||||
|
- ./scripts/build-olm-windows.sh
|
||||||
|
- mv olm/build/libolm.dll .
|
||||||
|
artifacts:
|
||||||
|
paths:
|
||||||
|
- libolm.dll
|
||||||
|
allow_failure: true
|
||||||
|
only:
|
||||||
|
- main
|
||||||
|
- tags
|
||||||
|
|
||||||
build_windows:
|
build_windows:
|
||||||
extends:
|
extends:
|
||||||
- .shared_windows_runners
|
- .shared_windows_runners
|
||||||
stage: build
|
stage: test
|
||||||
before_script: [./scripts/prepare-windows.ps1]
|
before_script:
|
||||||
script: [./scripts/build-windows.ps1]
|
- ./scripts/prepare-windows.ps1
|
||||||
|
# workarounding artifacts download being broken
|
||||||
|
- $response = Invoke-WebRequest -Uri "$CI_API_V4_URL/projects/$CI_PROJECT_ID/pipelines/$CI_PIPELINE_ID/jobs" -UseBasicParsing
|
||||||
|
- $jobs = $response | ConvertFrom-Json
|
||||||
|
- $job = $jobs | where { $_.name -eq "build_olm_windows" }
|
||||||
|
- $jobId = $job.id
|
||||||
|
- Invoke-WebRequest -Uri "$CI_API_V4_URL/projects/$CI_PROJECT_ID/jobs/$jobId/artifacts/libolm.dll" -UseBasicParsing -OutFile libolm.dll
|
||||||
|
script:
|
||||||
|
- ./scripts/build-windows.ps1
|
||||||
|
- Copy-Item -Path "libolm.dll" -Destination "build/windows/runner/Release"
|
||||||
|
- ./scripts/package-windows.ps1
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- build/windows/runner/Release
|
- build/windows/runner/Release
|
||||||
@ -140,28 +194,28 @@ build_windows:
|
|||||||
|
|
||||||
build_android_debug:
|
build_android_debug:
|
||||||
stage: build
|
stage: build
|
||||||
script: [./scripts/build-android-debug.sh]
|
script: [flutter build apk --debug]
|
||||||
artifacts:
|
artifacts:
|
||||||
when: on_success
|
when: on_success
|
||||||
paths:
|
paths:
|
||||||
- build/app/outputs/apk/debug/app-debug.apk
|
- build/app/outputs/apk/debug/app-debug.apk
|
||||||
except:
|
|
||||||
- main
|
|
||||||
- tags
|
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
|
except:
|
||||||
|
- main
|
||||||
|
- tags
|
||||||
|
|
||||||
build_android_apk:
|
build_android_apk:
|
||||||
stage: build
|
stage: build
|
||||||
before_script:
|
before_script:
|
||||||
- git apply ./scripts/enable-android-google-services.patch
|
- git apply ./scripts/enable-android-google-services.patch
|
||||||
- ./scripts/prepare-android-release.sh
|
- ./scripts/prepare-android-release.sh
|
||||||
script: [./scripts/build-android-apk.sh]
|
script: [flutter build apk --release]
|
||||||
artifacts:
|
artifacts:
|
||||||
when: on_success
|
when: on_success
|
||||||
paths:
|
paths:
|
||||||
- build/android/app-release.apk
|
- build/app/outputs/apk/release/app-release.apk
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
@ -201,9 +255,6 @@ fdroid_repo:
|
|||||||
needs:
|
needs:
|
||||||
- "build_android_apk"
|
- "build_android_apk"
|
||||||
resource_group: playstore_release
|
resource_group: playstore_release
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- famedly
|
|
||||||
allow_failure: true
|
allow_failure: true
|
||||||
only:
|
only:
|
||||||
- main
|
- main
|
||||||
@ -223,12 +274,7 @@ pages:
|
|||||||
- cd ..
|
- cd ..
|
||||||
- mv docs public
|
- mv docs public
|
||||||
- mv repo public || true
|
- mv repo public || true
|
||||||
- mv build/web/ public/nightly
|
- mv build/web/ public/web
|
||||||
# ensure the nightly deployment knows its location
|
|
||||||
- sed -i "s/href=\"\/web\/\"/href=\"\/nightly\/\"/g" public/nightly/index.html
|
|
||||||
- rm -rf build
|
|
||||||
- ./scripts/download-web-stable.sh
|
|
||||||
- mv stable public/web
|
|
||||||
artifacts:
|
artifacts:
|
||||||
paths:
|
paths:
|
||||||
- public
|
- public
|
||||||
@ -237,11 +283,11 @@ pages:
|
|||||||
|
|
||||||
build_linux_x86:
|
build_linux_x86:
|
||||||
stage: build
|
stage: build
|
||||||
|
image: registry.gitlab.com/famedly/company/frontend/flutter-dockerimages/flutter-linux/stable:${FLUTTER_VERSION}
|
||||||
before_script:
|
before_script:
|
||||||
[
|
- sudo apt-get update
|
||||||
sudo apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install keyboard-configuration -y && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 -y,
|
- sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 -y
|
||||||
]
|
script: [flutter build linux --release]
|
||||||
script: [./scripts/build-linux.sh]
|
|
||||||
tags:
|
tags:
|
||||||
- docker
|
- docker
|
||||||
- famedly
|
- famedly
|
||||||
@ -252,8 +298,9 @@ build_linux_x86:
|
|||||||
|
|
||||||
build_linux_arm64:
|
build_linux_arm64:
|
||||||
stage: build
|
stage: build
|
||||||
before_script: [flutter upgrade]
|
before_script:
|
||||||
script: [./scripts/build-linux.sh]
|
- flutter upgrade $FLUTTER_VERSION --force
|
||||||
|
script: [flutter build linux --release]
|
||||||
tags: [docker_arm64]
|
tags: [docker_arm64]
|
||||||
only:
|
only:
|
||||||
- main
|
- main
|
||||||
@ -267,8 +314,6 @@ build_linux_arm64:
|
|||||||
update_dependencies:
|
update_dependencies:
|
||||||
stage: build
|
stage: build
|
||||||
needs: []
|
needs: []
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
only:
|
only:
|
||||||
- schedules
|
- schedules
|
||||||
variables:
|
variables:
|
||||||
@ -293,9 +338,6 @@ update_dependencies:
|
|||||||
.release:
|
.release:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
image: curlimages/curl:latest
|
image: curlimages/curl:latest
|
||||||
tags:
|
|
||||||
- docker
|
|
||||||
- famedly
|
|
||||||
rules:
|
rules:
|
||||||
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
|
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
|
||||||
- if: '$CI_COMMIT_TAG =~ /^rc\d+\.\d+\.\d+-\d+$/'
|
- if: '$CI_COMMIT_TAG =~ /^rc\d+\.\d+\.\d+-\d+$/'
|
||||||
@ -308,28 +350,29 @@ upload_android:
|
|||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- |
|
- |
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file build/android/app-release.apk ${PACKAGE_REGISTRY_URL}/fluffychat.apk
|
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file build/app/outputs/apk/release/app-release.apk ${PACKAGE_REGISTRY_URL}/fluffychat.apk
|
||||||
|
|
||||||
upload_web:
|
upload_web:
|
||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- tar czf package.tar.gz -C build/web/ .
|
- tar czf package.tar.gz -C build/web/ .
|
||||||
- |
|
- |
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-web.tar.gz
|
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-web.tar.gz
|
||||||
|
|
||||||
upload_linux_x86:
|
upload_linux_x86:
|
||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- tar czf package.tar.gz -C build/linux/x64/release/bundle/ .
|
- tar czf package.tar.gz -C build/linux/x64/release/bundle/ .
|
||||||
- |
|
- |
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-x86.tar.gz
|
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-x86.tar.gz
|
||||||
|
|
||||||
upload_linux_arm64:
|
upload_linux_arm64:
|
||||||
extends: .release
|
extends: .release
|
||||||
script:
|
script:
|
||||||
- tar czf package.tar.gz -C build/linux/arm64/release/bundle/ .
|
- tar czf package.tar.gz -C build/linux/arm64/release/bundle/ .
|
||||||
- |
|
- |
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-arm64.tar.gz
|
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.tar.gz ${PACKAGE_REGISTRY_URL}/fluffychat-linux-arm64.tar.gz
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
upload_windows:
|
upload_windows:
|
||||||
extends: .release
|
extends: .release
|
||||||
@ -339,8 +382,9 @@ upload_windows:
|
|||||||
- mv build/windows/runner/Release/fluffychat.msix fluffychat.msix
|
- mv build/windows/runner/Release/fluffychat.msix fluffychat.msix
|
||||||
- cd build/windows/runner/Release; zip -r ../../../../package.zip . ; cd -
|
- cd build/windows/runner/Release; zip -r ../../../../package.zip . ; cd -
|
||||||
- |
|
- |
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.zip ${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip
|
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file package.zip ${PACKAGE_REGISTRY_URL}/fluffychat-windows.zip
|
||||||
curl --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file fluffychat.msix ${PACKAGE_REGISTRY_URL}/fluffychat-windows.msix
|
curl --fail-with-body --header "JOB-TOKEN: ${CI_JOB_TOKEN}" --upload-file fluffychat.msix ${PACKAGE_REGISTRY_URL}/fluffychat-windows.msix
|
||||||
|
allow_failure: true
|
||||||
|
|
||||||
deploy_playstore:
|
deploy_playstore:
|
||||||
stage: deploy
|
stage: deploy
|
||||||
|
|||||||
25
.metadata
@ -4,7 +4,7 @@
|
|||||||
# This file should be version controlled.
|
# This file should be version controlled.
|
||||||
|
|
||||||
version:
|
version:
|
||||||
revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
||||||
channel: stable
|
channel: stable
|
||||||
|
|
||||||
project_type: app
|
project_type: app
|
||||||
@ -13,26 +13,11 @@ project_type: app
|
|||||||
migration:
|
migration:
|
||||||
platforms:
|
platforms:
|
||||||
- platform: root
|
- platform: root
|
||||||
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
||||||
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
||||||
- platform: android
|
|
||||||
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
- platform: ios
|
|
||||||
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
- platform: linux
|
|
||||||
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
- platform: macos
|
- platform: macos
|
||||||
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
create_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
||||||
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
base_revision: d3d8effc686d73e0114d71abdcccef63fa1f25d2
|
||||||
- platform: web
|
|
||||||
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
- platform: windows
|
|
||||||
create_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
base_revision: b8f7f1f9869bb2d116aa6a70dbeac61000b52849
|
|
||||||
|
|
||||||
# User provided section
|
# User provided section
|
||||||
|
|
||||||
|
|||||||
226
CHANGELOG.md
@ -1,3 +1,229 @@
|
|||||||
|
## v1.12.0
|
||||||
|
- Added translation using Weblate (Toki Pona) (Mæve Rey)
|
||||||
|
- Translated using Weblate (Arabic) (Rex_sa)
|
||||||
|
- Translated using Weblate (Chinese (Simplified)) (Eric)
|
||||||
|
- Translated using Weblate (Croatian) (Milo Ivir)
|
||||||
|
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
||||||
|
- Translated using Weblate (Galician) (josé m)
|
||||||
|
- Translated using Weblate (Indonesian) (Linerly)
|
||||||
|
- Translated using Weblate (Polish) (lauren n. liberda)
|
||||||
|
- Translated using Weblate (Romanian) (Riley)
|
||||||
|
- Translated using Weblate (Russian) (DarkCoder15)
|
||||||
|
- Translated using Weblate (Spanish) (José Muñoz)
|
||||||
|
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
||||||
|
- build: Remove dependency overwrite for ffi (Krille)
|
||||||
|
- build: Update dependencies (Krille)
|
||||||
|
- builds: Change minsdkversion of Android from 16 to 19 (Krille)
|
||||||
|
- builds: Do not allow failure for linux x86 (Krille)
|
||||||
|
- builds: Do not use verbose mode on building linux (Krille)
|
||||||
|
- builds: Linux with flutter 3.10 (Krille)
|
||||||
|
- builds: Remove workaround for building linux arm64 (Krille)
|
||||||
|
- builds: Update file_picker to 5.3.0 (Krille)
|
||||||
|
- builds: Update flutter table html (Krille)
|
||||||
|
- builds: Update flutter_html (Krille)
|
||||||
|
- builds: migrate to dart 3.0/flutter 3.10 (lauren n. liberda)
|
||||||
|
- chore: Add missing blockquote style (Krille)
|
||||||
|
- chore: Allow failure in build linux for now (Krille)
|
||||||
|
- chore: Ask for storage persistence (Krille)
|
||||||
|
- chore: Clean unused translations (Malin Errenst)
|
||||||
|
- chore: Enhance room pills (Krille)
|
||||||
|
- chore: Minor code clean up (Krille)
|
||||||
|
- chore: Update flutter webrtc (Krille)
|
||||||
|
- chore: Upgrade to Flutter 3.10.1 (Malin Errenst)
|
||||||
|
- chore: change release curl calls to use --fail-with-body (Tim Flink)
|
||||||
|
- chore: update macOS icons and add build script (TheOneWithTheBraid)
|
||||||
|
- design: Replace anime images with neutral cupertino icons (Krille)
|
||||||
|
- feat: Add toggle to mute notifications from chat groups (fbievan)
|
||||||
|
- feat: Allow ruby tags in html (Krille)
|
||||||
|
- feat: Display progress value for initial sync (Krille)
|
||||||
|
- feat: Implement new error reporting tool when critical features break like playing audio or video messages or opening a chat (Krille)
|
||||||
|
- feat: clean up macOS build metadata (TheOneWithTheBraid)
|
||||||
|
- feat: set display information correctly (TheOneWithTheBraid)
|
||||||
|
- feat: update macOS build files (TheOneWithTheBraid)
|
||||||
|
- feat: update macOS build information for macOS Ventura (TheOneWithTheBraid)
|
||||||
|
- fix "Unhandled Exception: VRouter.of(context) was called with a context which does not contain a VRouter." (Lauren N. Liberda)
|
||||||
|
- fix: Broken arb file (Krille)
|
||||||
|
- fix: Do not unnecessary request all members in public rooms (Krille)
|
||||||
|
- fix: Remove wrong rendered linebreak in html (Krille)
|
||||||
|
- fix: Scroll down button (Krille)
|
||||||
|
- fix: Scroll up and scroll down buttons in chat list (Krille)
|
||||||
|
- fix: Scrolldown button (Krille)
|
||||||
|
- fix: Too long file name cause a render overflow (Skying)
|
||||||
|
- fix: Try to reload timeline on IOException (Krille)
|
||||||
|
- fix: User pills (Krille)
|
||||||
|
- fix: broken CI artifact uploads (TheOneWithTheBraid)
|
||||||
|
- fix: custom emote placeholder (TheOneWithTheBraid)
|
||||||
|
- fix: path of libolm (TheOneWithTheBraid)
|
||||||
|
- fix: Quick account switching (JHansen)
|
||||||
|
- fix: read reciepts (JHansen)
|
||||||
|
- perf: Use valuenotifier to not rebuild chatlist (Krille)
|
||||||
|
- refactor: Reimplement flutter matrix html locally (Krille)
|
||||||
|
- refactor: Update Roboto and Noto Emoji (The one with the Braid)
|
||||||
|
- refactor: Use AnimatedSize for FAB (Krille)
|
||||||
|
- refactor: Use DateTime for weekday localization (Malin Errenst)
|
||||||
|
|
||||||
|
## v1.11.2
|
||||||
|
- Translated using Weblate (Croatian) (Milo Ivir)
|
||||||
|
- Translated using Weblate (Dutch) (Jelv)
|
||||||
|
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
||||||
|
- Translated using Weblate (Galician) (josé m)
|
||||||
|
- Translated using Weblate (Polish) (Eryk Michalak)
|
||||||
|
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
||||||
|
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
||||||
|
- feat: Permission dialog before open link in browser (Krille)
|
||||||
|
- fix: Chats do not load (Krille)
|
||||||
|
|
||||||
|
## v1.11.1 - 2023-04-20
|
||||||
|
- fix: Download files on web and iOS with correct mimetype
|
||||||
|
|
||||||
|
## v1.11.0 - 2023-04-14
|
||||||
|
- feat: Add visual read marker (Krille)
|
||||||
|
- feat: Jump to last read event (Krille)
|
||||||
|
- feat: Use fragmented timeline to jump to event (Krille)
|
||||||
|
- feat: change to flutterwebauth2 (ShootingStarDragons)
|
||||||
|
- fix: Join public room (Krille)
|
||||||
|
- fix: Set fcm priority to max on android (Krille)
|
||||||
|
- refactor: CI scripts and old workarounds for build scripts (Krille)
|
||||||
|
- refactor: Client in ChatPage (Krille)
|
||||||
|
- refactor: Not nullable room in ChatPage (Krille)
|
||||||
|
- refactor: Switch to file_picker package and get rid of some dependency overrides (Krille)
|
||||||
|
- refactor: Use correct Matrix instance (Krille)
|
||||||
|
- style: Make emptypage logo bigger (Krille)
|
||||||
|
- style: Minor adjustments for modal bottom sheets (Krille)
|
||||||
|
- style: Move chats to top (Krille)
|
||||||
|
- style: Use SliverList for chatlist (Krille)
|
||||||
|
- refactor: Container -> SizedBox.shrink() (noob_tea)
|
||||||
|
- Translated using Weblate (Chinese (Simplified)) (Eric)
|
||||||
|
- Translated using Weblate (Dutch) (Jelv)
|
||||||
|
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
||||||
|
- Translated using Weblate (French) (Anne Onyme 017)
|
||||||
|
- Translated using Weblate (Galician) (josé m)
|
||||||
|
- Translated using Weblate (Indonesian) (Linerly)
|
||||||
|
- Translated using Weblate (Persian) (Parsa)
|
||||||
|
- Translated using Weblate (Persian) (Siavash)
|
||||||
|
- Translated using Weblate (Polish) (Luna)
|
||||||
|
- Translated using Weblate (Swedish) (Kristoffer Grundström)
|
||||||
|
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
||||||
|
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
||||||
|
|
||||||
|
## v1.10.0 - 2023-02-25
|
||||||
|
- Added translation using Weblate (Thai) (Wphaoka)
|
||||||
|
- Added translation using Weblate (Tibetan) (Nathan Freitas)
|
||||||
|
- Default hardcoded message when l10n is not available (fabienli)
|
||||||
|
- Fix: The stable repo fingerprint (TODO the qr-code should be updated) (machiav3lli)
|
||||||
|
- Translated using Weblate (Basque) (xabirequejo)
|
||||||
|
- Translated using Weblate (Dutch) (Jelv)
|
||||||
|
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
||||||
|
- Translated using Weblate (French) (Anne Onyme 017)
|
||||||
|
- Translated using Weblate (Galician) (josé m)
|
||||||
|
- Translated using Weblate (Galician) (josé m)
|
||||||
|
- Translated using Weblate (Indonesian) (Linerly)
|
||||||
|
- Translated using Weblate (Japanese) (Suguru Hirahara)
|
||||||
|
- Translated using Weblate (Persian) (Farooq Karimi Zadeh)
|
||||||
|
- Translated using Weblate (Swedish) (Joaquim Homrighausen)
|
||||||
|
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
||||||
|
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
||||||
|
- chore: Disable stable for web until script is fixed (Krille)
|
||||||
|
- chore: Display warning when logout without backup (Krille)
|
||||||
|
- chore: Downgrade flutter CI version (Krille)
|
||||||
|
- chore: Follow up audioplayer on linux (Krille)
|
||||||
|
- chore: Follow up chat encryption desgin (Krille)
|
||||||
|
- chore: Follow up fix audioplayer on android (Christian Pauly)
|
||||||
|
- chore: Follow up formatting (Christian Pauly)
|
||||||
|
- chore: Follow up formatting (Krille)
|
||||||
|
- chore: Follow up remove hero animation (Krille)
|
||||||
|
- chore: Follow up secrity settings design (Krille)
|
||||||
|
- chore: Follow up settings page (Krille)
|
||||||
|
- chore: Follow up settings page design (Christian Pauly)
|
||||||
|
- chore: Follow up style adjustments (Krille)
|
||||||
|
- chore: Lookup l10n in pushhelper if null (Krille)
|
||||||
|
- chore: Update matrix package to 0.17.0 (Krille)
|
||||||
|
- chore: Update to Flutter 3.7.1 (Krille)
|
||||||
|
- docs/qr-stable.svg: update the QR code (Aminda Suomalainen)
|
||||||
|
- feat: Enable audioplayer for web and linux (Christian Pauly)
|
||||||
|
- fix: Display error when user tries to send too large file (Christian Pauly)
|
||||||
|
- refactor: Do only instantiate AudioPlayer() object when in use (Christian Pauly)
|
||||||
|
- refactor: Remove syncstatus verbose logs (Christian Pauly)
|
||||||
|
- refactor: Store cached files in tmp directory so OS will clear file cache from time to time (Krille)
|
||||||
|
- style: Adjust key verification dialog (Christian Pauly)
|
||||||
|
- style: Bootstrap design adjustments (Christian Pauly)
|
||||||
|
- style: Encryption page adjustments (Christian Pauly)
|
||||||
|
- style: Enhance user device settings design (Krille)
|
||||||
|
- style: Enhanced chat details design (Krille)
|
||||||
|
- style: Give chat list list tiles rounded corners (Krille)
|
||||||
|
- style: Link underline color (Christian Pauly)
|
||||||
|
- style: Make adaptive bottom sheets scrollable by default (Krille)
|
||||||
|
- style: Make invite page more pretty (Krille)
|
||||||
|
- style: New settings design (Krille)
|
||||||
|
- style: Nicer chips in encryption settings and icons showing device status (Krille)
|
||||||
|
- style: Use emojis on web as well (Christian Pauly)
|
||||||
|
- style: Use robotomono to display device keys (Christian Pauly)
|
||||||
|
- utils/url_launcher: force opening http(s) links in external browser (Marcus Hoffmann)
|
||||||
|
|
||||||
|
## v1.9.0 - 2023-01-29
|
||||||
|
- Translated using Weblate (Czech) (Michal Bedáň)
|
||||||
|
- Translated using Weblate (Czech) (grreby)
|
||||||
|
- Translated using Weblate (Dutch) (Jelv)
|
||||||
|
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
||||||
|
- Translated using Weblate (Galician) (josé m)
|
||||||
|
- Translated using Weblate (German) (Christian)
|
||||||
|
- Translated using Weblate (German) (Vri 🌈)
|
||||||
|
- Translated using Weblate (Indonesian) (Linerly)
|
||||||
|
- Translated using Weblate (Korean) (Youngbin Han)
|
||||||
|
- Translated using Weblate (Polish) (Wiktor)
|
||||||
|
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
||||||
|
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
||||||
|
- chore: Change invite link textfield label (Krille)
|
||||||
|
- chore: Remove unused dependency (Krille)
|
||||||
|
- chore: Remove unused translations (Krille)
|
||||||
|
- chore: Update Matrix SDK and refactor (Krille)
|
||||||
|
- chore: Update dependencies (Krille)
|
||||||
|
- chore: Update flutter_map (Krille)
|
||||||
|
- chore: add integration tests (TheOneWithTheBraid)
|
||||||
|
- chore: add integration tests for spaces (TheOneWithTheBraid)
|
||||||
|
- design: More clear chat background and rounded popup menu (Krille)
|
||||||
|
- design: Nicer navigationrail (Krille)
|
||||||
|
- design: Upgrade to Flutter 3.7
|
||||||
|
- feat: Bring back disabling the header bar on Linux desktop (q234rty)
|
||||||
|
- feat: Nicer design for abandonded DM rooms (Christian Pauly)
|
||||||
|
- fix: Archive (Krille)
|
||||||
|
- fix: Shared preferences package for flutter 3.7 (Christian Pauly)
|
||||||
|
- fix: permission of web builds (TheOneWithTheBraid)
|
||||||
|
- fix: Notification Settings (Krille)
|
||||||
|
- refactor: Migrate to Flutter 3.7.0 (Christian Pauly)
|
||||||
|
- refactor: Same animations everywhere in app (Krille)
|
||||||
|
- refactor: Stories header with futurebuilder (Krille)
|
||||||
|
- refactor: disable some redundant tests (TheOneWithTheBraid)
|
||||||
|
- style: Animate in out search results (Krille)
|
||||||
|
- style: New modal bottom sheets (Krille)
|
||||||
|
- style: Redesign public room bottomsheets (Krille)
|
||||||
|
|
||||||
|
## v1.8.0 2022-12-30
|
||||||
|
- Added translation using Weblate (Yue (yue_HK)) (Raatty)
|
||||||
|
- Translated using Weblate (Chinese (Simplified)) (Mike Evans)
|
||||||
|
- Translated using Weblate (Estonian) (Priit Jõerüüt)
|
||||||
|
- Translated using Weblate (French) (Anne Onyme 017)
|
||||||
|
- Translated using Weblate (Indonesian) (Linerly)
|
||||||
|
- Translated using Weblate (Turkish) (Oğuz Ersen)
|
||||||
|
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
|
||||||
|
- design: New encryption page (Krille Fear)
|
||||||
|
- feat: Add audio message support to linux (Krille Fear)
|
||||||
|
- feat: Use Android system accent color (Krille Fear)
|
||||||
|
- feat: include olm to Windows builds (TheOneWithTheBraid)
|
||||||
|
- feat: Store drafts (Krille)
|
||||||
|
- fix: Android push notification follow-up (TheOneWithTheBraid)
|
||||||
|
- fix: Content banner (Krille Fear)
|
||||||
|
- fix: Correct redacted by username (Krille Fear)
|
||||||
|
- fix: Do not setup push on every app resume (Krille Fear)
|
||||||
|
- fix: Encryption button is orange in public rooms (Krille Fear)
|
||||||
|
- fix: File event design (Krille Fear)
|
||||||
|
- fix: Hide google services warning after marked (Krille Fear)
|
||||||
|
- fix: Improve story page appearance (Reinhart Previano Koentjoro)
|
||||||
|
- fix: Libhandy windows (Krille Fear)
|
||||||
|
- fix: Monochromatic icon rendering for Android 13+ (Reinhart Previano Koentjoro)
|
||||||
|
- fix: homeserver error text not visible in app bar (TheOneWithTheBraid)
|
||||||
|
- fix: minor issues in room list (TheOneWithTheBraid)
|
||||||
|
|
||||||
## v1.7.2 2022-12-19
|
## v1.7.2 2022-12-19
|
||||||
Update dependencies and translations.
|
Update dependencies and translations.
|
||||||
|
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
FROM cirrusci/flutter as builder
|
FROM ghcr.io/cirruslabs/flutter as builder
|
||||||
RUN sudo apt update && sudo apt install curl -y
|
RUN sudo apt update && sudo apt install curl -y
|
||||||
COPY . /app
|
COPY . /app
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|||||||
@ -8,6 +8,7 @@ linter:
|
|||||||
- prefer_final_locals
|
- prefer_final_locals
|
||||||
- prefer_final_in_for_each
|
- prefer_final_in_for_each
|
||||||
- sort_pub_dependencies
|
- sort_pub_dependencies
|
||||||
|
- require_trailing_commas
|
||||||
|
|
||||||
analyzer:
|
analyzer:
|
||||||
errors:
|
errors:
|
||||||
|
|||||||
@ -44,7 +44,7 @@ android {
|
|||||||
|
|
||||||
defaultConfig {
|
defaultConfig {
|
||||||
applicationId "chat.fluffy.fluffychat"
|
applicationId "chat.fluffy.fluffychat"
|
||||||
minSdkVersion 16
|
minSdkVersion 19
|
||||||
targetSdkVersion 31
|
targetSdkVersion 31
|
||||||
versionCode flutterVersionCode.toInteger()
|
versionCode flutterVersionCode.toInteger()
|
||||||
versionName flutterVersionName
|
versionName flutterVersionName
|
||||||
|
|||||||
@ -93,8 +93,9 @@
|
|||||||
</intent-filter>
|
</intent-filter>
|
||||||
</activity>
|
</activity>
|
||||||
|
|
||||||
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity"
|
<activity
|
||||||
android:exported="true">
|
android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
|
||||||
|
android:exported="true">
|
||||||
<intent-filter android:label="flutter_web_auth">
|
<intent-filter android:label="flutter_web_auth">
|
||||||
<action android:name="android.intent.action.VIEW" />
|
<action android:name="android.intent.action.VIEW" />
|
||||||
<category android:name="android.intent.category.DEFAULT" />
|
<category android:name="android.intent.category.DEFAULT" />
|
||||||
|
|||||||
11
android/app/src/main/res/drawable/ic_launcher_monochrome.xml
Normal file
@ -2,5 +2,5 @@
|
|||||||
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<background android:drawable="@color/ic_launcher_background"/>
|
<background android:drawable="@color/ic_launcher_background"/>
|
||||||
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
<foreground android:drawable="@drawable/ic_launcher_foreground"/>
|
||||||
<monochrome android:drawable="@drawable/ic_launcher_foreground"/>
|
<monochrome android:drawable="@drawable/ic_launcher_monochrome"/>
|
||||||
</adaptive-icon>
|
</adaptive-icon>
|
||||||
@ -1,5 +1,5 @@
|
|||||||
buildscript {
|
buildscript {
|
||||||
ext.kotlin_version = '1.6.10'
|
ext.kotlin_version = '1.8.0'
|
||||||
repositories {
|
repositories {
|
||||||
google()
|
google()
|
||||||
mavenCentral()
|
mavenCentral()
|
||||||
@ -27,6 +27,6 @@ subprojects {
|
|||||||
project.evaluationDependsOn(':app')
|
project.evaluationDependsOn(':app')
|
||||||
}
|
}
|
||||||
|
|
||||||
task clean(type: Delete) {
|
tasks.register("clean", Delete) {
|
||||||
delete rootProject.buildDir
|
delete rootProject.buildDir
|
||||||
}
|
}
|
||||||
|
|||||||
@ -5,12 +5,17 @@
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="0: update_fastlane" time="0.000202">
|
<testcase classname="fastlane.lanes" name="0: update_fastlane" time="1.455419">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
<testcase classname="fastlane.lanes" name="1: default_platform" time="7.9e-05">
|
<testcase classname="fastlane.lanes" name="1: default_platform" time="0.000127">
|
||||||
|
|
||||||
|
</testcase>
|
||||||
|
|
||||||
|
|
||||||
|
<testcase classname="fastlane.lanes" name="2: google_play_track_version_codes" time="2.638619">
|
||||||
|
|
||||||
</testcase>
|
</testcase>
|
||||||
|
|
||||||
|
|||||||
BIN
assets/banner_transparent.png
Normal file
|
After Width: | Height: | Size: 82 KiB |
|
Before Width: | Height: | Size: 37 KiB After Width: | Height: | Size: 44 KiB |
@ -1,30 +1,25 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2021-08-14 12:41:10.154280",
|
"@@last_modified": "2021-08-14 12:41:10.154280",
|
||||||
"about": "সম্পর্কে",
|
"about": "সম্পর্কে",
|
||||||
"@about": {
|
"@about": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"accept": "স্বীকার করি",
|
"accept": "স্বীকার করি",
|
||||||
"@accept": {
|
"@accept": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"acceptedTheInvitation": "{username} আমন্ত্রণ গ্রহণ করেছে",
|
"acceptedTheInvitation": "{username} আমন্ত্রণ গ্রহণ করেছে",
|
||||||
"@acceptedTheInvitation": {
|
"@acceptedTheInvitation": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"username": {}
|
"username": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"account": "অ্যাকাউন্ট",
|
||||||
|
"@account": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
},
|
|
||||||
"account": "অ্যাকাউন্ট",
|
|
||||||
"@account": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"accountInformation": "অ্যাকাউন্ট তথ্য",
|
|
||||||
"@accountInformation": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
1
assets/l10n/intl_bo.arb
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
1
assets/l10n/intl_el.arb
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
@ -1 +1 @@
|
|||||||
{}
|
{}
|
||||||
@ -1,155 +1,120 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2021-08-14 12:41:09.940318",
|
"@@last_modified": "2021-08-14 12:41:09.940318",
|
||||||
"copiedToClipboard": "Copiada para a área de transferência",
|
"copiedToClipboard": "Copiada para a área de transferência",
|
||||||
"@copiedToClipboard": {
|
"@copiedToClipboard": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"login": "Iniciar sessão",
|
"login": "Iniciar sessão",
|
||||||
"@login": {
|
"@login": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"monday": "segunda-feira",
|
"about": "Sobre",
|
||||||
"@monday": {
|
"@about": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"saturday": "sábado",
|
"admin": "Admin",
|
||||||
"@saturday": {
|
"@admin": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"wednesday": "quarta-feira",
|
"areYouSure": "Tens a certeza?",
|
||||||
"@wednesday": {
|
"@areYouSure": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"about": "Sobre",
|
"notifications": "Notificações",
|
||||||
"@about": {
|
"@notifications": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"admin": "Admin",
|
"account": "Conta",
|
||||||
"@admin": {
|
"@account": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"areYouSure": "Tens a certeza?",
|
"cancel": "Cancelar",
|
||||||
"@areYouSure": {
|
"@cancel": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"notifications": "Notificações",
|
"delete": "Eliminar",
|
||||||
"@notifications": {
|
"@delete": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {}
|
||||||
},
|
},
|
||||||
"account": "Conta",
|
"dateAndTimeOfDay": "{date}, {timeOfDay}",
|
||||||
"@account": {
|
"@dateAndTimeOfDay": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {}
|
"placeholders": {
|
||||||
},
|
"date": {},
|
||||||
"cancel": "Cancelar",
|
"timeOfDay": {}
|
||||||
"@cancel": {
|
}
|
||||||
"type": "text",
|
},
|
||||||
"placeholders": {}
|
"dateWithYear": "{day}-{month}-{year}",
|
||||||
},
|
"@dateWithYear": {
|
||||||
"delete": "Eliminar",
|
"type": "text",
|
||||||
"@delete": {
|
"placeholders": {
|
||||||
"type": "text",
|
"year": {},
|
||||||
"placeholders": {}
|
"month": {},
|
||||||
},
|
"day": {}
|
||||||
"dateAndTimeOfDay": "{date}, {timeOfDay}",
|
}
|
||||||
"@dateAndTimeOfDay": {
|
},
|
||||||
"type": "text",
|
"help": "Ajuda",
|
||||||
"placeholders": {
|
"@help": {
|
||||||
"date": {},
|
"type": "text",
|
||||||
"timeOfDay": {}
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"messages": "Mensagens",
|
||||||
|
"@messages": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"reason": "Razão",
|
||||||
|
"@reason": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"privacy": "Privacidade",
|
||||||
|
"@privacy": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"openCamera": "Abrir câmara",
|
||||||
|
"@openCamera": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"settings": "Configurações",
|
||||||
|
"@settings": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"logout": "Terminar sessão",
|
||||||
|
"@logout": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"search": "Pesquisar",
|
||||||
|
"@search": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"users": "Utilizadores",
|
||||||
|
"@users": {},
|
||||||
|
"close": "Fechar",
|
||||||
|
"@close": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"dateWithoutYear": "{day}-{month}",
|
||||||
|
"@dateWithoutYear": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {
|
||||||
|
"month": {},
|
||||||
|
"day": {}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"dateWithYear": "{day}-{month}-{year}",
|
|
||||||
"@dateWithYear": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {
|
|
||||||
"year": {},
|
|
||||||
"month": {},
|
|
||||||
"day": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"help": "Ajuda",
|
|
||||||
"@help": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"messages": "Mensagens",
|
|
||||||
"@messages": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"reason": "Razão",
|
|
||||||
"@reason": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"privacy": "Privacidade",
|
|
||||||
"@privacy": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"openCamera": "Abrir câmara",
|
|
||||||
"@openCamera": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"settings": "Configurações",
|
|
||||||
"@settings": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"tuesday": "terça-feira",
|
|
||||||
"@tuesday": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"logout": "Terminar sessão",
|
|
||||||
"@logout": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"search": "Pesquisar",
|
|
||||||
"@search": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"sunday": "domingo",
|
|
||||||
"@sunday": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"users": "Utilizadores",
|
|
||||||
"@users": {},
|
|
||||||
"close": "Fechar",
|
|
||||||
"@close": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"dateWithoutYear": "{day}-{month}",
|
|
||||||
"@dateWithoutYear": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {
|
|
||||||
"month": {},
|
|
||||||
"day": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"friday": "sexta-feira",
|
|
||||||
"@friday": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"thursday": "quinta-feira",
|
|
||||||
"@thursday": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,374 +0,0 @@
|
|||||||
{
|
|
||||||
"@@last_modified": "2021-08-14 12:41:09.895217",
|
|
||||||
"about": "පිළිබඳව",
|
|
||||||
"@about": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"accept": "පිළිගන්න",
|
|
||||||
"@accept": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"account": "ගිණුම",
|
|
||||||
"@account": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"accountInformation": "ගිණුමේ තොරතුරු",
|
|
||||||
"@accountInformation": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"addEmail": "වි-තැපෑල එකතු කරන්න",
|
|
||||||
"@addEmail": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"admin": "පරිපාලක",
|
|
||||||
"@admin": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"allChats": "සියලුම සංවාද",
|
|
||||||
"@allChats": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"alreadyHaveAnAccount": "දැනටමත් ගිණුමක් තිබේද?",
|
|
||||||
"@alreadyHaveAnAccount": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"anyoneCanJoin": "ඕනෑම කෙනෙකුට එක්විය හැකිය",
|
|
||||||
"@anyoneCanJoin": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"archive": "සංරක්ෂිතය",
|
|
||||||
"@archive": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"archivedRoom": "සංරක්ෂිත කාමරය",
|
|
||||||
"@archivedRoom": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"areGuestsAllowedToJoin": "ආගන්තුක පරිශීලකයින්ට එක්වීමට අවසර තිබේද",
|
|
||||||
"@areGuestsAllowedToJoin": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"areYouSure": "ඔබට විශ්වාසද?",
|
|
||||||
"@areYouSure": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"areYouSureYouWantToLogout": "ඔබට නික්මීමට අවශ්ය බව විශ්වාසද?",
|
|
||||||
"@areYouSureYouWantToLogout": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"audioPlayerPlay": "ධාවනය",
|
|
||||||
"@audioPlayerPlay": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"blockDevice": "උපාංගය අවහිර කරන්න",
|
|
||||||
"@blockDevice": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"cachedKeys": "යතුරු නිහිතගතයි",
|
|
||||||
"@cachedKeys": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"cancel": "අවලංගු කරන්න",
|
|
||||||
"@cancel": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"changeDeviceName": "උපාංගයේ නම වෙනස් කරන්න",
|
|
||||||
"@changeDeviceName": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"changePassword": "මුරපදය වෙනස් කරන්න",
|
|
||||||
"@changePassword": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"chat": "සංවාදය",
|
|
||||||
"@chat": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"chatBackup": "සංවාද උපස්ථය",
|
|
||||||
"@chatBackup": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"chatDetails": "සංවාදයේ විස්තර",
|
|
||||||
"@chatDetails": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"chats": "සංවාද",
|
|
||||||
"@chats": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"chooseAStrongPassword": "ශක්තිමත් මුරපදයක් තෝරන්න",
|
|
||||||
"@chooseAStrongPassword": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"chooseAUsername": "පරිශීලක නාමයක් තෝරන්න",
|
|
||||||
"@chooseAUsername": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"clearArchive": "සංරක්ෂිතය හිස් කරන්න",
|
|
||||||
"@clearArchive": {},
|
|
||||||
"close": "වසන්න",
|
|
||||||
"@close": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"commandHint_join": "දී ඇති කාමරයට එක්වන්න",
|
|
||||||
"@commandHint_join": {
|
|
||||||
"type": "text",
|
|
||||||
"description": "Usage hint for the command /join"
|
|
||||||
},
|
|
||||||
"commandHint_leave": "මෙම කාමරය හැරයන්න",
|
|
||||||
"@commandHint_leave": {
|
|
||||||
"type": "text",
|
|
||||||
"description": "Usage hint for the command /leave"
|
|
||||||
},
|
|
||||||
"commandInvalid": "විධානය වලංගු නොවේ",
|
|
||||||
"@commandInvalid": {
|
|
||||||
"type": "text"
|
|
||||||
},
|
|
||||||
"commandMissing": "{{command} විධානයක් නොවේ.",
|
|
||||||
"@commandMissing": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {
|
|
||||||
"command": {}
|
|
||||||
},
|
|
||||||
"description": "State that {command} is not a valid /command."
|
|
||||||
},
|
|
||||||
"compareEmojiMatch": "සසඳා බලා පහත දැක්වෙන ඉමොජි අනෙක් උපාංගයට නිසැකවම ගැලපෙන බවට වග බලා ගන්න:",
|
|
||||||
"@compareEmojiMatch": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"compareNumbersMatch": "සංසන්දනය කර පහත දැක්වෙන අංක අනෙක් උපාංගට නිසැකව ගැලපෙන බවට වග බලා ගන්න:",
|
|
||||||
"@compareNumbersMatch": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"confirm": "තහවුරු කරන්න",
|
|
||||||
"@confirm": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"connect": "සබඳින්න",
|
|
||||||
"@connect": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"connectionAttemptFailed": "සබැඳීමේ උත්සාහය අසාර්ථකයි",
|
|
||||||
"@connectionAttemptFailed": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"contactHasBeenInvitedToTheGroup": "සමූහය වෙත සබඳතාවයකට ආරාධනා කර ඇත",
|
|
||||||
"@contactHasBeenInvitedToTheGroup": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"copy": "පිටපත්",
|
|
||||||
"@copy": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"create": "සාදන්න",
|
|
||||||
"@create": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"createAccountNow": "දැන් ගිණුමක් සාදන්න",
|
|
||||||
"@createAccountNow": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"createNewGroup": "නව සමූහයක් සාදන්න",
|
|
||||||
"@createNewGroup": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"donate": "පරිත්යාග",
|
|
||||||
"@donate": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"encryption": "සංකේතාංකනය",
|
|
||||||
"@encryption": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"everythingReady": "සියල්ල සූදානම්!",
|
|
||||||
"@everythingReady": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"fontSize": "මුද්රණඅකුරේ ප්රමාණය",
|
|
||||||
"@fontSize": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"goToTheNewRoom": "නව කාමරයට යන්න",
|
|
||||||
"@goToTheNewRoom": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"joinRoom": "කාමරයට එක්වන්න",
|
|
||||||
"@joinRoom": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"keysCached": "යතුරු නිහිතගත යි",
|
|
||||||
"@keysCached": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"next": "ඊලඟ",
|
|
||||||
"@next": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"noPublicRoomsFound": "ප්රසිද්ධ කාමර හමු නොවිණි…",
|
|
||||||
"@noPublicRoomsFound": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"people": "මිනිසුන්",
|
|
||||||
"@people": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"publicGroups": "ප්රසිද්ධ සමූහ",
|
|
||||||
"@publicGroups": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"removeDevice": "උපාංගය ඉවත්කරන්න",
|
|
||||||
"@removeDevice": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"roomVersion": "කාමරයේ අනුවාදය",
|
|
||||||
"@roomVersion": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"savedFileAs": "ලෙස ගොනුව සුරකින්න {filename}",
|
|
||||||
"@savedFileAs": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {
|
|
||||||
"filename": {}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"saveFile": "ගොනුව සුරකින්න",
|
|
||||||
"@saveFile": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"saveFileToFolder": "ගොනුව මෙම බහාලුමට සුරකින්න",
|
|
||||||
"@saveFileToFolder": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"securityKey": "ආරක්ෂක යතුර",
|
|
||||||
"@securityKey": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"securityKeyLost": "ආරක්ෂක යතුර නැතිවුනාද?",
|
|
||||||
"@securityKeyLost": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"send": "යවන්න",
|
|
||||||
"@send": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"showPassword": "මුරපදය පෙන්වන්න",
|
|
||||||
"@showPassword": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"sunday": "ඉරිදා",
|
|
||||||
"@sunday": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"username": "පරිශීලක නාමය",
|
|
||||||
"@username": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"videoCall": "දෘශ්ය ඇමතුම",
|
|
||||||
"@videoCall": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"wallpaper": "බිතුපත",
|
|
||||||
"@wallpaper": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"warning": "අවවාදයයි!",
|
|
||||||
"@warning": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"wednesday": "බදාදා",
|
|
||||||
"@wednesday": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"writeAMessage": "පණිවිඩයක් ලියන්න…",
|
|
||||||
"@writeAMessage": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"yes": "ඔව්",
|
|
||||||
"@yes": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"you": "ඔබ",
|
|
||||||
"@you": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"yourOwnUsername": "ඔබට හිමි පරිශීලකනාමය",
|
|
||||||
"@yourOwnUsername": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"zoomIn": "විශාලනය",
|
|
||||||
"@zoomIn": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"zoomOut": "කුඩාලනය",
|
|
||||||
"@zoomOut": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@ -1,20 +1,20 @@
|
|||||||
{
|
{
|
||||||
"@@last_modified": "2021-08-14 12:41:09.826673",
|
"@@last_modified": "2021-08-14 12:41:09.826673",
|
||||||
"acceptedTheInvitation": "{username} அழைப்பை ஏற்றுக்கொண்டார்",
|
"acceptedTheInvitation": "{username} அழைப்பை ஏற்றுக்கொண்டார்",
|
||||||
"@acceptedTheInvitation": {
|
"@acceptedTheInvitation": {
|
||||||
"type": "text",
|
"type": "text",
|
||||||
"placeholders": {
|
"placeholders": {
|
||||||
"username": {}
|
"username": {}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"accept": "ஏற்றுக்கொள்",
|
||||||
|
"@accept": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
|
},
|
||||||
|
"about": "பற்றி",
|
||||||
|
"@about": {
|
||||||
|
"type": "text",
|
||||||
|
"placeholders": {}
|
||||||
}
|
}
|
||||||
},
|
}
|
||||||
"accept": "ஏற்றுக்கொள்",
|
|
||||||
"@accept": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
},
|
|
||||||
"about": "பற்றி",
|
|
||||||
"@about": {
|
|
||||||
"type": "text",
|
|
||||||
"placeholders": {}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
1
assets/l10n/intl_th.arb
Normal file
@ -0,0 +1 @@
|
|||||||
|
{}
|
||||||
|
Before Width: | Height: | Size: 212 KiB After Width: | Height: | Size: 146 KiB |
|
Before Width: | Height: | Size: 44 KiB |
|
Before Width: | Height: | Size: 6.2 KiB |
@ -7,11 +7,9 @@ are also published on it.
|
|||||||
|
|
||||||
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click it**.
|
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click it**.
|
||||||
|
|
||||||
{::nomarkdown}
|
<a href="fdroidrepos://fluffychat.im/repo/stable/repo/?fingerprint=5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07" >
|
||||||
<a href="fdroidrepos://fluffychat.im/repo/stable/repo/?fingerprint=8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB" >
|
|
||||||
<img src="qr-stable.svg" width="300" height="300"/>
|
<img src="qr-stable.svg" width="300" height="300"/>
|
||||||
</a>
|
</a>
|
||||||
{:/}
|
|
||||||
|
|
||||||
|
|
||||||
### If the QR-Code doesn't work:
|
### If the QR-Code doesn't work:
|
||||||
@ -24,11 +22,11 @@ If this still isn't working follow the next steps:
|
|||||||
2. Go to the `Settings` Tab in the Bottom bar
|
2. Go to the `Settings` Tab in the Bottom bar
|
||||||
3. Click the `Repositories` Action
|
3. Click the `Repositories` Action
|
||||||
4. Click on the plus sign at the top.
|
4. Click on the plus sign at the top.
|
||||||
5. Fill in `https://fluffychat.im/repo/stable/repo/` into the top field and `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB` in the bottom field.
|
5. Fill in `https://fluffychat.im/repo/stable/repo/` into the top field and `5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07` in the bottom field.
|
||||||
|
|
||||||
## What is the fingerprint?
|
## What is the fingerprint?
|
||||||
|
|
||||||
The fingerprint of the Repository is: `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB`
|
The fingerprint of the Repository is: `5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07`
|
||||||
|
|
||||||
# Nightly Repository
|
# Nightly Repository
|
||||||
|
|
||||||
@ -36,11 +34,9 @@ The fingerprint of the Repository is: `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3
|
|||||||
|
|
||||||
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click** it.
|
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click** it.
|
||||||
|
|
||||||
{::nomarkdown}
|
|
||||||
<a href="fdroidrepos://fluffychat.im/repo/nightly/repo/?fingerprint=21A469657300576478B623DF99D8EB889A80BCD939ACA60A4074741BEAEC397D" >
|
<a href="fdroidrepos://fluffychat.im/repo/nightly/repo/?fingerprint=21A469657300576478B623DF99D8EB889A80BCD939ACA60A4074741BEAEC397D" >
|
||||||
<img src="qr-nightly.svg" width="300" height="300"/>
|
<img src="qr-nightly.svg" width="300" height="300"/>
|
||||||
</a>
|
</a>
|
||||||
{:/}
|
|
||||||
|
|
||||||
|
|
||||||
### If the QR-Code doesn't work:
|
### If the QR-Code doesn't work:
|
||||||
|
|||||||
646
docs/index.html
@ -1,565 +1,119 @@
|
|||||||
<!DOCTYPE html>
|
<!DOCTYPE html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
|
<html>
|
||||||
|
|
||||||
<head>
|
<head>
|
||||||
<meta charset="UTF-8">
|
<meta charset="utf-8">
|
||||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
<title>FluffyChat Official Website</title>
|
||||||
<meta http-equiv="X-UA-Compatible" content="ie=edge">
|
<meta name="identifier-url" content="https://fluffychat.im" />
|
||||||
<title>FluffyChat - Official Website</title>
|
<meta name="title" content="FluffyChat Official Website" />
|
||||||
<meta name="description" content="A cute and secure chatclient for the matrix protocol">
|
<meta name="description" content="The cutest messenger in the Matrix network" />
|
||||||
<meta name="keywords"
|
<meta name="abstract" content="FluffyChat is the cutest messenger in the Matrix network" />
|
||||||
content="Fluffychat, Matrix, Web, Android, iOS, Desktop, Chat, Client, Chatclient, Matrix.org, Secure, E2EE, End to End, Encryption, End to End Encryption, F-Droid, Foss, FOSS, OpenSource, Free, Community, Open">
|
<meta name="keywords" content="FluffyChat, Matrix, Flutter, App" />
|
||||||
<script type="application/ld+json">
|
<meta name="author" content="Krille Fear" />
|
||||||
{
|
<meta name="revisit-after" content="15" />
|
||||||
"@context": "https://schema.org",
|
<meta name="language" content="EN" />
|
||||||
"@type": "MobileApplication",
|
<meta name="robots" content="All" />
|
||||||
"name": "Fluffychat",
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||||
"applicationCategory": "CommunicationApplication",
|
<link rel="icon" type="image/x-icon" href="favicon.png">
|
||||||
"countriesNotSupported": "fr",
|
<link href="tailwind.css" rel="stylesheet">
|
||||||
"operatingSystem": "ANDROID",
|
|
||||||
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
|
||||||
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
|
||||||
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
|
||||||
"author": {
|
|
||||||
"@type": "Person",
|
|
||||||
"callSign": "KrilleFear"
|
|
||||||
},
|
|
||||||
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
|
||||||
"offers": {
|
|
||||||
"@type": "Offer",
|
|
||||||
"price": "0",
|
|
||||||
"priceCurrency": "USD"
|
|
||||||
},
|
|
||||||
"aggregateRating": {
|
|
||||||
"@type": "AggregateRating",
|
|
||||||
"ratingValue": "4.5",
|
|
||||||
"ratingCount": "133"
|
|
||||||
},
|
|
||||||
"installUrl": "https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="application/ld+json">
|
|
||||||
{
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "MobileApplication",
|
|
||||||
"name": "Fluffychat",
|
|
||||||
"applicationCategory": "CommunicationApplication",
|
|
||||||
"countriesNotSupported": "fr",
|
|
||||||
"operatingSystem": "ANDROID",
|
|
||||||
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
|
||||||
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
|
||||||
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
|
||||||
"author": {
|
|
||||||
"@type": "Person",
|
|
||||||
"callSign": "KrilleFear"
|
|
||||||
},
|
|
||||||
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
|
||||||
"offers": {
|
|
||||||
"@type": "Offer",
|
|
||||||
"price": "0",
|
|
||||||
"priceCurrency": "USD"
|
|
||||||
},
|
|
||||||
"aggregateRating": {
|
|
||||||
"@type": "AggregateRating",
|
|
||||||
"ratingValue": "4.5",
|
|
||||||
"ratingCount": "133"
|
|
||||||
},
|
|
||||||
"installUrl": "https://f-droid.org/de/packages/chat.fluffy.fluffychat/"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="application/ld+json">
|
|
||||||
{
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "MobileApplication",
|
|
||||||
"name": "Fluffychat",
|
|
||||||
"applicationCategory": "CommunicationApplication",
|
|
||||||
"countriesNotSupported": "fr",
|
|
||||||
"operatingSystem": "IOS",
|
|
||||||
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
|
||||||
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
|
||||||
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
|
||||||
"author": {
|
|
||||||
"@type": "Person",
|
|
||||||
"callSign": "KrilleFear"
|
|
||||||
},
|
|
||||||
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
|
||||||
"offers": {
|
|
||||||
"@type": "Offer",
|
|
||||||
"price": "0",
|
|
||||||
"priceCurrency": "USD"
|
|
||||||
},
|
|
||||||
"aggregateRating": {
|
|
||||||
"@type": "AggregateRating",
|
|
||||||
"ratingValue": "4.4",
|
|
||||||
"ratingCount": "28"
|
|
||||||
},
|
|
||||||
"installUrl": "https://apps.apple.com/app/fluffychat/id1551469600"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="application/ld+json">
|
|
||||||
{
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "WebApplication",
|
|
||||||
"name": "Fluffychat",
|
|
||||||
"applicationCategory": "CommunicationApplication",
|
|
||||||
"countriesNotSupported": "fr",
|
|
||||||
"operatingSystem": "WEB",
|
|
||||||
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
|
||||||
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
|
||||||
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
|
||||||
"author": {
|
|
||||||
"@type": "Person",
|
|
||||||
"callSign": "KrilleFear"
|
|
||||||
},
|
|
||||||
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
|
||||||
"offers": {
|
|
||||||
"@type": "Offer",
|
|
||||||
"price": "0",
|
|
||||||
"priceCurrency": "USD"
|
|
||||||
},
|
|
||||||
"aggregateRating": {
|
|
||||||
"@type": "AggregateRating",
|
|
||||||
"ratingValue": "4.5",
|
|
||||||
"ratingCount": "133"
|
|
||||||
},
|
|
||||||
"url": "https://fluffychat.im/web",
|
|
||||||
"downloadUrl": "https://fluffychat.im/web",
|
|
||||||
"installUrl": "https://fluffychat.im/web"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="application/ld+json">
|
|
||||||
{
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "SoftwareApplication",
|
|
||||||
"name": "Fluffychat",
|
|
||||||
"applicationCategory": "CommunicationApplication",
|
|
||||||
"countriesNotSupported": "fr",
|
|
||||||
"operatingSystem": "LINUX",
|
|
||||||
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
|
||||||
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
|
||||||
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
|
||||||
"author": {
|
|
||||||
"@type": "Person",
|
|
||||||
"callSign": "KrilleFear"
|
|
||||||
},
|
|
||||||
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
|
||||||
"offers": {
|
|
||||||
"@type": "Offer",
|
|
||||||
"price": "0",
|
|
||||||
"priceCurrency": "USD"
|
|
||||||
},
|
|
||||||
"aggregateRating": {
|
|
||||||
"@type": "AggregateRating",
|
|
||||||
"ratingValue": "4.5",
|
|
||||||
"ratingCount": "133"
|
|
||||||
},
|
|
||||||
"downloadUrl": "https://snapcraft.io/fluffychat",
|
|
||||||
"installUrl": "https://snapcraft.io/fluffychat"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="application/ld+json">
|
|
||||||
{
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "SoftwareApplication",
|
|
||||||
"name": "Fluffychat",
|
|
||||||
"applicationCategory": "CommunicationApplication",
|
|
||||||
"countriesNotSupported": "fr",
|
|
||||||
"operatingSystem": "LINUX",
|
|
||||||
"releaseNotes": "https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md",
|
|
||||||
"screenshot": "https://gitlab.com/famedly/fluffychat/-/raw/main/docs/screenshots/mobile.png",
|
|
||||||
"softwareHelp": "https://gitlab.com/famedly/fluffychat/-/wikis/FAQ",
|
|
||||||
"author": {
|
|
||||||
"@type": "Person",
|
|
||||||
"callSign": "KrilleFear"
|
|
||||||
},
|
|
||||||
"license": "https://gitlab.com/famedly/fluffychat/-/blob/main/LICENSE",
|
|
||||||
"offers": {
|
|
||||||
"@type": "Offer",
|
|
||||||
"price": "0",
|
|
||||||
"priceCurrency": "USD"
|
|
||||||
},
|
|
||||||
"aggregateRating": {
|
|
||||||
"@type": "AggregateRating",
|
|
||||||
"ratingValue": "4.5",
|
|
||||||
"ratingCount": "133"
|
|
||||||
},
|
|
||||||
"downloadUrl": "https://flathub.org/apps/details/im.fluffychat.Fluffychat",
|
|
||||||
"installUrl": "https://flathub.org/apps/details/im.fluffychat.Fluffychat"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="application/ld+json">
|
|
||||||
{
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "WebSite",
|
|
||||||
"name": "FluffyChat - Official Website",
|
|
||||||
"url": "https://fluffychat.im",
|
|
||||||
"description": "A cute and secure chatclient for the matrix protocol",
|
|
||||||
"thumbnailUrl": "https://fluffychat.im/favicon.png",
|
|
||||||
"inLanguage": "de-de"
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<script type="application/ld+json">
|
|
||||||
{
|
|
||||||
"@context": "https://schema.org",
|
|
||||||
"@type": "BreadcrumbList",
|
|
||||||
"description": "Breadcrumbs list",
|
|
||||||
"name": "Breadcrumbs",
|
|
||||||
"itemListElement": [
|
|
||||||
{
|
|
||||||
"@type": "ListItem",
|
|
||||||
"item": {
|
|
||||||
"@id": "https://fluffychat.im",
|
|
||||||
"name": "Homepage"
|
|
||||||
},
|
|
||||||
"position": 1
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<link rel="icon" type="image/png" href="favicon.png">
|
|
||||||
<link rel="stylesheet" href="tailwind.css">
|
|
||||||
<!-- Animation CSS-->
|
|
||||||
<style>
|
<style>
|
||||||
@font-face {
|
@font-face {
|
||||||
font-family: Zen Kurenaido;
|
font-family: Zen Kurenaido;
|
||||||
src: url(ZenKurenaido-Regular.ttf);
|
src: url(ZenKurenaido-Regular.ttf);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------
|
|
||||||
* Generated by Animista
|
|
||||||
* w: http://animista.net, t: @cssanimista
|
|
||||||
* ---------------------------------------------- */
|
|
||||||
|
|
||||||
.slide-in-bottom {
|
|
||||||
-webkit-animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) both;
|
|
||||||
animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) both
|
|
||||||
}
|
|
||||||
|
|
||||||
.slide-in-bottom-h1 {
|
|
||||||
-webkit-animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .5s both;
|
|
||||||
animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .5s both
|
|
||||||
}
|
|
||||||
|
|
||||||
.slide-in-bottom-subtitle {
|
|
||||||
-webkit-animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .75s both;
|
|
||||||
animation: slide-in-bottom .5s cubic-bezier(.25, .46, .45, .94) .75s both
|
|
||||||
}
|
|
||||||
|
|
||||||
.fade-in {
|
|
||||||
-webkit-animation: fade-in 1.2s cubic-bezier(.39, .575, .565, 1.000) 1s both;
|
|
||||||
animation: fade-in 1.2s cubic-bezier(.39, .575, .565, 1.000) 1s both
|
|
||||||
}
|
|
||||||
|
|
||||||
.bounce-top-icons {
|
|
||||||
-webkit-animation: bounce-top .9s 1s both;
|
|
||||||
animation: bounce-top .9s 1s both
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes slide-in-bottom {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: translateY(1000px);
|
|
||||||
transform: translateY(1000px);
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-webkit-transform: translateY(0);
|
|
||||||
transform: translateY(0);
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes slide-in-bottom {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: translateY(1000px);
|
|
||||||
transform: translateY(1000px);
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-webkit-transform: translateY(0);
|
|
||||||
transform: translateY(0);
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes bounce-top {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: translateY(-45px);
|
|
||||||
transform: translateY(-45px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in;
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
24% {
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
-webkit-transform: translateY(-24px);
|
|
||||||
transform: translateY(-24px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
65% {
|
|
||||||
-webkit-transform: translateY(-12px);
|
|
||||||
transform: translateY(-12px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
82% {
|
|
||||||
-webkit-transform: translateY(-6px);
|
|
||||||
transform: translateY(-6px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
93% {
|
|
||||||
-webkit-transform: translateY(-4px);
|
|
||||||
transform: translateY(-4px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
25%,
|
|
||||||
55%,
|
|
||||||
75%,
|
|
||||||
87% {
|
|
||||||
-webkit-transform: translateY(0);
|
|
||||||
transform: translateY(0);
|
|
||||||
-webkit-animation-timing-function: ease-out;
|
|
||||||
animation-timing-function: ease-out
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-webkit-transform: translateY(0);
|
|
||||||
transform: translateY(0);
|
|
||||||
-webkit-animation-timing-function: ease-out;
|
|
||||||
animation-timing-function: ease-out;
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes bounce-top {
|
|
||||||
0% {
|
|
||||||
-webkit-transform: translateY(-45px);
|
|
||||||
transform: translateY(-45px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in;
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
24% {
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
|
|
||||||
40% {
|
|
||||||
-webkit-transform: translateY(-24px);
|
|
||||||
transform: translateY(-24px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
65% {
|
|
||||||
-webkit-transform: translateY(-12px);
|
|
||||||
transform: translateY(-12px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
82% {
|
|
||||||
-webkit-transform: translateY(-6px);
|
|
||||||
transform: translateY(-6px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
93% {
|
|
||||||
-webkit-transform: translateY(-4px);
|
|
||||||
transform: translateY(-4px);
|
|
||||||
-webkit-animation-timing-function: ease-in;
|
|
||||||
animation-timing-function: ease-in
|
|
||||||
}
|
|
||||||
|
|
||||||
25%,
|
|
||||||
55%,
|
|
||||||
75%,
|
|
||||||
87% {
|
|
||||||
-webkit-transform: translateY(0);
|
|
||||||
transform: translateY(0);
|
|
||||||
-webkit-animation-timing-function: ease-out;
|
|
||||||
animation-timing-function: ease-out
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
-webkit-transform: translateY(0);
|
|
||||||
transform: translateY(0);
|
|
||||||
-webkit-animation-timing-function: ease-out;
|
|
||||||
animation-timing-function: ease-out;
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@-webkit-keyframes fade-in {
|
|
||||||
0% {
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
@keyframes fade-in {
|
|
||||||
0% {
|
|
||||||
opacity: 0
|
|
||||||
}
|
|
||||||
|
|
||||||
100% {
|
|
||||||
opacity: 1
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
|
<body
|
||||||
|
class="flex flex-col items-center justify-center min-h-screen w-screen bg-gradient-to-t from-purple-200 to-blue-50 dark:from-gray-800 dark:to-slate-900 p-4"
|
||||||
|
style="font-family: 'Zen Kurenaido', sans-serif;">
|
||||||
|
<img src="favicon.png" class="h-10" />
|
||||||
|
<h1 class="flex text-4xl items-center mb-4">
|
||||||
|
<span style="color: #5625BA">Fluffy</span>
|
||||||
|
<span style="color: #41a2bc">Chat</span>
|
||||||
|
</h1>
|
||||||
|
<img src="screenshots/screenshots.png" class="sm:max-w-lg max-w-screen mb-8" />
|
||||||
|
|
||||||
<body class="leading-normal tracking-normal text-gray-900" style="font-family: 'Zen Kurenaido', sans-serif;">
|
<div class="max-w-lg mb-8 flex justify-center flex-wrap">
|
||||||
|
<a href="https://apps.apple.com/app/fluffychat/id1551469600"><img src="appstore-badge.png"
|
||||||
|
class="w-36 pr-2 mb-2 inline hover:scale-105 transition-transform"></a>
|
||||||
|
<a href="https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"><img src="google-play-badge.png"
|
||||||
<div class="h-screen pb-14 bg-right bg-cover" style="background-image:url('bg.svg');">
|
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline">
|
||||||
<!--Nav-->
|
</a><a href="https://f-droid.org/packages/chat.fluffy.fluffychat/"><img src="fdroid_button.png"
|
||||||
<div class="w-full container mx-auto p-6">
|
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline">
|
||||||
|
</a>
|
||||||
<div class="w-full flex items-center justify-between">
|
<a href="https://fluffychat.im/web">
|
||||||
<a class="flex items-center no-underline hover:no-underline font-bold text-2xl lg:text-4xl" href="#">
|
<img src="browser-badge.png" class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
|
||||||
<img src="favicon.png" class="h-8 fill-current text-indigo-600 pr-2" /> <span
|
<a href="https://snapcraft.io/fluffychat"><img
|
||||||
style="color: #5625BA">Fluffy</span><span style="color: #41a2bc">Chat</span>
|
src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg"
|
||||||
</a>
|
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
|
||||||
|
<a href="https://flathub.org/apps/details/im.fluffychat.Fluffychat"><img src="flathub-badge-en.png"
|
||||||
<div class="flex w-1/2 justify-end content-center">
|
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"></a>
|
||||||
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
</div>
|
||||||
href="https://matrix.to/#/#fluffychat:matrix.org">
|
|
||||||
<svg class="fill-current h-6" enable-background="new -91 49.217 56.693 56.693" id="Layer_1"
|
|
||||||
version="1.1" viewBox="-91 49.217 56.693 56.693" xml:space="preserve"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<path
|
|
||||||
d="M-38.3289,79.8244c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.5351,1.5264l-3.0737-9.1321l4.4169-1.4866 c2.2362-0.7526,3.4388-3.1756,2.6861-5.4117c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.4168,1.4866l-1.4877-4.4201 c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861v0c-2.2362,0.7526-3.4388,3.1756-2.6861,5.4117l1.4877,4.4201l-9.3246,3.1385 l-1.4697-4.3666c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117l1.4697,4.3666 l-4.445,1.4961c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117v0c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861l4.445-1.4961 l3.0737,9.1321l-4.3268,1.4563c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861 l4.3268-1.4563l1.5778,4.6877c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5778-4.6877 l9.3246-3.1385l1.5598,4.6342c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5598-4.6342 l4.5351-1.5264C-38.7789,84.4835-37.5762,82.0606-38.3289,79.8244z M-65.6982,84.5288l-3.0737-9.1321l9.3246-3.1385l3.0737,9.1321 L-65.6982,84.5288z" />
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
|
||||||
href="https://twitter.com/KrilleFear">
|
|
||||||
<svg class="fill-current h-6" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 32 32">
|
|
||||||
<path
|
|
||||||
d="M30.063 7.313c-.813 1.125-1.75 2.125-2.875 2.938v.75c0 1.563-.188 3.125-.688 4.625a15.088 15.088 0 0 1-2.063 4.438c-.875 1.438-2 2.688-3.25 3.813a15.015 15.015 0 0 1-4.625 2.563c-1.813.688-3.75 1-5.75 1-3.25 0-6.188-.875-8.875-2.625.438.063.875.125 1.375.125 2.688 0 5.063-.875 7.188-2.5-1.25 0-2.375-.375-3.375-1.125s-1.688-1.688-2.063-2.875c.438.063.813.125 1.125.125.5 0 1-.063 1.5-.25-1.313-.25-2.438-.938-3.313-1.938a5.673 5.673 0 0 1-1.313-3.688v-.063c.813.438 1.688.688 2.625.688a5.228 5.228 0 0 1-1.875-2c-.5-.875-.688-1.813-.688-2.75 0-1.063.25-2.063.75-2.938 1.438 1.75 3.188 3.188 5.25 4.25s4.313 1.688 6.688 1.813a5.579 5.579 0 0 1 1.5-5.438c1.125-1.125 2.5-1.688 4.125-1.688s3.063.625 4.188 1.813a11.48 11.48 0 0 0 3.688-1.375c-.438 1.375-1.313 2.438-2.563 3.188 1.125-.125 2.188-.438 3.313-.875z">
|
|
||||||
</path>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
|
||||||
href="https://metalhead.club/@krille">
|
|
||||||
<svg class="fill-current h-6" viewBox="0 0 1000 1000" version="1.1"
|
|
||||||
xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"
|
|
||||||
xml:space="preserve"
|
|
||||||
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
|
||||||
<clipPath id="_clip1">
|
|
||||||
<rect x="33.6" y="-0.035" width="932.844" height="1000" />
|
|
||||||
</clipPath>
|
|
||||||
<g clip-path="url(#_clip1)">
|
|
||||||
<path
|
|
||||||
d="M946.586,599.455c-13.713,70.541 -122.816,147.742 -248.121,162.703c-65.341,7.796 -129.674,14.962 -198.275,11.815c-112.191,-5.139 -200.716,-26.776 -200.716,-26.776c0,10.92 0.673,21.319 2.02,31.044c14.586,110.711 109.787,117.344 199.967,120.436c91.021,3.114 172.068,-22.44 172.068,-22.44l3.74,82.281c0,0 -63.666,34.185 -177.079,40.473c-62.539,3.437 -140.192,-1.573 -230.636,-25.511c-196.158,-51.916 -229.893,-260.996 -235.055,-473.143c-1.573,-62.987 -0.603,-122.381 -0.603,-172.056c0,-216.931 142.142,-280.516 142.142,-280.516c71.672,-32.914 194.655,-46.755 322.508,-47.8l3.142,0c127.853,1.045 250.917,14.886 322.583,47.8c0,0 142.138,63.585 142.138,280.516c0,0 1.783,160.053 -19.823,271.174"
|
|
||||||
style="fill-rule:nonzero;" />
|
|
||||||
<path
|
|
||||||
d="M798.748,345.11l0,262.667l-104.07,0l0,-254.946c0,-53.743 -22.614,-81.021 -67.847,-81.021c-50.012,0 -75.077,32.359 -75.077,96.343l0,139.547l-103.457,0l0,-139.547c0,-63.984 -25.07,-96.343 -75.082,-96.343c-45.233,0 -67.847,27.278 -67.847,81.021l0,254.946l-104.07,0l0,-262.667c0,-53.683 13.669,-96.343 41.127,-127.904c28.314,-31.561 65.395,-47.741 111.425,-47.741c53.256,0 93.585,20.468 120.251,61.41l25.922,43.451l25.927,-43.451c26.66,-40.942 66.99,-61.41 120.251,-61.41c46.025,0 83.106,16.18 111.425,47.741c27.453,31.561 41.122,74.221 41.122,127.904"
|
|
||||||
style="fill:#fff;fill-rule:nonzero;" />
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
</a>
|
|
||||||
<a class="inline-block text-blue-300 no-underline hover:text-indigo-800 hover:text-underline text-center h-10 p-2 md:h-auto md:p-4"
|
|
||||||
href="https://ko-fi.com/krille">
|
|
||||||
<img class="w-10 hover:animate-bounce" src="Kofi_pixel_logo.png"/>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Main-->
|
|
||||||
<div class="container pt-8 px-6 mx-auto flex flex-wrap flex-col md:flex-row items-center">
|
|
||||||
|
|
||||||
<!--Left Col-->
|
|
||||||
<div class="flex flex-col w-full xl:w-2/5 justify-center lg:items-start overflow-y-hidden">
|
|
||||||
<h1
|
|
||||||
class="my-4 text-3xl md:text-5xl text-purple-800 font-bold leading-tight text-center md:text-left slide-in-bottom-h1">
|
|
||||||
Open. Nonprofit. Cute.</h1>
|
|
||||||
<p class="leading-normal text-base md:text-2xl mb-8 text-center md:text-left slide-in-bottom-subtitle">
|
|
||||||
Easy to use (<a class="underline hover:text-blue-700 transition-all"
|
|
||||||
href="https://matrix.org">matrix</a>) messenger. Secure and decentralized.</p>
|
|
||||||
|
|
||||||
<p class="text-blue-700 font-bold pb-4 text-center md:text-left fade-in">Mobile app:</p>
|
|
||||||
<div class="w-full flex justify-center md:justify-start pb-24 lg:pb-0 fade-in">
|
|
||||||
<a href="https://apps.apple.com/app/fluffychat/id1551469600"><img src="appstore-badge.png"
|
|
||||||
class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
|
||||||
<a href="https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"><img
|
|
||||||
src="google-play-badge.png" class="max-h-12 pr-2 mb-2 bounce-top-icons inline">
|
|
||||||
</a><a href="https://f-droid.org/de/packages/chat.fluffy.fluffychat/"><img src="fdroid_button.png"
|
|
||||||
class="max-h-12 pr-2 mb-2 bounce-top-icons inline">
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
<p class="text-blue-700 font-bold py-4 text-center md:text-left fade-in">Desktop app:</p>
|
|
||||||
<div class="w-full flex justify-center md:justify-start pb-24 lg:pb-0 fade-in">
|
|
||||||
<a href="https://fluffychat.im/web">
|
|
||||||
<img src="browser-badge.png" class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
|
||||||
<a href="https://snapcraft.io/fluffychat"><img
|
|
||||||
src="https://snapcraft.io/static/images/badges/en/snap-store-black.svg"
|
|
||||||
class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
|
||||||
<a href="https://flathub.org/apps/details/im.fluffychat.Fluffychat"><img src="flathub-badge-en.png"
|
|
||||||
class="max-h-12 pr-2 mb-2 bounce-top-icons inline"></a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Right Col-->
|
|
||||||
<div class="w-full xl:w-3/5 py-6 relative">
|
|
||||||
<img class="w-full mx-auto slide-in-bottom" src="screenshots/screenshots.png">
|
|
||||||
</div>
|
|
||||||
|
|
||||||
<!--Footer-->
|
|
||||||
<div class="w-full pt-16 pb-6 text-sm text-center md:text-left fade-in">
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat">Source code</a>
|
|
||||||
-
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat/-/blob/main/PRIVACY.md">Privacy</a>
|
|
||||||
-
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md">Changelog</a>
|
|
||||||
-
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800"
|
|
||||||
href="https://hosted.weblate.org/projects/fluffychat/">Translations</a>
|
|
||||||
-
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800"
|
|
||||||
href="https://gitlab.com/famedly/fluffychat/-/blob/main/docs/fdroid_repo.md">FluffyChat F-Droid repository</a>
|
|
||||||
-
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800"
|
|
||||||
href="https://liberapay.com/KrilleChritzelius/donate">Donate</a>
|
|
||||||
-
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800"
|
|
||||||
href="https://keys.mailvelope.com/pks/lookup?op=get&search=christian-pauly%40posteo.de">Contact</a>
|
|
||||||
-
|
|
||||||
<a class="text-gray-500 no-underline hover:text-purple-800" href="https://krillefear.gitlab.io">Created
|
|
||||||
by Krille Fear</a>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
</div>
|
|
||||||
|
|
||||||
|
<div class="flex mb-8 justify-center content-center">
|
||||||
|
<a rel="me"
|
||||||
|
class="inline-block text-indigo-500 no-underline hover:text-indigo-900 hover:scale-105 transition-all text-center h-auto p-4"
|
||||||
|
rel="me" href="https://mastodon.art/@krille">
|
||||||
|
<svg class="fill-current h-6" viewBox="0 0 1000 1000" version="1.1" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink" xml:space="preserve"
|
||||||
|
style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
|
||||||
|
<clipPath id="_clip1">
|
||||||
|
<rect x="33.6" y="-0.035" width="932.844" height="1000" />
|
||||||
|
</clipPath>
|
||||||
|
<g clip-path="url(#_clip1)">
|
||||||
|
<path
|
||||||
|
d="M946.586,599.455c-13.713,70.541 -122.816,147.742 -248.121,162.703c-65.341,7.796 -129.674,14.962 -198.275,11.815c-112.191,-5.139 -200.716,-26.776 -200.716,-26.776c0,10.92 0.673,21.319 2.02,31.044c14.586,110.711 109.787,117.344 199.967,120.436c91.021,3.114 172.068,-22.44 172.068,-22.44l3.74,82.281c0,0 -63.666,34.185 -177.079,40.473c-62.539,3.437 -140.192,-1.573 -230.636,-25.511c-196.158,-51.916 -229.893,-260.996 -235.055,-473.143c-1.573,-62.987 -0.603,-122.381 -0.603,-172.056c0,-216.931 142.142,-280.516 142.142,-280.516c71.672,-32.914 194.655,-46.755 322.508,-47.8l3.142,0c127.853,1.045 250.917,14.886 322.583,47.8c0,0 142.138,63.585 142.138,280.516c0,0 1.783,160.053 -19.823,271.174"
|
||||||
|
style="fill-rule:nonzero;" />
|
||||||
|
<path
|
||||||
|
d="M798.748,345.11l0,262.667l-104.07,0l0,-254.946c0,-53.743 -22.614,-81.021 -67.847,-81.021c-50.012,0 -75.077,32.359 -75.077,96.343l0,139.547l-103.457,0l0,-139.547c0,-63.984 -25.07,-96.343 -75.082,-96.343c-45.233,0 -67.847,27.278 -67.847,81.021l0,254.946l-104.07,0l0,-262.667c0,-53.683 13.669,-96.343 41.127,-127.904c28.314,-31.561 65.395,-47.741 111.425,-47.741c53.256,0 93.585,20.468 120.251,61.41l25.922,43.451l25.927,-43.451c26.66,-40.942 66.99,-61.41 120.251,-61.41c46.025,0 83.106,16.18 111.425,47.741c27.453,31.561 41.122,74.221 41.122,127.904"
|
||||||
|
style="fill:#fff;fill-rule:nonzero;" />
|
||||||
|
</g>
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a class="inline-block text-indigo-500 no-underline hover:text-indigo-900 hover:scale-105 transition-all text-center h-auto p-4"
|
||||||
|
href="https://matrix.to/#/#fluffychat:matrix.org">
|
||||||
|
<svg class="fill-current h-6" enable-background="new -91 49.217 56.693 56.693" id="Layer_1" version="1.1"
|
||||||
|
viewBox="-91 49.217 56.693 56.693" xml:space="preserve" xmlns="http://www.w3.org/2000/svg"
|
||||||
|
xmlns:xlink="http://www.w3.org/1999/xlink">
|
||||||
|
<path
|
||||||
|
d="M-38.3289,79.8244c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.5351,1.5264l-3.0737-9.1321l4.4169-1.4866 c2.2362-0.7526,3.4388-3.1756,2.6861-5.4117c-0.7526-2.2362-3.1756-3.4388-5.4117-2.6861l-4.4168,1.4866l-1.4877-4.4201 c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861v0c-2.2362,0.7526-3.4388,3.1756-2.6861,5.4117l1.4877,4.4201l-9.3246,3.1385 l-1.4697-4.3666c-0.7527-2.2362-3.1756-3.4388-5.4117-2.6861c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117l1.4697,4.3666 l-4.445,1.4961c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117v0c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861l4.445-1.4961 l3.0737,9.1321l-4.3268,1.4563c-2.2362,0.7527-3.4388,3.1756-2.6861,5.4117c0.7526,2.2362,3.1756,3.4388,5.4117,2.6861 l4.3268-1.4563l1.5778,4.6877c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5778-4.6877 l9.3246-3.1385l1.5598,4.6342c0.7527,2.2362,3.1756,3.4388,5.4117,2.6861c2.2362-0.7527,3.4388-3.1756,2.6861-5.4117l-1.5598-4.6342 l4.5351-1.5264C-38.7789,84.4835-37.5762,82.0606-38.3289,79.8244z M-65.6982,84.5288l-3.0737-9.1321l9.3246-3.1385l3.0737,9.1321 L-65.6982,84.5288z" />
|
||||||
|
</svg>
|
||||||
|
</a>
|
||||||
|
<a class="inline-block no-underline hover:scale-105 transition-all text-center h-auto p-4"
|
||||||
|
href="https://ko-fi.com/krille">
|
||||||
|
<img src="kofi_button_dark.png" class="h-6 fill-current" />
|
||||||
|
</a>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<!--Footer-->
|
||||||
|
<div class="w-full text-sm text-center max-w-lg">
|
||||||
|
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat">Source
|
||||||
|
code</a>
|
||||||
|
-
|
||||||
|
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat/-/blob/main/PRIVACY.md">Privacy</a>
|
||||||
|
-
|
||||||
|
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat/-/blob/main/CHANGELOG.md">Changelog</a>
|
||||||
|
-
|
||||||
|
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
||||||
|
href="https://hosted.weblate.org/projects/fluffychat/">Translations</a>
|
||||||
|
-
|
||||||
|
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
||||||
|
href="https://gitlab.com/famedly/fluffychat/-/blob/main/docs/fdroid_repo.md">FluffyChat F-Droid
|
||||||
|
repository</a>
|
||||||
|
-
|
||||||
|
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
||||||
|
href="https://keys.mailvelope.com/pks/lookup?op=get&search=christian-pauly%40posteo.de">Contact</a>
|
||||||
|
-
|
||||||
|
<a class="text-slate-700 dark:text-slate-200 no-underline hover:text-purple-800"
|
||||||
|
href="https://krillefear.gitlab.io">Created
|
||||||
|
by Krille Fear</a>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
BIN
docs/kofi_button_dark.png
Normal file
|
After Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 84 KiB After Width: | Height: | Size: 38 KiB |
BIN
fonts/Roboto/RobotoMono-Regular.ttf
Normal file
@ -1,49 +1,193 @@
|
|||||||
import 'dart:developer';
|
import 'package:fluffychat/config/setting_keys.dart';
|
||||||
|
import 'package:fluffychat/pages/chat/chat_view.dart';
|
||||||
|
import 'package:fluffychat/pages/chat_list/chat_list_body.dart';
|
||||||
|
import 'package:fluffychat/pages/chat_list/search_title.dart';
|
||||||
|
import 'package:fluffychat/pages/invitation_selection/invitation_selection_view.dart';
|
||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
import 'package:flutter_test/flutter_test.dart';
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
import 'package:hive_flutter/hive_flutter.dart';
|
||||||
import 'package:integration_test/integration_test.dart';
|
import 'package:integration_test/integration_test.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/main.dart' as app;
|
import 'package:fluffychat/main.dart' as app;
|
||||||
|
import 'package:shared_preferences/shared_preferences.dart';
|
||||||
|
|
||||||
|
import 'extensions/default_flows.dart';
|
||||||
|
import 'extensions/wait_for.dart';
|
||||||
import 'users.dart';
|
import 'users.dart';
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
IntegrationTestWidgetsFlutterBinding.ensureInitialized();
|
||||||
|
|
||||||
group('Integration Test', () {
|
group(
|
||||||
testWidgets('Test if the app starts', (WidgetTester tester) async {
|
'Integration Test',
|
||||||
app.main();
|
() {
|
||||||
await tester.pumpAndSettle();
|
setUpAll(
|
||||||
|
() async {
|
||||||
|
// this random dialog popping up is super hard to cover in tests
|
||||||
|
SharedPreferences.setMockInitialValues({
|
||||||
|
SettingKeys.showNoGoogle: false,
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
Hive.deleteFromDisk();
|
||||||
|
Hive.initFlutter();
|
||||||
|
} catch (_) {}
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
await Future.delayed(const Duration(seconds: 10));
|
testWidgets(
|
||||||
|
'Start app, login and logout',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
app.main();
|
||||||
|
await tester.ensureAppStartedHomescreen();
|
||||||
|
await tester.ensureLoggedOut();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
await tester.pumpAndSettle();
|
testWidgets(
|
||||||
|
'Login again',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
app.main();
|
||||||
|
await tester.ensureAppStartedHomescreen();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
expect(find.text('Connect'), findsOneWidget);
|
testWidgets(
|
||||||
|
'Start chat and send message',
|
||||||
|
(WidgetTester tester) async {
|
||||||
|
app.main();
|
||||||
|
await tester.ensureAppStartedHomescreen();
|
||||||
|
await tester.waitFor(find.byType(TextField));
|
||||||
|
await tester.enterText(find.byType(TextField), Users.user2.name);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
final input = find.byType(TextField);
|
await tester.scrollUntilVisible(
|
||||||
|
find.text('Chats').first,
|
||||||
|
500,
|
||||||
|
scrollable: find
|
||||||
|
.descendant(
|
||||||
|
of: find.byType(ChatListViewBody),
|
||||||
|
matching: find.byType(Scrollable),
|
||||||
|
)
|
||||||
|
.first,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.text('Chats'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.waitFor(find.byType(SearchTitle));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
expect(input, findsOneWidget);
|
await tester.scrollUntilVisible(
|
||||||
|
find.text(Users.user2.name).first,
|
||||||
|
500,
|
||||||
|
scrollable: find
|
||||||
|
.descendant(
|
||||||
|
of: find.byType(ChatListViewBody),
|
||||||
|
matching: find.byType(Scrollable),
|
||||||
|
)
|
||||||
|
.first,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.text(Users.user2.name).first);
|
||||||
|
|
||||||
await tester.enterText(input, homeserver);
|
try {
|
||||||
await tester.testTextInput.receiveAction(TextInputAction.done);
|
await tester.waitFor(
|
||||||
await tester.pumpAndSettle();
|
find.byType(ChatView),
|
||||||
|
timeout: const Duration(seconds: 5),
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
// in case the homeserver sends the username as search result
|
||||||
|
if (find.byIcon(Icons.send_outlined).evaluate().isNotEmpty) {
|
||||||
|
await tester.tap(find.byIcon(Icons.send_outlined));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// in case registration is allowed
|
await tester.waitFor(find.byType(ChatView));
|
||||||
try {
|
await tester.enterText(find.byType(TextField).last, 'Test');
|
||||||
await tester.tap(find.text('Login'));
|
await tester.pumpAndSettle();
|
||||||
|
try {
|
||||||
|
await tester.waitFor(find.byIcon(Icons.send_outlined));
|
||||||
|
await tester.tap(find.byIcon(Icons.send_outlined));
|
||||||
|
} catch (_) {
|
||||||
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||||
|
}
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.waitFor(find.text('Test'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
testWidgets('Spaces', (tester) async {
|
||||||
|
app.main();
|
||||||
|
await tester.ensureAppStartedHomescreen();
|
||||||
|
|
||||||
|
await tester.waitFor(find.byTooltip('Show menu'));
|
||||||
|
await tester.tap(find.byTooltip('Show menu'));
|
||||||
await tester.pumpAndSettle();
|
await tester.pumpAndSettle();
|
||||||
} catch (e) {
|
|
||||||
log('Registration is not allowed. Proceeding with login...');
|
|
||||||
}
|
|
||||||
await tester.pumpAndSettle();
|
|
||||||
|
|
||||||
final inputs = find.byType(TextField);
|
await tester.waitFor(find.byIcon(Icons.workspaces_outlined));
|
||||||
|
await tester.tap(find.byIcon(Icons.workspaces_outlined));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
await tester.enterText(inputs.first, Users.user1.name);
|
await tester.waitFor(find.byType(TextField));
|
||||||
await tester.enterText(inputs.last, Users.user1.password);
|
await tester.enterText(find.byType(TextField).last, 'Test Space');
|
||||||
await tester.testTextInput.receiveAction(TextInputAction.done);
|
await tester.pumpAndSettle();
|
||||||
});
|
|
||||||
});
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.waitFor(find.text('Invite contact'));
|
||||||
|
|
||||||
|
await tester.tap(find.text('Invite contact'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.waitFor(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(InvitationSelectionView),
|
||||||
|
matching: find.byType(TextField),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.enterText(
|
||||||
|
find.descendant(
|
||||||
|
of: find.byType(InvitationSelectionView),
|
||||||
|
matching: find.byType(TextField),
|
||||||
|
),
|
||||||
|
Users.user2.name,
|
||||||
|
);
|
||||||
|
|
||||||
|
await Future.delayed(const Duration(milliseconds: 250));
|
||||||
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||||
|
|
||||||
|
await Future.delayed(const Duration(milliseconds: 1000));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.tap(
|
||||||
|
find
|
||||||
|
.descendant(
|
||||||
|
of: find.descendant(
|
||||||
|
of: find.byType(InvitationSelectionView),
|
||||||
|
matching: find.byType(ListTile),
|
||||||
|
),
|
||||||
|
matching: find.text(Users.user2.name),
|
||||||
|
)
|
||||||
|
.last,
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.waitFor(find.maybeUppercaseText('Yes'));
|
||||||
|
await tester.tap(find.maybeUppercaseText('Yes'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.tap(find.byTooltip('Back'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.waitFor(find.text('Load 2 more participants'));
|
||||||
|
await tester.tap(find.text('Load 2 more participants'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
expect(find.text(Users.user2.name), findsOneWidget);
|
||||||
|
});
|
||||||
|
},
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
171
integration_test/extensions/default_flows.dart
Normal file
@ -0,0 +1,171 @@
|
|||||||
|
import 'dart:developer';
|
||||||
|
|
||||||
|
import 'package:fluffychat/pages/chat_list/chat_list_body.dart';
|
||||||
|
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart';
|
||||||
|
import 'package:flutter/material.dart';
|
||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
import '../users.dart';
|
||||||
|
import 'wait_for.dart';
|
||||||
|
|
||||||
|
extension DefaultFlowExtensions on WidgetTester {
|
||||||
|
Future<void> login() async {
|
||||||
|
final tester = this;
|
||||||
|
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.waitFor(find.text('Let\'s start'));
|
||||||
|
|
||||||
|
expect(find.text('Let\'s start'), findsOneWidget);
|
||||||
|
|
||||||
|
final input = find.byType(TextField);
|
||||||
|
|
||||||
|
expect(input, findsOneWidget);
|
||||||
|
|
||||||
|
// getting the placeholder in place
|
||||||
|
await tester.tap(find.byIcon(Icons.search));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.enterText(input, homeserver);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
// in case registration is allowed
|
||||||
|
// try {
|
||||||
|
await Future.delayed(const Duration(milliseconds: 50));
|
||||||
|
|
||||||
|
await tester.scrollUntilVisible(
|
||||||
|
find.text('Login'),
|
||||||
|
500,
|
||||||
|
scrollable: find.descendant(
|
||||||
|
of: find.byKey(const Key('ConnectPageListView')),
|
||||||
|
matching: find.byType(Scrollable).first,
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await tester.tap(find.text('Login'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
/*} catch (e) {
|
||||||
|
log('Registration is not allowed. Proceeding with login...');
|
||||||
|
}*/
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
await Future.delayed(const Duration(milliseconds: 50));
|
||||||
|
|
||||||
|
final inputs = find.byType(TextField);
|
||||||
|
|
||||||
|
await tester.enterText(inputs.first, Users.user1.name);
|
||||||
|
await tester.enterText(inputs.last, Users.user1.password);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.testTextInput.receiveAction(TextInputAction.done);
|
||||||
|
|
||||||
|
try {
|
||||||
|
// pumpAndSettle does not work in here as setState is called
|
||||||
|
// asynchronously
|
||||||
|
await tester.waitFor(
|
||||||
|
find.byType(LinearProgressIndicator),
|
||||||
|
timeout: const Duration(milliseconds: 1500),
|
||||||
|
skipPumpAndSettle: true,
|
||||||
|
);
|
||||||
|
} catch (_) {
|
||||||
|
// in case the input action does not work on the desired platform
|
||||||
|
if (find.text('Login').evaluate().isNotEmpty) {
|
||||||
|
await tester.tap(find.text('Login'));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
} catch (_) {
|
||||||
|
// may fail because of ongoing animation below dialog
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.waitFor(
|
||||||
|
find.byType(ChatListViewBody),
|
||||||
|
skipPumpAndSettle: true,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// ensure PushProvider check passes
|
||||||
|
Future<void> acceptPushWarning() async {
|
||||||
|
final tester = this;
|
||||||
|
|
||||||
|
final matcher = find.maybeUppercaseText('Do not show again');
|
||||||
|
|
||||||
|
try {
|
||||||
|
await tester.waitFor(matcher, timeout: const Duration(seconds: 5));
|
||||||
|
|
||||||
|
// the FCM push error dialog to be handled...
|
||||||
|
await tester.tap(matcher);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
} catch (_) {}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> ensureLoggedOut() async {
|
||||||
|
final tester = this;
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
if (find.byType(ChatListViewBody).evaluate().isNotEmpty) {
|
||||||
|
await tester.tap(find.byTooltip('Show menu'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.text('Settings'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.scrollUntilVisible(
|
||||||
|
find.text('Account'),
|
||||||
|
500,
|
||||||
|
scrollable: find.descendant(
|
||||||
|
of: find.byKey(const Key('SettingsListViewContent')),
|
||||||
|
matching: find.byType(Scrollable),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.text('Logout'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
await tester.tap(find.maybeUppercaseText('Yes'));
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
Future<void> ensureAppStartedHomescreen({
|
||||||
|
Duration timeout = const Duration(seconds: 20),
|
||||||
|
}) async {
|
||||||
|
final tester = this;
|
||||||
|
await tester.pumpAndSettle();
|
||||||
|
|
||||||
|
final homeserverPickerFinder = find.byType(HomeserverPicker);
|
||||||
|
final chatListFinder = find.byType(ChatListViewBody);
|
||||||
|
|
||||||
|
final end = DateTime.now().add(timeout);
|
||||||
|
|
||||||
|
log(
|
||||||
|
'Waiting for HomeserverPicker or ChatListViewBody...',
|
||||||
|
name: 'Test Runner',
|
||||||
|
);
|
||||||
|
do {
|
||||||
|
if (DateTime.now().isAfter(end)) {
|
||||||
|
throw Exception(
|
||||||
|
'Timed out waiting for HomeserverPicker or ChatListViewBody',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await pumpAndSettle();
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
} while (homeserverPickerFinder.evaluate().isEmpty &&
|
||||||
|
chatListFinder.evaluate().isEmpty);
|
||||||
|
|
||||||
|
if (homeserverPickerFinder.evaluate().isNotEmpty) {
|
||||||
|
log(
|
||||||
|
'Found HomeserverPicker, performing login.',
|
||||||
|
name: 'Test Runner',
|
||||||
|
);
|
||||||
|
await tester.login();
|
||||||
|
} else {
|
||||||
|
log(
|
||||||
|
'Found ChatListViewBody, skipping login.',
|
||||||
|
name: 'Test Runner',
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
await tester.acceptPushWarning();
|
||||||
|
}
|
||||||
|
}
|
||||||
49
integration_test/extensions/wait_for.dart
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
import 'package:flutter_test/flutter_test.dart';
|
||||||
|
|
||||||
|
/// Workaround for https://github.com/flutter/flutter/issues/88765
|
||||||
|
extension WaitForExtension on WidgetTester {
|
||||||
|
Future<void> waitFor(
|
||||||
|
Finder finder, {
|
||||||
|
Duration timeout = const Duration(seconds: 20),
|
||||||
|
bool skipPumpAndSettle = false,
|
||||||
|
}) async {
|
||||||
|
final end = DateTime.now().add(timeout);
|
||||||
|
|
||||||
|
do {
|
||||||
|
if (DateTime.now().isAfter(end)) {
|
||||||
|
throw Exception('Timed out waiting for $finder');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!skipPumpAndSettle) {
|
||||||
|
await pumpAndSettle();
|
||||||
|
}
|
||||||
|
await Future.delayed(const Duration(milliseconds: 100));
|
||||||
|
} while (finder.evaluate().isEmpty);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
extension MaybeUppercaseFinder on CommonFinders {
|
||||||
|
/// On Android some button labels are in uppercase while on iOS they
|
||||||
|
/// are not. This method tries both.
|
||||||
|
Finder maybeUppercaseText(
|
||||||
|
String text, {
|
||||||
|
bool findRichText = false,
|
||||||
|
bool skipOffstage = true,
|
||||||
|
}) {
|
||||||
|
try {
|
||||||
|
final finder = find.text(
|
||||||
|
text.toUpperCase(),
|
||||||
|
findRichText: findRichText,
|
||||||
|
skipOffstage: skipOffstage,
|
||||||
|
);
|
||||||
|
expect(finder, findsOneWidget);
|
||||||
|
return finder;
|
||||||
|
} catch (_) {
|
||||||
|
return find.text(
|
||||||
|
text,
|
||||||
|
findRichText: findRichText,
|
||||||
|
skipOffstage: skipOffstage,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,15 +1,25 @@
|
|||||||
import 'dart:io';
|
|
||||||
|
|
||||||
abstract class Users {
|
abstract class Users {
|
||||||
const Users._();
|
const Users._();
|
||||||
|
|
||||||
static final user1 = User(
|
static const user1 = User(
|
||||||
Platform.environment['USER1_NAME'] ?? 'alice',
|
String.fromEnvironment(
|
||||||
Platform.environment['USER1_PW'] ?? 'AliceInWonderland',
|
'USER1_NAME',
|
||||||
|
defaultValue: 'alice',
|
||||||
|
),
|
||||||
|
String.fromEnvironment(
|
||||||
|
'USER1_PW',
|
||||||
|
defaultValue: 'AliceInWonderland',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
static final user2 = User(
|
static const user2 = User(
|
||||||
Platform.environment['USER2_NAME'] ?? 'bob',
|
String.fromEnvironment(
|
||||||
Platform.environment['USER2_PW'] ?? 'JoWirSchaffenDas',
|
'USER2_NAME',
|
||||||
|
defaultValue: 'bob',
|
||||||
|
),
|
||||||
|
String.fromEnvironment(
|
||||||
|
'USER2_PW',
|
||||||
|
defaultValue: 'JoWirSchaffenDas',
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -20,5 +30,7 @@ class User {
|
|||||||
const User(this.name, this.password);
|
const User(this.name, this.password);
|
||||||
}
|
}
|
||||||
|
|
||||||
final homeserver =
|
const homeserver = 'http://${const String.fromEnvironment(
|
||||||
'http://${Platform.environment['HOMESERVER'] ?? 'localhost'}';
|
'HOMESERVER',
|
||||||
|
defaultValue: 'localhost',
|
||||||
|
)}';
|
||||||
|
|||||||
@ -3,7 +3,7 @@
|
|||||||
archiveVersion = 1;
|
archiveVersion = 1;
|
||||||
classes = {
|
classes = {
|
||||||
};
|
};
|
||||||
objectVersion = 51;
|
objectVersion = 54;
|
||||||
objects = {
|
objects = {
|
||||||
|
|
||||||
/* Begin PBXBuildFile section */
|
/* Begin PBXBuildFile section */
|
||||||
@ -286,10 +286,12 @@
|
|||||||
/* Begin PBXShellScriptBuildPhase section */
|
/* Begin PBXShellScriptBuildPhase section */
|
||||||
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
3B06AD1E1E4923F5004D2608 /* Thin Binary */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
inputPaths = (
|
inputPaths = (
|
||||||
|
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
|
||||||
);
|
);
|
||||||
name = "Thin Binary";
|
name = "Thin Binary";
|
||||||
outputPaths = (
|
outputPaths = (
|
||||||
@ -322,6 +324,7 @@
|
|||||||
};
|
};
|
||||||
9740EEB61CF901F6004384FC /* Run Script */ = {
|
9740EEB61CF901F6004384FC /* Run Script */ = {
|
||||||
isa = PBXShellScriptBuildPhase;
|
isa = PBXShellScriptBuildPhase;
|
||||||
|
alwaysOutOfDate = 1;
|
||||||
buildActionMask = 2147483647;
|
buildActionMask = 2147483647;
|
||||||
files = (
|
files = (
|
||||||
);
|
);
|
||||||
|
|||||||
@ -110,5 +110,7 @@
|
|||||||
</dict>
|
</dict>
|
||||||
<key>CADisableMinimumFrameDurationOnPhone</key>
|
<key>CADisableMinimumFrameDurationOnPhone</key>
|
||||||
<true/>
|
<true/>
|
||||||
|
<key>UIApplicationSupportsIndirectInputEvents</key>
|
||||||
|
<true/>
|
||||||
</dict>
|
</dict>
|
||||||
</plist>
|
</plist>
|
||||||
|
|||||||
@ -1,5 +1,5 @@
|
|||||||
app_identifier("im.fluffychat.app") # The bundle identifier of your app
|
app_identifier("im.fluffychat.app") # The bundle identifier of your app
|
||||||
apple_id("christian.pauly@wtal.de") # Your Apple email address
|
apple_id("christian-kussowski@posteo.de") # Your Apple email address
|
||||||
|
|
||||||
itc_team_id("122628977") # App Store Connect Team ID
|
itc_team_id("122628977") # App Store Connect Team ID
|
||||||
team_id("4NXF6Z997G") # Developer Portal Team ID
|
team_id("4NXF6Z997G") # Developer Portal Team ID
|
||||||
|
|||||||
@ -16,7 +16,7 @@ abstract class AppConfig {
|
|||||||
static const double messageFontSize = 15.75;
|
static const double messageFontSize = 15.75;
|
||||||
static const bool allowOtherHomeservers = true;
|
static const bool allowOtherHomeservers = true;
|
||||||
static const bool enableRegistration = true;
|
static const bool enableRegistration = true;
|
||||||
static const Color primaryColor = Color.fromARGB(255, 135, 103, 172);
|
static const Color primaryColor = Color(0xFF5625BA);
|
||||||
static const Color primaryColorLight = Color(0xFFCCBDEA);
|
static const Color primaryColorLight = Color(0xFFCCBDEA);
|
||||||
static const Color secondaryColor = Color(0xFF41a2bc);
|
static const Color secondaryColor = Color(0xFF41a2bc);
|
||||||
static String _privacyUrl =
|
static String _privacyUrl =
|
||||||
@ -24,6 +24,8 @@ abstract class AppConfig {
|
|||||||
static String get privacyUrl => _privacyUrl;
|
static String get privacyUrl => _privacyUrl;
|
||||||
static const String enablePushTutorial =
|
static const String enablePushTutorial =
|
||||||
'https://gitlab.com/famedly/fluffychat/-/wikis/Push-Notifications-without-Google-Services';
|
'https://gitlab.com/famedly/fluffychat/-/wikis/Push-Notifications-without-Google-Services';
|
||||||
|
static const String encryptionTutorial =
|
||||||
|
'https://gitlab.com/famedly/fluffychat/-/wikis/How-to-use-end-to-end-encryption-in-FluffyChat';
|
||||||
static const String appId = 'im.fluffychat.FluffyChat';
|
static const String appId = 'im.fluffychat.FluffyChat';
|
||||||
static const String appOpenUrlScheme = 'im.fluffychat';
|
static const String appOpenUrlScheme = 'im.fluffychat';
|
||||||
static String _webBaseUrl = 'https://fluffychat.im/web';
|
static String _webBaseUrl = 'https://fluffychat.im/web';
|
||||||
@ -31,6 +33,11 @@ abstract class AppConfig {
|
|||||||
static const String sourceCodeUrl = 'https://gitlab.com/famedly/fluffychat';
|
static const String sourceCodeUrl = 'https://gitlab.com/famedly/fluffychat';
|
||||||
static const String supportUrl =
|
static const String supportUrl =
|
||||||
'https://gitlab.com/famedly/fluffychat/issues';
|
'https://gitlab.com/famedly/fluffychat/issues';
|
||||||
|
static final Uri newIssueUrl = Uri(
|
||||||
|
scheme: 'https',
|
||||||
|
host: 'gitlab.com',
|
||||||
|
path: '/famedly/fluffychat/-/issues/new',
|
||||||
|
);
|
||||||
static const bool enableSentry = true;
|
static const bool enableSentry = true;
|
||||||
static const String sentryDns =
|
static const String sentryDns =
|
||||||
'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143';
|
'https://8591d0d863b646feb4f3dda7e5dcab38@o256755.ingest.sentry.io/5243143';
|
||||||
@ -68,8 +75,9 @@ abstract class AppConfig {
|
|||||||
colorSchemeSeed = Color(json['chat_color']);
|
colorSchemeSeed = Color(json['chat_color']);
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
Logs().w(
|
Logs().w(
|
||||||
'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"',
|
'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"',
|
||||||
e);
|
e,
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (json['application_name'] is String) {
|
if (json['application_name'] is String) {
|
||||||
|
|||||||
@ -9,7 +9,6 @@ import 'package:fluffychat/pages/chat_details/chat_details.dart';
|
|||||||
import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart';
|
import 'package:fluffychat/pages/chat_encryption_settings/chat_encryption_settings.dart';
|
||||||
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
import 'package:fluffychat/pages/chat_list/chat_list.dart';
|
||||||
import 'package:fluffychat/pages/chat_permissions_settings/chat_permissions_settings.dart';
|
import 'package:fluffychat/pages/chat_permissions_settings/chat_permissions_settings.dart';
|
||||||
import 'package:fluffychat/pages/connect/connect_page.dart';
|
|
||||||
import 'package:fluffychat/pages/device_settings/device_settings.dart';
|
import 'package:fluffychat/pages/device_settings/device_settings.dart';
|
||||||
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart';
|
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart';
|
||||||
import 'package:fluffychat/pages/invitation_selection/invitation_selection.dart';
|
import 'package:fluffychat/pages/invitation_selection/invitation_selection.dart';
|
||||||
@ -19,7 +18,6 @@ import 'package:fluffychat/pages/new_private_chat/new_private_chat.dart';
|
|||||||
import 'package:fluffychat/pages/new_space/new_space.dart';
|
import 'package:fluffychat/pages/new_space/new_space.dart';
|
||||||
import 'package:fluffychat/pages/settings/settings.dart';
|
import 'package:fluffychat/pages/settings/settings.dart';
|
||||||
import 'package:fluffychat/pages/settings_3pid/settings_3pid.dart';
|
import 'package:fluffychat/pages/settings_3pid/settings_3pid.dart';
|
||||||
import 'package:fluffychat/pages/settings_account/settings_account.dart';
|
|
||||||
import 'package:fluffychat/pages/settings_chat/settings_chat.dart';
|
import 'package:fluffychat/pages/settings_chat/settings_chat.dart';
|
||||||
import 'package:fluffychat/pages/settings_emotes/settings_emotes.dart';
|
import 'package:fluffychat/pages/settings_emotes/settings_emotes.dart';
|
||||||
import 'package:fluffychat/pages/settings_ignore_list/settings_ignore_list.dart';
|
import 'package:fluffychat/pages/settings_ignore_list/settings_ignore_list.dart';
|
||||||
@ -28,7 +26,6 @@ import 'package:fluffychat/pages/settings_notifications/settings_notifications.d
|
|||||||
import 'package:fluffychat/pages/settings_security/settings_security.dart';
|
import 'package:fluffychat/pages/settings_security/settings_security.dart';
|
||||||
import 'package:fluffychat/pages/settings_stories/settings_stories.dart';
|
import 'package:fluffychat/pages/settings_stories/settings_stories.dart';
|
||||||
import 'package:fluffychat/pages/settings_style/settings_style.dart';
|
import 'package:fluffychat/pages/settings_style/settings_style.dart';
|
||||||
import 'package:fluffychat/pages/sign_up/signup.dart';
|
|
||||||
import 'package:fluffychat/pages/story/story_page.dart';
|
import 'package:fluffychat/pages/story/story_page.dart';
|
||||||
import 'package:fluffychat/widgets/layouts/empty_page.dart';
|
import 'package:fluffychat/widgets/layouts/empty_page.dart';
|
||||||
import 'package:fluffychat/widgets/layouts/loading_view.dart';
|
import 'package:fluffychat/widgets/layouts/loading_view.dart';
|
||||||
@ -71,21 +68,25 @@ class AppRoutes {
|
|||||||
widget: const ChatDetails(),
|
widget: const ChatDetails(),
|
||||||
stackedRoutes: _chatDetailsRoutes,
|
stackedRoutes: _chatDetailsRoutes,
|
||||||
),
|
),
|
||||||
VWidget(path: ':roomid', widget: const Chat(), stackedRoutes: [
|
VWidget(
|
||||||
VWidget(
|
path: ':roomid',
|
||||||
path: 'encryption',
|
widget: const ChatPage(),
|
||||||
widget: const ChatEncryptionSettings(),
|
stackedRoutes: [
|
||||||
),
|
VWidget(
|
||||||
VWidget(
|
path: 'encryption',
|
||||||
path: 'invite',
|
widget: const ChatEncryptionSettings(),
|
||||||
widget: const InvitationSelection(),
|
),
|
||||||
),
|
VWidget(
|
||||||
VWidget(
|
path: 'invite',
|
||||||
path: 'details',
|
widget: const InvitationSelection(),
|
||||||
widget: const ChatDetails(),
|
),
|
||||||
stackedRoutes: _chatDetailsRoutes,
|
VWidget(
|
||||||
),
|
path: 'details',
|
||||||
]),
|
widget: const ChatDetails(),
|
||||||
|
stackedRoutes: _chatDetailsRoutes,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '/settings',
|
path: '/settings',
|
||||||
widget: const Settings(),
|
widget: const Settings(),
|
||||||
@ -94,6 +95,13 @@ class AppRoutes {
|
|||||||
VWidget(
|
VWidget(
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
widget: const Archive(),
|
widget: const Archive(),
|
||||||
|
stackedRoutes: [
|
||||||
|
VWidget(
|
||||||
|
path: ':roomid',
|
||||||
|
widget: const ChatPage(),
|
||||||
|
buildTransition: _dynamicTransition,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '/newprivatechat',
|
path: '/newprivatechat',
|
||||||
@ -164,14 +172,14 @@ class AppRoutes {
|
|||||||
VNester(
|
VNester(
|
||||||
path: ':roomid',
|
path: ':roomid',
|
||||||
widgetBuilder: (child) => SideViewLayout(
|
widgetBuilder: (child) => SideViewLayout(
|
||||||
mainView: const Chat(),
|
mainView: const ChatPage(),
|
||||||
sideView: child,
|
sideView: child,
|
||||||
),
|
),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
nestedRoutes: [
|
nestedRoutes: [
|
||||||
VWidget(
|
VWidget(
|
||||||
path: '',
|
path: '',
|
||||||
widget: const Chat(),
|
widget: const ChatPage(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
@ -220,13 +228,25 @@ class AppRoutes {
|
|||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
VWidget(
|
VNester(
|
||||||
path: '/archive',
|
path: '/archive',
|
||||||
widget: const TwoColumnLayout(
|
widgetBuilder: (child) => TwoColumnLayout(
|
||||||
mainView: Archive(),
|
mainView: const Archive(),
|
||||||
sideView: EmptyPage(),
|
sideView: child,
|
||||||
),
|
),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
|
nestedRoutes: [
|
||||||
|
VWidget(
|
||||||
|
path: '',
|
||||||
|
widget: const EmptyPage(),
|
||||||
|
buildTransition: _dynamicTransition,
|
||||||
|
),
|
||||||
|
VWidget(
|
||||||
|
path: ':roomid',
|
||||||
|
widget: const ChatPage(),
|
||||||
|
buildTransition: _dynamicTransition,
|
||||||
|
),
|
||||||
|
],
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -244,22 +264,6 @@ class AppRoutes {
|
|||||||
widget: const Login(),
|
widget: const Login(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
),
|
),
|
||||||
VWidget(
|
|
||||||
path: 'connect',
|
|
||||||
widget: const ConnectPage(),
|
|
||||||
buildTransition: _fadeTransition,
|
|
||||||
stackedRoutes: [
|
|
||||||
VWidget(
|
|
||||||
path: 'login',
|
|
||||||
widget: const Login(),
|
|
||||||
buildTransition: _fadeTransition,
|
|
||||||
),
|
|
||||||
VWidget(
|
|
||||||
path: 'signup',
|
|
||||||
widget: const SignupPage(),
|
|
||||||
buildTransition: _fadeTransition,
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
VWidget(
|
VWidget(
|
||||||
path: 'logs',
|
path: 'logs',
|
||||||
widget: const LogViewer(),
|
widget: const LogViewer(),
|
||||||
@ -326,37 +330,14 @@ class AppRoutes {
|
|||||||
],
|
],
|
||||||
),
|
),
|
||||||
VWidget(
|
VWidget(
|
||||||
path: 'account',
|
path: 'addaccount',
|
||||||
widget: const SettingsAccount(),
|
widget: const HomeserverPicker(),
|
||||||
buildTransition: _dynamicTransition,
|
buildTransition: _fadeTransition,
|
||||||
stackedRoutes: [
|
stackedRoutes: [
|
||||||
VWidget(
|
VWidget(
|
||||||
path: 'add',
|
path: 'login',
|
||||||
widget: const HomeserverPicker(),
|
widget: const Login(),
|
||||||
buildTransition: _fadeTransition,
|
buildTransition: _fadeTransition,
|
||||||
stackedRoutes: [
|
|
||||||
VWidget(
|
|
||||||
path: 'login',
|
|
||||||
widget: const Login(),
|
|
||||||
buildTransition: _fadeTransition,
|
|
||||||
),
|
|
||||||
VWidget(
|
|
||||||
path: 'connect',
|
|
||||||
widget: const ConnectPage(),
|
|
||||||
buildTransition: _fadeTransition,
|
|
||||||
stackedRoutes: [
|
|
||||||
VWidget(
|
|
||||||
path: 'login',
|
|
||||||
widget: const Login(),
|
|
||||||
buildTransition: _fadeTransition,
|
|
||||||
),
|
|
||||||
VWidget(
|
|
||||||
path: 'signup',
|
|
||||||
widget: const SignupPage(),
|
|
||||||
buildTransition: _fadeTransition,
|
|
||||||
),
|
|
||||||
]),
|
|
||||||
],
|
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -8,7 +8,6 @@ abstract class SettingKeys {
|
|||||||
static const String showDirectChatsInSpaces =
|
static const String showDirectChatsInSpaces =
|
||||||
'chat.fluffy.showDirectChatsInSpaces';
|
'chat.fluffy.showDirectChatsInSpaces';
|
||||||
static const String separateChatTypes = 'chat.fluffy.separateChatTypes';
|
static const String separateChatTypes = 'chat.fluffy.separateChatTypes';
|
||||||
static const String chatColor = 'chat.fluffy.chat_color';
|
|
||||||
static const String sentry = 'sentry';
|
static const String sentry = 'sentry';
|
||||||
static const String theme = 'theme';
|
static const String theme = 'theme';
|
||||||
static const String amoledEnabled = 'amoled_enabled';
|
static const String amoledEnabled = 'amoled_enabled';
|
||||||
|
|||||||
@ -9,7 +9,10 @@ import 'app_config.dart';
|
|||||||
abstract class FluffyThemes {
|
abstract class FluffyThemes {
|
||||||
static const double columnWidth = 360.0;
|
static const double columnWidth = 360.0;
|
||||||
|
|
||||||
static bool isColumnModeByWidth(double width) => width > columnWidth * 2 + 64;
|
static const double navRailWidth = 64.0;
|
||||||
|
|
||||||
|
static bool isColumnModeByWidth(double width) =>
|
||||||
|
width > columnWidth * 2 + navRailWidth;
|
||||||
|
|
||||||
static bool isColumnMode(BuildContext context) =>
|
static bool isColumnMode(BuildContext context) =>
|
||||||
isColumnModeByWidth(MediaQuery.of(context).size.width);
|
isColumnModeByWidth(MediaQuery.of(context).size.width);
|
||||||
@ -23,31 +26,47 @@ abstract class FluffyThemes {
|
|||||||
);
|
);
|
||||||
|
|
||||||
static var fallbackTextTheme = const TextTheme(
|
static var fallbackTextTheme = const TextTheme(
|
||||||
bodyText1: fallbackTextStyle,
|
bodyLarge: fallbackTextStyle,
|
||||||
bodyText2: fallbackTextStyle,
|
bodyMedium: fallbackTextStyle,
|
||||||
button: fallbackTextStyle,
|
labelLarge: fallbackTextStyle,
|
||||||
caption: fallbackTextStyle,
|
bodySmall: fallbackTextStyle,
|
||||||
overline: fallbackTextStyle,
|
labelSmall: fallbackTextStyle,
|
||||||
headline1: fallbackTextStyle,
|
displayLarge: fallbackTextStyle,
|
||||||
headline2: fallbackTextStyle,
|
displayMedium: fallbackTextStyle,
|
||||||
headline3: fallbackTextStyle,
|
displaySmall: fallbackTextStyle,
|
||||||
headline4: fallbackTextStyle,
|
headlineMedium: fallbackTextStyle,
|
||||||
headline5: fallbackTextStyle,
|
headlineSmall: fallbackTextStyle,
|
||||||
headline6: fallbackTextStyle,
|
titleLarge: fallbackTextStyle,
|
||||||
subtitle1: fallbackTextStyle,
|
titleMedium: fallbackTextStyle,
|
||||||
subtitle2: fallbackTextStyle,
|
titleSmall: fallbackTextStyle,
|
||||||
);
|
);
|
||||||
|
|
||||||
static ThemeData buildTheme(Brightness brightness,
|
static LinearGradient backgroundGradient(
|
||||||
[ColorScheme? colorScheme]) =>
|
BuildContext context,
|
||||||
|
int alpha,
|
||||||
|
) {
|
||||||
|
final colorScheme = Theme.of(context).colorScheme;
|
||||||
|
return LinearGradient(
|
||||||
|
begin: Alignment.topCenter,
|
||||||
|
colors: [
|
||||||
|
colorScheme.primaryContainer.withAlpha(alpha),
|
||||||
|
colorScheme.secondaryContainer.withAlpha(alpha),
|
||||||
|
colorScheme.tertiaryContainer.withAlpha(alpha),
|
||||||
|
colorScheme.primaryContainer.withAlpha(alpha),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static const Duration animationDuration = Duration(milliseconds: 250);
|
||||||
|
static const Curve animationCurve = Curves.easeInOut;
|
||||||
|
|
||||||
|
static ThemeData buildTheme(Brightness brightness, [Color? seed]) =>
|
||||||
ThemeData(
|
ThemeData(
|
||||||
visualDensity: VisualDensity.standard,
|
visualDensity: VisualDensity.standard,
|
||||||
useMaterial3: true,
|
useMaterial3: true,
|
||||||
brightness: brightness,
|
brightness: brightness,
|
||||||
colorSchemeSeed: AppConfig.colorSchemeSeed ??
|
colorSchemeSeed: seed ?? AppConfig.colorSchemeSeed,
|
||||||
colorScheme?.primary ??
|
textTheme: PlatformInfos.isDesktop || PlatformInfos.isWeb
|
||||||
AppConfig.chatColor,
|
|
||||||
textTheme: PlatformInfos.isDesktop
|
|
||||||
? brightness == Brightness.light
|
? brightness == Brightness.light
|
||||||
? Typography.material2018().black.merge(fallbackTextTheme)
|
? Typography.material2018().black.merge(fallbackTextTheme)
|
||||||
: Typography.material2018().white.merge(fallbackTextTheme)
|
: Typography.material2018().white.merge(fallbackTextTheme)
|
||||||
@ -58,8 +77,16 @@ abstract class FluffyThemes {
|
|||||||
dividerColor: brightness == Brightness.light
|
dividerColor: brightness == Brightness.light
|
||||||
? Colors.blueGrey.shade50
|
? Colors.blueGrey.shade50
|
||||||
: Colors.blueGrey.shade900,
|
: Colors.blueGrey.shade900,
|
||||||
inputDecorationTheme: const InputDecorationTheme(
|
popupMenuTheme: PopupMenuThemeData(
|
||||||
border: InputBorder.none,
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
inputDecorationTheme: InputDecorationTheme(
|
||||||
|
border: UnderlineInputBorder(
|
||||||
|
borderSide: BorderSide.none,
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
||||||
|
),
|
||||||
filled: true,
|
filled: true,
|
||||||
),
|
),
|
||||||
appBarTheme: AppBarTheme(
|
appBarTheme: AppBarTheme(
|
||||||
@ -72,10 +99,32 @@ abstract class FluffyThemes {
|
|||||||
statusBarBrightness: brightness,
|
statusBarBrightness: brightness,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
|
textButtonTheme: TextButtonThemeData(
|
||||||
|
style: TextButton.styleFrom(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
outlinedButtonTheme: OutlinedButtonThemeData(
|
||||||
|
style: OutlinedButton.styleFrom(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
dialogTheme: DialogTheme(
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
|
||||||
|
),
|
||||||
|
),
|
||||||
elevatedButtonTheme: ElevatedButtonThemeData(
|
elevatedButtonTheme: ElevatedButtonThemeData(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
padding: const EdgeInsets.all(16),
|
padding: const EdgeInsets.all(16),
|
||||||
textStyle: const TextStyle(fontSize: 16),
|
textStyle: const TextStyle(fontSize: 16),
|
||||||
|
shape: RoundedRectangleBorder(
|
||||||
|
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
|
|||||||
@ -3,7 +3,8 @@ import 'dart:math';
|
|||||||
|
|
||||||
import 'package:flutter/material.dart';
|
import 'package:flutter/material.dart';
|
||||||
|
|
||||||
import 'package:file_picker_cross/file_picker_cross.dart';
|
import 'package:collection/collection.dart';
|
||||||
|
import 'package:file_picker/file_picker.dart';
|
||||||
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
import 'package:future_loading_dialog/future_loading_dialog.dart';
|
||||||
import 'package:image_picker/image_picker.dart';
|
import 'package:image_picker/image_picker.dart';
|
||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
@ -12,12 +13,12 @@ import 'package:vrouter/vrouter.dart';
|
|||||||
|
|
||||||
import 'package:fluffychat/pages/add_story/add_story_view.dart';
|
import 'package:fluffychat/pages/add_story/add_story_view.dart';
|
||||||
import 'package:fluffychat/pages/add_story/invite_story_page.dart';
|
import 'package:fluffychat/pages/add_story/invite_story_page.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/matrix_file_extension.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_file_extension.dart';
|
||||||
import 'package:fluffychat/utils/resize_image.dart';
|
import 'package:fluffychat/utils/resize_image.dart';
|
||||||
import 'package:fluffychat/utils/story_theme_data.dart';
|
import 'package:fluffychat/utils/story_theme_data.dart';
|
||||||
import 'package:fluffychat/utils/string_color.dart';
|
import 'package:fluffychat/utils/string_color.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
import '../../utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
|
import '../../utils/matrix_sdk_extensions/client_stories_extension.dart';
|
||||||
|
|
||||||
class AddStoryPage extends StatefulWidget {
|
class AddStoryPage extends StatefulWidget {
|
||||||
const AddStoryPage({Key? key}) : super(key: key);
|
const AddStoryPage({Key? key}) : super(key: key);
|
||||||
@ -68,14 +69,15 @@ class AddStoryController extends State<AddStoryPage> {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void importMedia() async {
|
void importMedia() async {
|
||||||
final picked = await FilePickerCross.importFromStorage(
|
final picked = await FilePicker.platform.pickFiles(
|
||||||
type: FileTypeCross.image,
|
type: FileType.image,
|
||||||
|
withData: true,
|
||||||
);
|
);
|
||||||
final fileName = picked.fileName;
|
final file = picked?.files.firstOrNull;
|
||||||
if (fileName == null) return;
|
if (file == null) return;
|
||||||
final matrixFile = MatrixImageFile(
|
final matrixFile = MatrixImageFile(
|
||||||
bytes: picked.toUint8List(),
|
bytes: file.bytes!,
|
||||||
name: fileName,
|
name: file.name,
|
||||||
);
|
);
|
||||||
setState(() {
|
setState(() {
|
||||||
image = matrixFile;
|
image = matrixFile;
|
||||||
@ -88,14 +90,15 @@ class AddStoryController extends State<AddStoryPage> {
|
|||||||
);
|
);
|
||||||
if (picked == null) return;
|
if (picked == null) return;
|
||||||
final matrixFile = await showFutureLoadingDialog(
|
final matrixFile = await showFutureLoadingDialog(
|
||||||
context: context,
|
context: context,
|
||||||
future: () async {
|
future: () async {
|
||||||
final bytes = await picked.readAsBytes();
|
final bytes = await picked.readAsBytes();
|
||||||
return MatrixImageFile(
|
return MatrixImageFile(
|
||||||
bytes: bytes,
|
bytes: bytes,
|
||||||
name: picked.name,
|
name: picked.name,
|
||||||
);
|
);
|
||||||
});
|
},
|
||||||
|
);
|
||||||
|
|
||||||
setState(() {
|
setState(() {
|
||||||
image = matrixFile.result;
|
image = matrixFile.result;
|
||||||
|
|||||||
@ -6,7 +6,7 @@ import 'package:future_loading_dialog/future_loading_dialog.dart';
|
|||||||
import 'package:matrix/matrix.dart';
|
import 'package:matrix/matrix.dart';
|
||||||
|
|
||||||
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
import 'package:fluffychat/utils/localized_exception_extension.dart';
|
||||||
import 'package:fluffychat/utils/matrix_sdk_extensions.dart/client_stories_extension.dart';
|
import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart';
|
||||||
import 'package:fluffychat/widgets/avatar.dart';
|
import 'package:fluffychat/widgets/avatar.dart';
|
||||||
import 'package:fluffychat/widgets/matrix.dart';
|
import 'package:fluffychat/widgets/matrix.dart';
|
||||||
|
|
||||||
@ -92,34 +92,39 @@ class InviteStoryPageState extends State<InviteStoryPage> {
|
|||||||
const Divider(height: 1),
|
const Divider(height: 1),
|
||||||
Expanded(
|
Expanded(
|
||||||
child: FutureBuilder<List<User>>(
|
child: FutureBuilder<List<User>>(
|
||||||
future: loadContacts,
|
future: loadContacts,
|
||||||
builder: (context, snapshot) {
|
builder: (context, snapshot) {
|
||||||
final contacts = snapshot.data;
|
final contacts = snapshot.data;
|
||||||
if (contacts == null) {
|
if (contacts == null) {
|
||||||
final error = snapshot.error;
|
final error = snapshot.error;
|
||||||
if (error != null) {
|
if (error != null) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(error.toLocalizedString(context)));
|
child: Text(error.toLocalizedString(context)),
|
||||||
}
|
);
|
||||||
return const Center(
|
|
||||||
child: CircularProgressIndicator.adaptive());
|
|
||||||
}
|
}
|
||||||
_undecided = contacts.map((u) => u.id).toSet();
|
return const Center(
|
||||||
return ListView.builder(
|
child: CircularProgressIndicator.adaptive(),
|
||||||
itemCount: contacts.length,
|
|
||||||
itemBuilder: (context, i) => SwitchListTile.adaptive(
|
|
||||||
value: _invite.contains(contacts[i].id),
|
|
||||||
onChanged: (b) => setState(() => b
|
|
||||||
? _invite.add(contacts[i].id)
|
|
||||||
: _invite.remove(contacts[i].id)),
|
|
||||||
secondary: Avatar(
|
|
||||||
mxContent: contacts[i].avatarUrl,
|
|
||||||
name: contacts[i].calcDisplayname(),
|
|
||||||
),
|
|
||||||
title: Text(contacts[i].calcDisplayname()),
|
|
||||||
),
|
|
||||||
);
|
);
|
||||||
}),
|
}
|
||||||
|
_undecided = contacts.map((u) => u.id).toSet();
|
||||||
|
return ListView.builder(
|
||||||
|
itemCount: contacts.length,
|
||||||
|
itemBuilder: (context, i) => SwitchListTile.adaptive(
|
||||||
|
value: _invite.contains(contacts[i].id),
|
||||||
|
onChanged: (b) => setState(
|
||||||
|
() => b
|
||||||
|
? _invite.add(contacts[i].id)
|
||||||
|
: _invite.remove(contacts[i].id),
|
||||||
|
),
|
||||||
|
secondary: Avatar(
|
||||||
|
mxContent: contacts[i].avatarUrl,
|
||||||
|
name: contacts[i].calcDisplayname(),
|
||||||
|
),
|
||||||
|
title: Text(contacts[i].calcDisplayname()),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
),
|
||||||
),
|
),
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
|
|||||||
@ -21,11 +21,9 @@ class ArchiveController extends State<Archive> {
|
|||||||
Future<List<Room>> getArchive(BuildContext context) async {
|
Future<List<Room>> getArchive(BuildContext context) async {
|
||||||
final archive = this.archive;
|
final archive = this.archive;
|
||||||
if (archive != null) return archive;
|
if (archive != null) return archive;
|
||||||
return await Matrix.of(context).client.loadArchive();
|
return this.archive = await Matrix.of(context).client.loadArchive();
|
||||||
}
|
}
|
||||||
|
|
||||||
void forgetAction(int i) => setState(() => archive?.removeAt(i));
|
|
||||||
|
|
||||||
void forgetAllAction() async {
|
void forgetAllAction() async {
|
||||||
final archive = this.archive;
|
final archive = this.archive;
|
||||||
if (archive == null) return;
|
if (archive == null) return;
|
||||||
@ -44,7 +42,7 @@ class ArchiveController extends State<Archive> {
|
|||||||
context: context,
|
context: context,
|
||||||
future: () async {
|
future: () async {
|
||||||
while (archive.isNotEmpty) {
|
while (archive.isNotEmpty) {
|
||||||
Logs().v('Forget room ${archive.last.displayname}');
|
Logs().v('Forget room ${archive.last.getLocalizedDisplayname()}');
|
||||||
await archive.last.forget();
|
await archive.last.forget();
|
||||||
archive.removeLast();
|
archive.removeLast();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -21,10 +21,14 @@ class ArchiveView extends StatelessWidget {
|
|||||||
leading: const BackButton(),
|
leading: const BackButton(),
|
||||||
title: Text(L10n.of(context)!.archive),
|
title: Text(L10n.of(context)!.archive),
|
||||||
actions: [
|
actions: [
|
||||||
if (snapshot.hasData && archive != null && archive!.isNotEmpty)
|
if (snapshot.data?.isNotEmpty ?? false)
|
||||||
TextButton(
|
Padding(
|
||||||
onPressed: controller.forgetAllAction,
|
padding: const EdgeInsets.all(8.0),
|
||||||
child: Text(L10n.of(context)!.clearArchive),
|
child: TextButton.icon(
|
||||||
|
onPressed: controller.forgetAllAction,
|
||||||
|
label: Text(L10n.of(context)!.clearArchive),
|
||||||
|
icon: const Icon(Icons.cleaning_services_outlined),
|
||||||
|
),
|
||||||
)
|
)
|
||||||
],
|
],
|
||||||
),
|
),
|
||||||
@ -32,25 +36,27 @@ class ArchiveView extends StatelessWidget {
|
|||||||
builder: (BuildContext context) {
|
builder: (BuildContext context) {
|
||||||
if (snapshot.hasError) {
|
if (snapshot.hasError) {
|
||||||
return Center(
|
return Center(
|
||||||
child: Text(
|
child: Text(
|
||||||
L10n.of(context)!.oopsSomethingWentWrong,
|
L10n.of(context)!.oopsSomethingWentWrong,
|
||||||
textAlign: TextAlign.center,
|
textAlign: TextAlign.center,
|
||||||
));
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
if (!snapshot.hasData) {
|
if (!snapshot.hasData) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: CircularProgressIndicator.adaptive(strokeWidth: 2));
|
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
|
||||||
|
);
|
||||||
} else {
|
} else {
|
||||||
archive = snapshot.data;
|
archive = snapshot.data;
|
||||||
if (archive == null || archive!.isEmpty) {
|
if (archive == null || archive!.isEmpty) {
|
||||||
return const Center(
|
return const Center(
|
||||||
child: Icon(Icons.archive_outlined, size: 80));
|
child: Icon(Icons.archive_outlined, size: 80),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
return ListView.builder(
|
return ListView.builder(
|
||||||
itemCount: archive!.length,
|
itemCount: archive!.length,
|
||||||
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
itemBuilder: (BuildContext context, int i) => ChatListItem(
|
||||||
archive![i],
|
archive![i],
|
||||||
onForget: controller.forgetAction,
|
|
||||||
),
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|||||||
@ -125,9 +125,12 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
children: [
|
children: [
|
||||||
ListTile(
|
ListTile(
|
||||||
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
|
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
|
||||||
trailing: Icon(
|
trailing: CircleAvatar(
|
||||||
Icons.info_outlined,
|
backgroundColor: Colors.transparent,
|
||||||
color: Theme.of(context).colorScheme.primary,
|
child: Icon(
|
||||||
|
Icons.info_outlined,
|
||||||
|
color: Theme.of(context).colorScheme.primary,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
subtitle: Text(L10n.of(context)!.chatBackupDescription),
|
subtitle: Text(L10n.of(context)!.chatBackupDescription),
|
||||||
),
|
),
|
||||||
@ -136,10 +139,15 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
thickness: 1,
|
thickness: 1,
|
||||||
),
|
),
|
||||||
TextField(
|
TextField(
|
||||||
minLines: 4,
|
minLines: 2,
|
||||||
maxLines: 4,
|
maxLines: 4,
|
||||||
readOnly: true,
|
readOnly: true,
|
||||||
|
style: const TextStyle(fontFamily: 'RobotoMono'),
|
||||||
controller: TextEditingController(text: key),
|
controller: TextEditingController(text: key),
|
||||||
|
decoration: const InputDecoration(
|
||||||
|
contentPadding: EdgeInsets.all(16),
|
||||||
|
suffixIcon: Icon(Icons.key_outlined),
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
if (_supportsSecureStorage)
|
if (_supportsSecureStorage)
|
||||||
@ -233,12 +241,13 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
icon: const Icon(Icons.close),
|
icon: const Icon(Icons.close),
|
||||||
onPressed: Navigator.of(context).pop,
|
onPressed: Navigator.of(context).pop,
|
||||||
),
|
),
|
||||||
title: Text(L10n.of(context)!.unlockOldMessages),
|
title: Text(L10n.of(context)!.chatBackup),
|
||||||
),
|
),
|
||||||
body: Center(
|
body: Center(
|
||||||
child: ConstrainedBox(
|
child: ConstrainedBox(
|
||||||
constraints: const BoxConstraints(
|
constraints: const BoxConstraints(
|
||||||
maxWidth: FluffyThemes.columnWidth * 1.5),
|
maxWidth: FluffyThemes.columnWidth * 1.5,
|
||||||
|
),
|
||||||
child: ListView(
|
child: ListView(
|
||||||
padding: const EdgeInsets.all(16.0),
|
padding: const EdgeInsets.all(16.0),
|
||||||
children: [
|
children: [
|
||||||
@ -250,74 +259,85 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
color: Theme.of(context).colorScheme.primary,
|
color: Theme.of(context).colorScheme.primary,
|
||||||
),
|
),
|
||||||
subtitle: Text(
|
subtitle: Text(
|
||||||
L10n.of(context)!.pleaseEnterRecoveryKeyDescription),
|
L10n.of(context)!.pleaseEnterRecoveryKeyDescription,
|
||||||
|
),
|
||||||
),
|
),
|
||||||
const Divider(height: 32),
|
const Divider(height: 32),
|
||||||
TextField(
|
TextField(
|
||||||
minLines: 1,
|
minLines: 1,
|
||||||
maxLines: 1,
|
maxLines: 2,
|
||||||
autocorrect: false,
|
autocorrect: false,
|
||||||
readOnly: _recoveryKeyInputLoading,
|
readOnly: _recoveryKeyInputLoading,
|
||||||
autofillHints: _recoveryKeyInputLoading
|
autofillHints: _recoveryKeyInputLoading
|
||||||
? null
|
? null
|
||||||
: [AutofillHints.password],
|
: [AutofillHints.password],
|
||||||
controller: _recoveryKeyTextEditingController,
|
controller: _recoveryKeyTextEditingController,
|
||||||
|
style: const TextStyle(fontFamily: 'RobotoMono'),
|
||||||
decoration: InputDecoration(
|
decoration: InputDecoration(
|
||||||
hintText: 'Abc123 Def456',
|
contentPadding: const EdgeInsets.all(16),
|
||||||
labelText: L10n.of(context)!.recoveryKey,
|
hintStyle: TextStyle(
|
||||||
|
fontFamily:
|
||||||
|
Theme.of(context).textTheme.bodyLarge?.fontFamily,
|
||||||
|
),
|
||||||
|
hintText: L10n.of(context)!.recoveryKey,
|
||||||
errorText: _recoveryKeyInputError,
|
errorText: _recoveryKeyInputError,
|
||||||
),
|
),
|
||||||
),
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
style: ElevatedButton.styleFrom(
|
style: ElevatedButton.styleFrom(
|
||||||
foregroundColor:
|
foregroundColor:
|
||||||
Theme.of(context).colorScheme.onPrimary,
|
Theme.of(context).colorScheme.onPrimary,
|
||||||
backgroundColor: Theme.of(context).primaryColor,
|
backgroundColor: Theme.of(context).primaryColor,
|
||||||
),
|
|
||||||
icon: _recoveryKeyInputLoading
|
|
||||||
? const CircularProgressIndicator.adaptive()
|
|
||||||
: const Icon(Icons.lock_open_outlined),
|
|
||||||
label: Text(L10n.of(context)!.unlockOldMessages),
|
|
||||||
onPressed: _recoveryKeyInputLoading
|
|
||||||
? null
|
|
||||||
: () async {
|
|
||||||
setState(() {
|
|
||||||
_recoveryKeyInputError = null;
|
|
||||||
_recoveryKeyInputLoading = true;
|
|
||||||
});
|
|
||||||
try {
|
|
||||||
final key =
|
|
||||||
_recoveryKeyTextEditingController.text;
|
|
||||||
await bootstrap.newSsssKey!.unlock(
|
|
||||||
keyOrPassphrase: key,
|
|
||||||
);
|
|
||||||
Logs().d('SSSS unlocked');
|
|
||||||
await bootstrap
|
|
||||||
.client.encryption!.crossSigning
|
|
||||||
.selfSign(
|
|
||||||
keyOrPassphrase: key,
|
|
||||||
);
|
|
||||||
Logs().d('Successful elfsigned');
|
|
||||||
await bootstrap.openExistingSsss();
|
|
||||||
} catch (e, s) {
|
|
||||||
Logs().w('Unable to unlock SSSS', e, s);
|
|
||||||
setState(() => _recoveryKeyInputError =
|
|
||||||
L10n.of(context)!.oopsSomethingWentWrong);
|
|
||||||
} finally {
|
|
||||||
setState(
|
|
||||||
() => _recoveryKeyInputLoading = false);
|
|
||||||
}
|
|
||||||
}),
|
|
||||||
const SizedBox(height: 16),
|
|
||||||
Row(children: [
|
|
||||||
const Expanded(child: Divider()),
|
|
||||||
Padding(
|
|
||||||
padding: const EdgeInsets.all(12.0),
|
|
||||||
child: Text(L10n.of(context)!.or),
|
|
||||||
),
|
),
|
||||||
const Expanded(child: Divider()),
|
icon: _recoveryKeyInputLoading
|
||||||
]),
|
? const CircularProgressIndicator.adaptive()
|
||||||
|
: const Icon(Icons.lock_open_outlined),
|
||||||
|
label: Text(L10n.of(context)!.unlockOldMessages),
|
||||||
|
onPressed: _recoveryKeyInputLoading
|
||||||
|
? null
|
||||||
|
: () async {
|
||||||
|
setState(() {
|
||||||
|
_recoveryKeyInputError = null;
|
||||||
|
_recoveryKeyInputLoading = true;
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
final key =
|
||||||
|
_recoveryKeyTextEditingController.text;
|
||||||
|
await bootstrap.newSsssKey!.unlock(
|
||||||
|
keyOrPassphrase: key,
|
||||||
|
);
|
||||||
|
Logs().d('SSSS unlocked');
|
||||||
|
await bootstrap.client.encryption!.crossSigning
|
||||||
|
.selfSign(
|
||||||
|
keyOrPassphrase: key,
|
||||||
|
);
|
||||||
|
Logs().d('Successful elfsigned');
|
||||||
|
await bootstrap.openExistingSsss();
|
||||||
|
} catch (e, s) {
|
||||||
|
Logs().w('Unable to unlock SSSS', e, s);
|
||||||
|
setState(
|
||||||
|
() => _recoveryKeyInputError =
|
||||||
|
L10n.of(context)!.oopsSomethingWentWrong,
|
||||||
|
);
|
||||||
|
} finally {
|
||||||
|
setState(
|
||||||
|
() => _recoveryKeyInputLoading = false,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
const SizedBox(height: 16),
|
||||||
|
Row(
|
||||||
|
children: [
|
||||||
|
const Expanded(child: Divider()),
|
||||||
|
Padding(
|
||||||
|
padding: const EdgeInsets.all(12.0),
|
||||||
|
child: Text(L10n.of(context)!.or),
|
||||||
|
),
|
||||||
|
const Expanded(child: Divider()),
|
||||||
|
],
|
||||||
|
),
|
||||||
const SizedBox(height: 16),
|
const SizedBox(height: 16),
|
||||||
ElevatedButton.icon(
|
ElevatedButton.icon(
|
||||||
icon: const Icon(Icons.cast_connected_outlined),
|
icon: const Icon(Icons.cast_connected_outlined),
|
||||||
@ -394,11 +414,13 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
case BootstrapState.error:
|
case BootstrapState.error:
|
||||||
titleText = L10n.of(context)!.oopsSomethingWentWrong;
|
titleText = L10n.of(context)!.oopsSomethingWentWrong;
|
||||||
body = const Icon(Icons.error_outline, color: Colors.red, size: 40);
|
body = const Icon(Icons.error_outline, color: Colors.red, size: 40);
|
||||||
buttons.add(AdaptiveFlatButton(
|
buttons.add(
|
||||||
label: L10n.of(context)!.close,
|
AdaptiveFlatButton(
|
||||||
onPressed: () =>
|
label: L10n.of(context)!.close,
|
||||||
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
onPressed: () =>
|
||||||
));
|
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
||||||
|
),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
case BootstrapState.done:
|
case BootstrapState.done:
|
||||||
titleText = L10n.of(context)!.everythingReady;
|
titleText = L10n.of(context)!.everythingReady;
|
||||||
@ -409,11 +431,13 @@ class BootstrapDialogState extends State<BootstrapDialog> {
|
|||||||
Text(L10n.of(context)!.yourChatBackupHasBeenSetUp),
|
Text(L10n.of(context)!.yourChatBackupHasBeenSetUp),
|
||||||
],
|
],
|
||||||
);
|
);
|
||||||
buttons.add(AdaptiveFlatButton(
|
buttons.add(
|
||||||
label: L10n.of(context)!.close,
|
AdaptiveFlatButton(
|
||||||
onPressed: () =>
|
label: L10n.of(context)!.close,
|
||||||
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
onPressed: () =>
|
||||||
));
|
Navigator.of(context, rootNavigator: false).pop<bool>(false),
|
||||||
|
),
|
||||||
|
);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -75,7 +75,8 @@ class AddWidgetTileState extends State<AddWidgetTile> {
|
|||||||
Navigator.of(context).pop();
|
Navigator.of(context).pop();
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
ScaffoldMessenger.of(context).showSnackBar(
|
ScaffoldMessenger.of(context).showSnackBar(
|
||||||
SnackBar(content: Text(L10n.of(context)!.errorAddingWidget)));
|
SnackBar(content: Text(L10n.of(context)!.errorAddingWidget)),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||