Compare commits

...

134 Commits

Author SHA1 Message Date
Krille-chan
b4fcb5b0d9 chore: Use correct versions of adaptive_dialog 2023-07-14 08:02:47 +00:00
Krille
1911004d05
refactor: Update dependencies 2023-07-13 19:46:16 +09:00
Raatty
5d67564445
Added translation using Weblate (Greek) 2023-07-09 09:42:27 +02:00
Krille
be04c5a46e
design: Adjust open url dialog design a little bit 2023-07-07 12:10:07 +09:00
Farooq Karimi Zadeh
bd7a4c9dfb
Translated using Weblate (Persian)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-07-06 10:52:33 +02:00
Krille
10ee57722e
chore: Enable webrtc for linux again 2023-06-30 19:15:45 +09:00
Malin Errenst
ff5f7ab50e Merge branch 'malin/group-notification-channels' into 'main'
feat: Added grouping to message notification channels

See merge request famedly/fluffychat!1134
2023-06-30 07:55:24 +00:00
Krille
277885a61e
chore: Streamline background gradients 2023-06-29 16:56:15 +09:00
Malin Errenst
6633ebc376
feat: Added grouping to message notification channels 2023-06-29 09:36:08 +02:00
Krille-chan
b2d9986cd3 Merge branch 'braid/cute-events' into 'main'
fix: overflow in cute events

See merge request famedly/fluffychat!1132
2023-06-29 07:13:55 +00:00
Krille-chan
a0b9bb277f Merge branch 'braid/url-launch-copy' into 'main'
feat: add button to copy url in open dialog

See merge request famedly/fluffychat!1133
2023-06-29 07:13:30 +00:00
TheOneWithTheBraid
d381705cdd
feat: add button to copy url in open dialog
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-06-27 14:09:00 +02:00
3820d4264a
Translated using Weblate (Finnish)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fi/
2023-06-26 14:50:25 +02:00
Milo Ivir
cf4e2d3fad
Translated using Weblate (Croatian)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/hr/
2023-06-26 14:50:24 +02:00
josé m
002dc87577
Translated using Weblate (Galician)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-06-22 07:51:05 +02:00
The one with the braid
922e7ad0ff fix: overflow in cute events
Signed-off-by: The one with the braid <the-one@with-the-braid.cf>
2023-06-21 16:08:20 +02:00
Oğuz Ersen
5d7be8a672
Translated using Weblate (Turkish)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-06-20 19:50:49 +02:00
Krille-chan
431b357cfa Merge branch 'braid/allow-aarch64-failure' into 'main'
fix: allow aarch64 upload failure

See merge request famedly/fluffychat!1131
2023-06-19 10:35:58 +00:00
TheOneWithTheBraid
2938acf152 fix: allow aarch64 upload failure
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-06-19 12:27:07 +02:00
Krille
4127f70e4d
build: Change wakelock hotfix 2023-06-19 10:48:10 +02:00
xabirequejo
c07221cc12
Translated using Weblate (Basque)
Currently translated at 97.6% (536 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/eu/
2023-06-17 20:51:13 +02:00
Rex_sa
33b2f95e3f
Translated using Weblate (Arabic)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/
2023-06-16 11:52:28 +02:00
Ihor Hordiichuk
2a5cd9b218
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-06-15 10:51:43 +02:00
Linerly
a15fed034d
Translated using Weblate (Indonesian)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-06-13 14:47:59 +02:00
Riley
b9641ac021
Translated using Weblate (Romanian)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ro/
2023-06-13 14:47:59 +02:00
josé m
2145bd8846
Translated using Weblate (Galician)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-06-13 14:47:58 +02:00
Priit Jõerüüt
672b97b310
Translated using Weblate (Estonian)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-06-13 14:47:58 +02:00
Umoya NgoLwesihlanu
974da6ec90
Translated using Weblate (Arabic)
Currently translated at 100.0% (549 of 549 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/
2023-06-13 14:47:57 +02:00
Krille
f19bbcd010
refactor: More reliable request history/future timeline mechanism 2023-06-13 08:41:49 +02:00
Krille
a1468c92c8 Merge branch 'braid/allow-windows-failure' into 'main'
fix: allow windows upload job failure

See merge request famedly/fluffychat!1129
2023-06-12 05:19:41 +00:00
TheOneWithTheBraid
6dd125a087 fix: allow windows upload job failure
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-06-11 19:46:11 +02:00
Krille
842ecc4235
feat: New simplified login process with more prominent SSO and nicer layout 2023-06-11 18:04:31 +02:00
Krille
db66793d28
docs: Update mastodon link 2023-06-11 10:56:23 +02:00
Krille
324da027e9
builds: Bump version 2023-06-10 08:19:17 +02:00
DarkCoder15
f2f45e53a8
Translated using Weblate (Russian)
Currently translated at 99.2% (542 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ru/
2023-06-07 16:55:20 +02:00
Krille
cacab45fe3
chore: Follow up scrolldownbutton style 2023-06-04 11:14:06 +02:00
Krille
908d428220
design: Replace anime images with neutral cupertino icons 2023-06-03 18:27:26 +02:00
Krille
8a6d726b8c Merge branch 'braid/emoji-placeholder' into 'main'
fix: custom emote placeholder

See merge request famedly/fluffychat!1127
2023-06-03 16:05:59 +00:00
Krille
40275d3d14
fix: Scroll up and scroll down buttons in chat list 2023-06-03 17:59:48 +02:00
Krille
5039f1ba3b
refactor: Use AnimatedSize for FAB 2023-06-03 17:49:13 +02:00
Krille
299aac134d
feat: Display progress value for initial sync 2023-06-03 17:28:32 +02:00
TheOneWithTheBraid
044171c002 fix: custom emote placeholder
- place emote loading spinner in the position as the emote itself
- add key to preview in order to ensure proper states aligned

Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-06-02 18:39:47 +02:00
Krille
ec9155d8f0
chore: Update dependencies 2023-06-02 09:49:32 +02:00
Krille
221fe3edcc
builds: Update flutter table html 2023-06-01 13:01:58 +02:00
Krille
e166f17cae
refactor: Update flutter_html 2023-06-01 11:03:40 +02:00
Krille
640fe0d476
builds: Update flutter_html 2023-06-01 11:00:14 +02:00
Krille
3942de3222
fix: User pills 2023-05-31 15:52:51 +02:00
Krille
b00111381a
feat: Allow ruby tags in html 2023-05-31 13:05:06 +02:00
Krille
715dca561f
fix: Remove wrong rendered linebreak in html 2023-05-31 10:19:13 +02:00
Krille
44d7f61788
fix: Try to reload timeline on IOException 2023-05-31 09:22:50 +02:00
Krille
518739e29f
builds: Remove workaround for building linux arm64 2023-05-31 08:03:23 +02:00
Krille
06e6e9c5b1
chore: Follow up linkify inside html 2023-05-30 13:39:36 +02:00
Krille
17cfff153b Merge branch 'braid/macos' into 'main'
feat: update macOS build files

See merge request famedly/fluffychat!1121
2023-05-30 05:51:48 +00:00
Krille
9f224b9839 Merge branch 'braid/ci-fixes' into 'main'
fix: broken CI artifact uploads

See merge request famedly/fluffychat!1125
2023-05-30 05:51:28 +00:00
TheOneWithTheBraid
56e1bb6bfd fix: broken CI artifact uploads
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-05-29 19:19:28 +02:00
lauren n. liberda
6529ce0d0f
Translated using Weblate (Polish)
Currently translated at 99.2% (542 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/pl/
2023-05-28 11:48:20 +02:00
Rex_sa
81c7f7decd
Translated using Weblate (Arabic)
Currently translated at 100.0% (546 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ar/
2023-05-27 10:48:20 +02:00
Krille
85868cc0bd
chore: Follow up linkify in html message 2023-05-26 09:11:04 +02:00
Milo Ivir
1d0c842bad
Translated using Weblate (Croatian)
Currently translated at 100.0% (546 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/hr/
2023-05-24 22:48:59 +02:00
Krille
02bcc98037
chore: Disable linux webrtc 2023-05-24 21:02:13 +02:00
Krille
1a1c166ab0
chore: Enhance room pills 2023-05-24 08:23:06 +02:00
Krille
692d6042c5
chore: Ask for storage persistence 2023-05-23 15:21:38 +02:00
Krille
fa2ed930eb Revert "chore: Upgrade to Flutter 3.10.1"
This reverts commit d300cdb58f6a8be620471c53c7dd5920ba3f5c29
2023-05-23 13:02:28 +00:00
Krille
9785b0023c Revert "refactor: Update dependencies"
This reverts commit 2bb0dce7a15d4831eb30c39fc7ba5d863cbcd55e
2023-05-23 13:02:15 +00:00
Malin Errenst
313c94a4f1 Merge branch 'malin/flutter-3-10-1' into 'main'
chore: Upgrade to Flutter 3.10.1

See merge request famedly/fluffychat!1122
2023-05-23 07:44:51 +00:00
Krille
2bb0dce7a1
refactor: Update dependencies 2023-05-23 08:40:56 +02:00
Krille
b1785d4b8a
builds: Update file_picker to 5.3.0 2023-05-23 08:34:24 +02:00
Krille
3f15fa365f
chore: Follow up missing cache key 2023-05-23 08:32:27 +02:00
Krille
a56ebb245e
chore: do not humanize links 2023-05-23 08:22:34 +02:00
Malin Errenst
d300cdb58f
chore: Upgrade to Flutter 3.10.1 2023-05-22 21:33:14 +02:00
Krille
d88a1cd2d6
chore: Follow up img tag 2023-05-22 17:05:54 +02:00
Krille
3070b38d2e
chore: Follow up update matrix sdk 2023-05-22 16:30:04 +02:00
Krille
38db3b35aa
chore: Follow up html messages mxc images 2023-05-22 16:26:43 +02:00
Linerly
c4447adf8c
Translated using Weblate (Indonesian)
Currently translated at 100.0% (546 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-05-21 16:49:01 +02:00
Riley
0b91d3cecc
Translated using Weblate (Romanian)
Currently translated at 100.0% (546 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ro/
2023-05-21 16:49:01 +02:00
Eric
3b3d20f250
Translated using Weblate (Chinese (Simplified))
Currently translated at 97.6% (533 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/
2023-05-21 16:48:59 +02:00
Ihor Hordiichuk
0376e7f4b8
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (546 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-05-21 16:48:59 +02:00
josé m
77f43fbde0
Translated using Weblate (Galician)
Currently translated at 100.0% (546 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-05-21 16:48:59 +02:00
Priit Jõerüüt
e203508c42
Translated using Weblate (Estonian)
Currently translated at 100.0% (546 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-05-21 16:48:58 +02:00
José Muñoz
8b6745763a
Translated using Weblate (Spanish)
Currently translated at 77.1% (421 of 546 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/es/
2023-05-21 16:48:58 +02:00
Krille
8c4b2ade88
fix: Do not unnecessary request all members in public rooms 2023-05-20 08:21:33 +02:00
TheOneWithTheBraid
4e5f2ff05f fix: path of libolm
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-05-19 18:38:32 +02:00
TheOneWithTheBraid
fd1b62fc8d chore: update macOS icons and add build script
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-05-19 18:11:19 +02:00
Krille
f53d17eab7
chore: Readd support for html tables 2023-05-19 17:30:25 +02:00
TheOneWithTheBraid
c3b3f762eb feat: set display information correctly
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-05-19 14:11:27 +02:00
TheOneWithTheBraid
d288603c07 feat: clean up macOS build metadata
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-05-19 14:03:18 +02:00
TheOneWithTheBraid
e61682ef46 feat: update macOS build information for macOS Ventura
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-05-19 13:46:50 +02:00
TheOneWithTheBraid
3b228bb58b feat: update macOS build files
Signed-off-by: TheOneWithTheBraid <the-one@with-the-braid.cf>
2023-05-19 13:24:08 +02:00
Krille
b62c41ce57
chore: Follow up html styling 2023-05-19 08:14:48 +02:00
Krille
a4397e9cec
builds: Do not allow failure for linux x86 2023-05-18 11:02:32 +02:00
Krille
981d69706c
builds: Do not use verbose mode on building linux 2023-05-18 11:01:59 +02:00
Krille
0a4683d8a6
chore: Update flutter webrtc 2023-05-18 10:48:27 +02:00
Krille
43f6284ada
chore: Allow failure in build linux for now 2023-05-17 15:21:01 +02:00
Krille
8cf6297560
chore: Disable img for now in html messages 2023-05-17 15:20:40 +02:00
Krille
1f42d7dff0
chore: Add missing blockquote style 2023-05-17 13:25:39 +02:00
Krille
abbf18e1dc Merge branch 'krille/reimplement-flutter-matrix-html' into 'main'
refactor: Reimplement flutter matrix html locally

See merge request famedly/fluffychat!1119
2023-05-17 10:55:34 +00:00
Krille
102f3bba8e
refactor: Reimplement flutter matrix html locally 2023-05-17 12:26:59 +02:00
Krille
8faba7bdf2
chore: Remove macos_ui dependency 2023-05-16 19:21:37 +02:00
Krille
d41d21f8e1
chore: Remove webrtc override 2023-05-16 19:12:20 +02:00
Krille
298cd6245c Merge branch 'fail-on-curl-failures-during-build' into 'main'
change release curl calls to use --fail-with-body

Closes #1193

See merge request famedly/fluffychat!1110
2023-05-16 17:03:16 +00:00
Tim Flink
8bd88c4845 chore: change release curl calls to use --fail-with-body 2023-05-16 17:03:15 +00:00
Krille
e3bf76d8e2 Merge branch 'braid/update-fonts' into 'main'
chore: Update Roboto and Noto Emoji

See merge request famedly/fluffychat!1107
2023-05-16 16:56:09 +00:00
The one with the Braid
3445d5be21 refactor: Update Roboto and Noto Emoji 2023-05-16 16:56:09 +00:00
Krille
a838ba3000 Merge branch 'filenametolong' into 'main'
filename is too long and over the widget

See merge request famedly/fluffychat!1103
2023-05-16 16:55:19 +00:00
Skying
15b655413d fix: Too long file name cause a render overflow 2023-05-16 16:55:19 +00:00
Krille
2418c61498
chore: Follow up clean up 2023-05-16 18:51:01 +02:00
Krille
dfacbf9e32 Merge branch 'group-notif' into 'main'
Add Group Notifications

Closes #1175

See merge request famedly/fluffychat!1116
2023-05-16 16:50:20 +00:00
fbievan
85f5b69d6e feat: Add toggle to mute notifications from chat groups 2023-05-16 16:50:20 +00:00
Krille
08797da53d
feat: Implement new error reporting tool when critical features break like playing audio or video messages or opening a chat 2023-05-16 18:45:39 +02:00
Krille
d3bd2c3a08
builds: Change minsdkversion of Android from 16 to 19 2023-05-16 10:44:25 +02:00
Krille
1086c0e5cd Merge branch 'malin/improve-date-localization' into 'main'
Improve date localization

See merge request famedly/fluffychat!1118
2023-05-16 08:37:46 +00:00
Malin Errenst
60df0761a5
chore: Clean unused translations 2023-05-16 10:25:52 +02:00
Malin Errenst
650d878649
refactor: Use DateTime for weekday localization 2023-05-16 10:25:52 +02:00
Krille
06f399c76d
chore: Update dep ref 2023-05-16 09:35:27 +02:00
Krille
7c5b60474f
chore: Follow up update flutter matrix html 2023-05-16 09:12:13 +02:00
Krille
d81f92f2e2
builds: Linux with flutter 3.10 2023-05-15 19:14:03 +02:00
Krille
1a8038e51d
chore: Minor code clean up 2023-05-15 18:55:27 +02:00
Krille
54a6ce8391 Merge branch 'dart3' into 'main'
migrate to dart 3.0/flutter 3.10

Closes #1203

See merge request famedly/fluffychat!1114
2023-05-15 16:52:03 +00:00
lauren n. liberda
b1c38d766f builds: migrate to dart 3.0/flutter 3.10 2023-05-15 16:52:03 +00:00
Krille
f44e24aec1 Merge branch 'vrouter-context' into 'main'
fix "Unhandled Exception: VRouter.of(context) was called with a context which...

Closes #1163

See merge request famedly/fluffychat!1117
2023-05-15 16:37:51 +00:00
Lauren N. Liberda
325dcf901a
fix "Unhandled Exception: VRouter.of(context) was called with a context which does not contain a VRouter."
fixes #1163
2023-05-14 19:17:47 +02:00
Krille
77e1da8318
chore: Disable webrtc on linux again 2023-05-11 18:15:47 +02:00
Krille
b0a58d8524
perf: Use valuenotifier to not rebuild chatlist 2023-05-10 13:01:35 +02:00
Krille
623c3bfc2e
fix: Scroll down button 2023-05-09 15:14:35 +02:00
Krille
5cd6cf79a2
build: Remove dependency overwrite for ffi 2023-05-09 14:51:25 +02:00
Krille
e1d54fa992
build: Update dependencies 2023-05-09 14:47:05 +02:00
Krille
b1c481c4d1
fix: Broken arb file 2023-05-09 13:37:51 +02:00
Krille
64821e4ec5 Merge branch 'main' into 'main'
fix: Quick account switching

Closes #1186

See merge request famedly/fluffychat!1111
2023-05-08 13:26:59 +00:00
Krille
88585fb192
fix: Scrolldown button 2023-05-08 15:25:36 +02:00
JHansen
25f5d5f4fd Fix read reciepts 2023-05-08 12:02:15 +00:00
JHansen
d0d33ce2c8 Fix Quick account switching 2023-05-08 04:56:40 +00:00
Mæve Rey
32d8791fe9
Added translation using Weblate (Toki Pona) 2023-05-07 16:23:08 +02:00
Linerly
e76f42a706
Translated using Weblate (Indonesian)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-05-07 15:48:59 +02:00
josé m
32f4e471cf
Translated using Weblate (Galician)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-05-06 05:50:56 +02:00
158 changed files with 36050 additions and 35434 deletions

View File

@ -1,5 +1,5 @@
variables: variables:
FLUTTER_VERSION: 3.7.11 FLUTTER_VERSION: 3.10.0
image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION} image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
@ -19,7 +19,7 @@ code_analyze:
script: script:
- flutter pub get - flutter pub get
- dart run import_sorter:main --no-comments --exit-if-changed - dart run import_sorter:main --no-comments --exit-if-changed
- flutter format lib/ test/ --set-exit-if-changed - dart format lib/ test/ --set-exit-if-changed
- flutter analyze - flutter analyze
- git apply ./scripts/enable-android-google-services.patch - git apply ./scripts/enable-android-google-services.patch
- flutter pub get - flutter pub get
@ -31,7 +31,7 @@ code_analyze:
widget_test: widget_test:
stage: test stage: test
script: [ flutter test ] script: [flutter test]
# the basic integration test configuration testing FLOSS builds on Synapse # the basic integration test configuration testing FLOSS builds on Synapse
.integration_test: .integration_test:
@ -84,7 +84,6 @@ widget_test:
- docker - docker
- famedly - famedly
# integration tests for Linux builds # integration tests for Linux builds
### disabled because of Linux headless issues ### disabled because of Linux headless issues
.integration_test_linux: .integration_test_linux:
@ -98,7 +97,7 @@ widget_test:
- apt-get install -y clang cmake ninja-build pkg-config libgtk-3-dev liblzma-dev libsecret-1-dev libjsoncpp-dev - 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 --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 ) - 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: [ ] after_script: []
artifacts: artifacts:
# extending the default tests to test the Google-flavored builds # extending the default tests to test the Google-flavored builds
@ -144,7 +143,7 @@ release_mode_launches:
build_web: 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: script:
- flutter build web --release --verbose --source-maps - flutter build web --release --verbose --source-maps
artifacts: artifacts:
@ -195,7 +194,7 @@ build_windows:
build_android_debug: build_android_debug:
stage: build stage: build
script: [ flutter build apk --debug ] script: [flutter build apk --debug]
artifacts: artifacts:
when: on_success when: on_success
paths: paths:
@ -212,7 +211,7 @@ build_android_apk:
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: [ flutter build apk --release ] script: [flutter build apk --release]
artifacts: artifacts:
when: on_success when: on_success
paths: paths:
@ -229,7 +228,7 @@ deploy_playstore_internal:
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/release-playstore-beta.sh ] script: [./scripts/release-playstore-beta.sh]
artifacts: artifacts:
when: on_success when: on_success
paths: paths:
@ -284,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 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
- 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 -v ] script: [flutter build linux --release]
tags: tags:
- docker - docker
- famedly - famedly
@ -300,18 +299,9 @@ build_linux_x86:
build_linux_arm64: build_linux_arm64:
stage: build stage: build
before_script: before_script:
# Workaround from https://github.com/flutter/flutter/issues/116703#issuecomment-1403956612 - flutter upgrade $FLUTTER_VERSION --force
- rm -rf workaround116703 script: [flutter build linux --release]
- mkdir workaround116703 tags: [docker_arm64]
- cd workaround116703
- curl -O https://storage.googleapis.com/flutter_infra_release/releases/stable/linux/flutter_linux_${FLUTTER_VERSION}-stable.tar.xz
- tar -xvf flutter_linux_${FLUTTER_VERSION}-stable.tar.xz flutter/bin/cache/artifacts/engine/linux-x64/shader_lib
- mkdir -p /opt/flutter/bin/cache/artifacts/engine/linux-arm64
- cp -R flutter/bin/cache/artifacts/engine/linux-x64/shader_lib /opt/flutter/bin/cache/artifacts/engine/linux-arm64
- rm -rf flutter flutter_linux_${FLUTTER_VERSION}-stable.tar.xz
- cd ..
script: [ flutter build linux --release -v ]
tags: [ docker_arm64 ]
only: only:
- main - main
- tags - tags
@ -323,7 +313,7 @@ build_linux_arm64:
update_dependencies: update_dependencies:
stage: build stage: build
needs: [ ] needs: []
only: only:
- schedules - schedules
variables: variables:
@ -360,29 +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:
# workaround bug of Flutter engine - tar czf package.tar.gz -C build/web/ .
- tar czf package.tar.gz --ignore-failed-read -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
@ -392,15 +382,16 @@ 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
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/release-playstore.sh ] script: [./scripts/release-playstore.sh]
resource_group: playstore_release resource_group: playstore_release
only: only:
- tags - tags

View File

@ -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

View File

@ -1,3 +1,67 @@
## 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 ## v1.11.2
- Translated using Weblate (Croatian) (Milo Ivir) - Translated using Weblate (Croatian) (Milo Ivir)
- Translated using Weblate (Dutch) (Jelv) - Translated using Weblate (Dutch) (Jelv)

View File

@ -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

View File

@ -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
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 51 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 44 KiB

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
{} {}

View File

@ -71,11 +71,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Sala arxivada",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Accés dels usuaris convidats", "areGuestsAllowedToJoin": "Accés dels usuaris convidats",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -400,11 +395,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Signatura creuada activada",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Actiu actualment", "currentlyActive": "Actiu actualment",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -602,11 +592,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "divendres",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Des de la unió", "fromJoining": "Des de la unió",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -772,11 +757,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Les claus estan desades a la memòria cau",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} ha expulsat a {targetName}", "kicked": "{username} ha expulsat a {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -906,11 +886,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "dilluns",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Silencia el xat", "muteChat": "Silencia el xat",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1201,11 +1176,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "dissabte",
"@saturday": {
"type": "text",
"placeholders": {}
},
"security": "Seguretat", "security": "Seguretat",
"@security": { "@security": {
"type": "text", "type": "text",
@ -1394,11 +1364,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "diumenge",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "Sistema", "systemTheme": "Sistema",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1414,16 +1379,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Aquesta sala ha estat arxivada.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "dijous",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1445,11 +1400,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "dimarts",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "No disponible", "unavailable": "No disponible",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1610,11 +1560,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "dimecres",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Us hem enviat un missatge de correu electrònic", "weSentYouAnEmail": "Us hem enviat un missatge de correu electrònic",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -1801,8 +1746,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "El vostre id. dusuari:",
"@yourUserId": {},
"enableEncryption": "Activa el xifratge", "enableEncryption": "Activa el xifratge",
"@enableEncryption": { "@enableEncryption": {
"type": "text", "type": "text",
@ -2065,11 +2008,6 @@
"supportedVersions": {} "supportedVersions": {}
} }
}, },
"discover": "Descobreix",
"@discover": {
"type": "text",
"placeholders": {}
},
"editChatPermissions": "Edita els permisos del xat", "editChatPermissions": "Edita els permisos del xat",
"@editChatPermissions": { "@editChatPermissions": {
"type": "text", "type": "text",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

1
assets/l10n/intl_el.arb Normal file
View File

@ -0,0 +1 @@
{}

View File

@ -134,11 +134,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Archived Room",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Are guest users allowed to join", "areGuestsAllowedToJoin": "Are guest users allowed to join",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -388,8 +383,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "Your user ID:",
"@yourUserId": {},
"yourChatBackupHasBeenSetUp": "Your chat backup has been set up.", "yourChatBackupHasBeenSetUp": "Your chat backup has been set up.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"chatBackup": "Chat backup", "chatBackup": "Chat backup",
@ -633,11 +626,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Cross-signing on",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Currently active", "currentlyActive": "Currently active",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -723,6 +711,11 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"allRooms": "All Group Chats",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"discover": "Discover", "discover": "Discover",
"@discover": { "@discover": {
"type": "text", "type": "text",
@ -896,11 +889,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Friday",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "From joining", "fromJoining": "From joining",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -1091,11 +1079,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Keys are cached",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} kicked {targetName}", "kicked": "👞 {username} kicked {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1160,8 +1143,6 @@
"@dehydrate": {}, "@dehydrate": {},
"dehydrateWarning": "This action cannot be undone. Ensure you safely store the backup file.", "dehydrateWarning": "This action cannot be undone. Ensure you safely store the backup file.",
"@dehydrateWarning": {}, "@dehydrateWarning": {},
"dehydrateShare": "This is your private FluffyChat export. Ensure you don't lose it and keep it private.",
"@dehydrateShare": {},
"dehydrateTor": "TOR Users: Export session", "dehydrateTor": "TOR Users: Export session",
"@dehydrateTor": {}, "@dehydrateTor": {},
"dehydrateTorLong": "For TOR users, it is recommended to export the session before closing the window.", "dehydrateTorLong": "For TOR users, it is recommended to export the session before closing the window.",
@ -1236,17 +1217,11 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"noSearchResult": "No matching search results.",
"moderator": "Moderator", "moderator": "Moderator",
"@moderator": { "@moderator": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Monday",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Mute chat", "muteChat": "Mute chat",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1312,8 +1287,6 @@
}, },
"shareYourInviteLink": "Share your invite link", "shareYourInviteLink": "Share your invite link",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"typeInInviteLinkManually": "Type in invite link manually...",
"@typeInInviteLinkManually": {},
"scanQrCode": "Scan QR code", "scanQrCode": "Scan QR code",
"@scanQrCode": {}, "@scanQrCode": {},
"none": "None", "none": "None",
@ -1671,11 +1644,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Saturday",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Save file", "saveFile": "Save file",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1929,11 +1897,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Sunday",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Synchronizing… Please wait.", "synchronizingPleaseWait": "Synchronizing… Please wait.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1954,16 +1917,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "This room has been archived.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Thursday",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -2000,11 +1953,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Tuesday",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Unavailable", "unavailable": "Unavailable",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -2177,11 +2125,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Wednesday",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "We sent you an email", "weSentYouAnEmail": "We sent you an email",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2436,8 +2379,6 @@
"@stories": {}, "@stories": {},
"users": "Users", "users": "Users",
"@users": {}, "@users": {},
"enableAutoBackups": "Enable auto backups",
"@enableAutoBackups": {},
"unlockOldMessages": "Unlock old messages", "unlockOldMessages": "Unlock old messages",
"@unlockOldMessages": {}, "@unlockOldMessages": {},
"storeInSecureStorageDescription": "Store the recovery key in the secure storage of this device.", "storeInSecureStorageDescription": "Store the recovery key in the secure storage of this device.",
@ -2530,5 +2471,10 @@
"jumpToLastReadMessage": "Jump to last read message", "jumpToLastReadMessage": "Jump to last read message",
"readUpToHere": "Read up to here", "readUpToHere": "Read up to here",
"jump": "Jump", "jump": "Jump",
"openLinkInBrowser": "Open link in browser" "openLinkInBrowser": "Open link in browser",
"reportErrorDescription": "Oh no. Something went wrong. Please try again later. If you want, you can report the bug to the developers.",
"report": "report",
"signInWithPassword": "Sign in with password",
"continueWith": "Continue with:",
"pleaseTryAgainLaterOrChooseDifferentServer": "Please try again later or choose a different server."
} }

View File

@ -81,11 +81,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Arĥivita ĉambro",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Ĉu gastoj rajtas aliĝi", "areGuestsAllowedToJoin": "Ĉu gastoj rajtas aliĝi",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -533,11 +528,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Delegaj subskriboj estas ŝaltitaj",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Nun aktiva", "currentlyActive": "Nun aktiva",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -623,11 +613,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Trovi",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Prezenta nomo ŝanĝiĝis", "displaynameHasBeenChanged": "Prezenta nomo ŝanĝiĝis",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -794,11 +779,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Vendredo",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Ekde aliĝo", "fromJoining": "Ekde aliĝo",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -989,11 +969,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Ŝlosiloj estas kaŝmemoritaj",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} forpelis uzanton {targetName}", "kicked": "{username} forpelis uzanton {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1118,11 +1093,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Lundo",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Silentigi babilon", "muteChat": "Silentigi babilon",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1503,11 +1473,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Sabato",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Konservi dosieron", "saveFile": "Konservi dosieron",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1742,11 +1707,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Dimanĉo",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Spegulante… Bonvolu atendi.", "synchronizingPleaseWait": "Spegulante… Bonvolu atendi.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1767,16 +1727,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Ĉi tiu ĉambro arĥiviĝis.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Ĵaŭdo",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1813,11 +1763,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Mardo",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Nedisponeble", "unavailable": "Nedisponeble",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1988,11 +1933,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Merkredo",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Ni sendis retleteron al vi", "weSentYouAnEmail": "Ni sendis retleteron al vi",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",

File diff suppressed because it is too large Load Diff

View File

@ -82,11 +82,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Arhiveeritud jututuba",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Kas külalised võivad liituda", "areGuestsAllowedToJoin": "Kas külalised võivad liituda",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -544,11 +539,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Risttunnustamine on kasutusel",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Hetkel aktiivne", "currentlyActive": "Hetkel aktiivne",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -634,11 +624,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Avasta",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Kuvatav nimi on muudetud", "displaynameHasBeenChanged": "Kuvatav nimi on muudetud",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -805,11 +790,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Reede",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Alates liitumise hetkest", "fromJoining": "Alates liitumise hetkest",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -1000,11 +980,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Krüptovõtmed on puhverdatud",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} müksas kasutaja {targetName} välja", "kicked": "👞 {username} müksas kasutaja {targetName} välja",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1139,11 +1114,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Esmaspäev",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Summuta vestlus", "muteChat": "Summuta vestlus",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1537,11 +1507,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Laupäev",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Salvesta fail", "saveFile": "Salvesta fail",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1780,11 +1745,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Pühapäev",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Sünkroniseerin andmeid… Palun oota.", "synchronizingPleaseWait": "Sünkroniseerin andmeid… Palun oota.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1805,16 +1765,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "See jututuba on arhiveeritud.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Neljapäev",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1851,11 +1801,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Teisipäev",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Eemal", "unavailable": "Eemal",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -2026,11 +1971,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Kolmapäev",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Me saatsime sulle e-kirja", "weSentYouAnEmail": "Me saatsime sulle e-kirja",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2107,8 +2047,6 @@
"@addToSpace": {}, "@addToSpace": {},
"scanQrCode": "Skaneeri QR-koodi", "scanQrCode": "Skaneeri QR-koodi",
"@scanQrCode": {}, "@scanQrCode": {},
"typeInInviteLinkManually": "Sisesta kutse link käsitsi...",
"@typeInInviteLinkManually": {},
"shareYourInviteLink": "Jaga oma kutselinki", "shareYourInviteLink": "Jaga oma kutselinki",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"sendOnEnter": "Saada sõnum sisestusklahvi vajutusel", "sendOnEnter": "Saada sõnum sisestusklahvi vajutusel",
@ -2135,8 +2073,6 @@
"@link": {}, "@link": {},
"yourChatBackupHasBeenSetUp": "Sinu vestluste varundus on seadistatud.", "yourChatBackupHasBeenSetUp": "Sinu vestluste varundus on seadistatud.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"yourUserId": "Sinu kasutajatunnus:",
"@yourUserId": {},
"unverified": "Verifitseerimata", "unverified": "Verifitseerimata",
"@unverified": {}, "@unverified": {},
"repeatPassword": "Korda salasõna", "repeatPassword": "Korda salasõna",
@ -2374,8 +2310,6 @@
"@recoveryKey": {}, "@recoveryKey": {},
"users": "Kasutajad", "users": "Kasutajad",
"@users": {}, "@users": {},
"enableAutoBackups": "Võta kasutusele automaatne varundus",
"@enableAutoBackups": {},
"stories": "Jutustused", "stories": "Jutustused",
"@stories": {}, "@stories": {},
"storeInSecureStorageDescription": "Salvesta taastevõti selle seadme turvahoidlas.", "storeInSecureStorageDescription": "Salvesta taastevõti selle seadme turvahoidlas.",
@ -2402,8 +2336,6 @@
}, },
"dehydrate": "Ekspordi sessiooni teave ja kustuta nutiseadmest rakenduse andmed", "dehydrate": "Ekspordi sessiooni teave ja kustuta nutiseadmest rakenduse andmed",
"@dehydrate": {}, "@dehydrate": {},
"dehydrateShare": "See on sinu FluffyChat'i privaatsete andmete eksport. Palun hoia teda turvaliselt ja vaata, et sa seda ei kaotaks.",
"@dehydrateShare": {},
"dehydrateTor": "TOR'i kasutajad: Ekspordi sessioon", "dehydrateTor": "TOR'i kasutajad: Ekspordi sessioon",
"@dehydrateTor": {}, "@dehydrateTor": {},
"hydrateTor": "TOR'i kasutajatele: impordi viimati eksporditud sessiooni andmed", "hydrateTor": "TOR'i kasutajatele: impordi viimati eksporditud sessiooni andmed",
@ -2532,8 +2464,6 @@
"@deviceKeys": {}, "@deviceKeys": {},
"newSpaceDescription": "Kogukonnad võimaldavad sul koondada erinevaid vestlusi ning korraldada avalikku või privaatset ühistegevust.", "newSpaceDescription": "Kogukonnad võimaldavad sul koondada erinevaid vestlusi ning korraldada avalikku või privaatset ühistegevust.",
"@newSpaceDescription": {}, "@newSpaceDescription": {},
"noSearchResult": "Sobivaid otsingutulemusi ei leidu.",
"@noSearchResult": {},
"enterInviteLinkOrMatrixId": "Sisesta kutse link või Matrix ID...", "enterInviteLinkOrMatrixId": "Sisesta kutse link või Matrix ID...",
"@enterInviteLinkOrMatrixId": {}, "@enterInviteLinkOrMatrixId": {},
"letsStart": "Sõidame!", "letsStart": "Sõidame!",
@ -2560,5 +2490,25 @@
"jump": "Hüppa", "jump": "Hüppa",
"@jump": {}, "@jump": {},
"openLinkInBrowser": "Ava link veebibrauseris", "openLinkInBrowser": "Ava link veebibrauseris",
"@openLinkInBrowser": {} "@openLinkInBrowser": {},
"discover": "Otsi ja leia",
"@discover": {
"type": "text",
"placeholders": {}
},
"report": "teata",
"@report": {},
"allRooms": "Kõik vestlusrühmad",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"reportErrorDescription": "Oh appike! Midagi läks valesti. Palun proovi hiljem uuesti. Kui soovid, võid sellest veast arendajatele teatada.",
"@reportErrorDescription": {},
"continueWith": "Jätkamiseks kasuta:",
"@continueWith": {},
"signInWithPassword": "Logi sisse salasõnaga",
"@signInWithPassword": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "Palun proovi hiljem uuesti või muuda serveri nime.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {}
} }

View File

@ -62,11 +62,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Artxibatutako gela",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Ba al dute gonbidatutako erabiltzaileek bat egiteko baimenik?", "areGuestsAllowedToJoin": "Ba al dute gonbidatutako erabiltzaileek bat egiteko baimenik?",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -271,12 +266,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareEmojiMatch": "Konparatu eta egiaztatu ondorengo emojiak beste gailukoarekin bat datozela:", "compareEmojiMatch": "Konparatu ondorengo emojiak:",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Konparatu eta egiaztatu ondorengo zenbakiak beste gailukoarekin bat datozela:", "compareNumbersMatch": "Konparatu ondorengo zenbakiak:",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -337,11 +332,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Zeharkako sinadura gaituta dago",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Unean aktibo", "currentlyActive": "Unean aktibo",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -494,17 +484,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Ostirala", "fromJoining": "Bat egiteaz geroztik",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "sartzeaz",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"fromTheInvitation": "gonbidapenaz", "fromTheInvitation": "Gonbidapenaz geroztik",
"@fromTheInvitation": { "@fromTheInvitation": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -629,11 +614,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Gakoak katxean daude",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username}(e)k {targetName} kaleratu du", "kicked": "👞 {username}(e)k {targetName} kaleratu du",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -736,11 +716,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Astelehena",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Mututu berriketa", "muteChat": "Mututu berriketa",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -949,11 +924,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Larunbata",
"@saturday": {
"type": "text",
"placeholders": {}
},
"seenByUser": "{username}(e)k ikusi du", "seenByUser": "{username}(e)k ikusi du",
"@seenByUser": { "@seenByUser": {
"type": "text", "type": "text",
@ -1110,11 +1080,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Igandea",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "Sistemak darabilena", "systemTheme": "Sistemak darabilena",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1130,16 +1095,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Gela hau artxibatu da.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Osteguna",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1151,11 +1106,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Asteartea",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unbannedUser": "{username}(e)k {targetName} baimendu du", "unbannedUser": "{username}(e)k {targetName} baimendu du",
"@unbannedUser": { "@unbannedUser": {
"type": "text", "type": "text",
@ -1304,11 +1254,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Asteazkena",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"whoIsAllowedToJoinThisGroup": "Nork duen baimena talde honetara batzeko", "whoIsAllowedToJoinThisGroup": "Nork duen baimena talde honetara batzeko",
"@whoIsAllowedToJoinThisGroup": { "@whoIsAllowedToJoinThisGroup": {
"type": "text", "type": "text",
@ -1525,7 +1470,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"unreadChats": "{unreadCount, plural, =1{irakurri gabeko txat 1} other {{unreadCount} txat irakurri gabe}}", "unreadChats": "{unreadCount, plural, =1{irakurri gabeko txat 1} other {irakurri gabeko {unreadCount} txat}}",
"@unreadChats": { "@unreadChats": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1740,8 +1685,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "Zure erabiltzaile IDa:",
"@yourUserId": {},
"chatBackup": "Txataren babeskopia", "chatBackup": "Txataren babeskopia",
"@chatBackup": { "@chatBackup": {
"type": "text", "type": "text",
@ -1873,8 +1816,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"typeInInviteLinkManually": "Idatzi eskuz gonbidapen esteka…",
"@typeInInviteLinkManually": {},
"online": "Linean", "online": "Linean",
"@online": { "@online": {
"type": "text", "type": "text",
@ -2009,11 +1950,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Deskubritu",
"@discover": {
"type": "text",
"placeholders": {}
},
"emotePacks": "Emote sortak gelarako", "emotePacks": "Emote sortak gelarako",
"@emotePacks": { "@emotePacks": {
"type": "text", "type": "text",
@ -2064,7 +2000,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"noEncryptionForPublicRooms": "Zifraketa aktiba dezakezu soilik gela publikoa ez bada.", "noEncryptionForPublicRooms": "Zifraketa aktiba dezakezu soilik gelak publikoa izateari utzi badio.",
"@noEncryptionForPublicRooms": { "@noEncryptionForPublicRooms": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -2296,7 +2232,7 @@
"@widgetEtherpad": {}, "@widgetEtherpad": {},
"widgetJitsi": "Jitsi Meet", "widgetJitsi": "Jitsi Meet",
"@widgetJitsi": {}, "@widgetJitsi": {},
"widgetCustom": "Neurrira egindakoa", "widgetCustom": "Norberak ezarritakoa",
"@widgetCustom": {}, "@widgetCustom": {},
"widgetName": "Izena", "widgetName": "Izena",
"@widgetName": {}, "@widgetName": {},
@ -2407,10 +2343,6 @@
"@hydrateTorLong": {}, "@hydrateTorLong": {},
"noEmailWarning": "Sartu baliozko posta helbide bat. Bestela ezingo duzu pasahitza berrezarri. Hala ere nahi ez baduzu, sakatu berriro botoia aurrera egiteko.", "noEmailWarning": "Sartu baliozko posta helbide bat. Bestela ezingo duzu pasahitza berrezarri. Hala ere nahi ez baduzu, sakatu berriro botoia aurrera egiteko.",
"@noEmailWarning": {}, "@noEmailWarning": {},
"enableAutoBackups": "Gaitu babeskopia automatikoak",
"@enableAutoBackups": {},
"dehydrateShare": "Hau zure FluffyChaten esportazio pribatua da. Ez galdu eta ez partekatu inorekin.",
"@dehydrateShare": {},
"dehydrateTor": "TOR Erabiltzaileak: Esportatu saioa", "dehydrateTor": "TOR Erabiltzaileak: Esportatu saioa",
"@dehydrateTor": {}, "@dehydrateTor": {},
"hydrateTor": "TOR Erabiltzaileak: Inportatu esportatutako saioa", "hydrateTor": "TOR Erabiltzaileak: Inportatu esportatutako saioa",
@ -2498,7 +2430,7 @@
"@startFirstChat": {}, "@startFirstChat": {},
"newSpaceDescription": "Guneek txatak taldekatzea ahalbidetzen dute eta komunitate pribatu edo publikoak osatzea.", "newSpaceDescription": "Guneek txatak taldekatzea ahalbidetzen dute eta komunitate pribatu edo publikoak osatzea.",
"@newSpaceDescription": {}, "@newSpaceDescription": {},
"endToEndEncryption": "Puntuz puntuko zifraketa", "endToEndEncryption": "Ertzetik ertzerako zifratzea",
"@endToEndEncryption": {}, "@endToEndEncryption": {},
"disableEncryptionWarning": "Segurtasun arrazoiak direla-eta, ezin duzu lehendik zifratuta zegoen txat bateko zifraketa ezgaitu.", "disableEncryptionWarning": "Segurtasun arrazoiak direla-eta, ezin duzu lehendik zifratuta zegoen txat bateko zifraketa ezgaitu.",
"@disableEncryptionWarning": {}, "@disableEncryptionWarning": {},
@ -2519,6 +2451,57 @@
"@sorryThatsNotPossible": {}, "@sorryThatsNotPossible": {},
"reopenChat": "Ireki txata berriro", "reopenChat": "Ireki txata berriro",
"@reopenChat": {}, "@reopenChat": {},
"noSearchResult": "Ez da emaitzarik aurkitu.", "commandHint_googly": "Bidali begi dibertigarri batzuk",
"@noSearchResult": {} "@commandHint_googly": {},
"commandHint_cuddle": "Bidali besarkada goxoa",
"@commandHint_cuddle": {},
"googlyEyesContent": "{senderName}(e)k begi dibertigarri batzuk bidali dizkizu",
"@googlyEyesContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"allRooms": "Talde-txat guztiak",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"jumpToLastReadMessage": "Joan irakurritako azken mezura",
"@jumpToLastReadMessage": {},
"reportErrorDescription": "Ez! Zerbaitek huts egin du. Saiatu berriro geroago. Nahi izanez gero, eman garatzaileei errorearen berri.",
"@reportErrorDescription": {},
"cuddleContent": "{senderName}(e)k samurki besarkatu zaitu",
"@cuddleContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"readUpToHere": "Honaino irakurrita",
"@readUpToHere": {},
"discover": "Deskubritu",
"@discover": {
"type": "text",
"placeholders": {}
},
"fileHasBeenSavedAt": "Fitxategia {path}(e)n gorde da",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"jump": "Joan",
"@jump": {},
"openLinkInBrowser": "Ireki esteka nabigatzailean",
"@openLinkInBrowser": {},
"report": "eman berri",
"@report": {},
"signInWithPassword": "Hasi saioa pasahitzarekin",
"@signInWithPassword": {},
"continueWith": "Jarraitu honekin:",
"@continueWith": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "Saiatu geroago edo hautatu beste zerbitzari bat.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {}
} }

View File

@ -79,11 +79,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "اتاق بایگانی شده",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areYouSure": "مطمئن هستید؟", "areYouSure": "مطمئن هستید؟",
"@areYouSure": { "@areYouSure": {
"type": "text", "type": "text",
@ -647,11 +642,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "کشف کردن",
"@discover": {
"type": "text",
"placeholders": {}
},
"copy": "کپی", "copy": "کپی",
"@copy": { "@copy": {
"type": "text", "type": "text",
@ -682,8 +672,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "هويت‌ کاربری شما:",
"@yourUserId": {},
"commandHint_html": "متن با فرمت HTML بفرستید", "commandHint_html": "متن با فرمت HTML بفرستید",
"@commandHint_html": { "@commandHint_html": {
"type": "text", "type": "text",
@ -751,11 +739,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "امضا کردن متقابل فعال",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"dateWithYear": "{year}-{month}-{day}", "dateWithYear": "{year}-{month}-{day}",
"@dateWithYear": { "@dateWithYear": {
"type": "text", "type": "text",
@ -1098,11 +1081,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "جمعه",
"@friday": {
"type": "text",
"placeholders": {}
},
"groupDescription": "توصیف گروه", "groupDescription": "توصیف گروه",
"@groupDescription": { "@groupDescription": {
"type": "text", "type": "text",
@ -1184,11 +1162,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "دوشنبه",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "بی‌صدا کردن گپ", "muteChat": "بی‌صدا کردن گپ",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1415,8 +1388,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"noSearchResult": "نتایج جستجوی منطبقی وجود ندارد.",
"@noSearchResult": {},
"moderator": "مدیر", "moderator": "مدیر",
"@moderator": { "@moderator": {
"type": "text", "type": "text",
@ -1427,8 +1398,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"typeInInviteLinkManually": "پیوند دعوت را به صورت دستی وارد کنید...",
"@typeInInviteLinkManually": {},
"noPermission": "بدون اجازه", "noPermission": "بدون اجازه",
"@noPermission": { "@noPermission": {
"type": "text", "type": "text",
@ -1521,11 +1490,6 @@
"targetName": {} "targetName": {}
} }
}, },
"keysCached": "کلیدها در حافظه پنهان هستند",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"joinedTheChat": "👋 {username} به گپ پیوست", "joinedTheChat": "👋 {username} به گپ پیوست",
"@joinedTheChat": { "@joinedTheChat": {
"type": "text", "type": "text",
@ -1548,8 +1512,6 @@
}, },
"dehydrateWarning": "این عمل قابل لغو نیست. مطمئن شوید که فایل پشتیبان را به صورت امن ذخیره می کنید.", "dehydrateWarning": "این عمل قابل لغو نیست. مطمئن شوید که فایل پشتیبان را به صورت امن ذخیره می کنید.",
"@dehydrateWarning": {}, "@dehydrateWarning": {},
"dehydrateShare": "این صدور فلافی‌چت خصوصی شماست. مطمئن شوید که آن را از دست نمی‌دهید و آن را خصوصی نگه می‌دارید.",
"@dehydrateShare": {},
"locationDisabledNotice": "خدمات مکان غیرفعال است. لطفا آن را فعال کنید تا بتوانید موقعیت مکانی خود را به اشتراک بگذارید.", "locationDisabledNotice": "خدمات مکان غیرفعال است. لطفا آن را فعال کنید تا بتوانید موقعیت مکانی خود را به اشتراک بگذارید.",
"@locationDisabledNotice": { "@locationDisabledNotice": {
"type": "text", "type": "text",
@ -1745,11 +1707,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "شنبه",
"@saturday": {
"type": "text",
"placeholders": {}
},
"search": "جستجو", "search": "جستجو",
"@search": { "@search": {
"type": "text", "type": "text",
@ -1979,11 +1936,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thursday": "پنج‌شنبه",
"@thursday": {
"type": "text",
"placeholders": {}
},
"nextAccount": "حساب بعدی", "nextAccount": "حساب بعدی",
"@nextAccount": {}, "@nextAccount": {},
"editWidgets": "ویرایش ویجت‌ها", "editWidgets": "ویرایش ویجت‌ها",
@ -2027,11 +1979,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "سه‌شنبه",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "خارج از دسترس", "unavailable": "خارج از دسترس",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -2062,11 +2009,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "چهارشنبه",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"whoCanPerformWhichAction": "چه کسی توان انجام کدام عمل را داراست", "whoCanPerformWhichAction": "چه کسی توان انجام کدام عمل را داراست",
"@whoCanPerformWhichAction": { "@whoCanPerformWhichAction": {
"type": "text", "type": "text",
@ -2131,21 +2073,11 @@
}, },
"startFirstChat": "اولین گپ خود را شروع کنید", "startFirstChat": "اولین گپ خود را شروع کنید",
"@startFirstChat": {}, "@startFirstChat": {},
"sunday": "یک‌شنبه",
"@sunday": {
"type": "text",
"placeholders": {}
},
"theyMatch": "با هم منطبق هستند", "theyMatch": "با هم منطبق هستند",
"@theyMatch": { "@theyMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "این اتاق بایگانی شده است.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"title": "فلافی‌چت", "title": "فلافی‌چت",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -2545,10 +2477,30 @@
"@stories": {}, "@stories": {},
"users": "کاربرها", "users": "کاربرها",
"@users": {}, "@users": {},
"enableAutoBackups": "فعال‌سازی پشتیبان‌گیری خودکار",
"@enableAutoBackups": {},
"storeInSecureStorageDescription": "کلید بازیابی را در محل ذخیره‌سازی امن این دستگاه ذخیره کنید.", "storeInSecureStorageDescription": "کلید بازیابی را در محل ذخیره‌سازی امن این دستگاه ذخیره کنید.",
"@storeInSecureStorageDescription": {}, "@storeInSecureStorageDescription": {},
"jump": "پرش", "jump": "پرش",
"@jump": {} "@jump": {},
"discover": "کشف کنید",
"@discover": {
"type": "text",
"placeholders": {}
},
"allRooms": "تمام چت‌های گروهی",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"report": "گزارش",
"@report": {},
"openLinkInBrowser": "بازکردن پیوند در مرورگر",
"@openLinkInBrowser": {},
"reportErrorDescription": "اوه نه. اشتباهی رخ داد. لطفا بعدا تلاش کنید. اگر تمایل دارید، می‌توانید این اشکال را با توسعه‌دهندگان گزارش دهید.",
"@reportErrorDescription": {},
"signInWithPassword": "ورود با رمزعبور",
"@signInWithPassword": {},
"continueWith": "ادامه دادن با:",
"@continueWith": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "لطفا بعدا تلاش کنید یا سرور دیگری انتخاب کنید.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {}
} }

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -9,11 +9,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Dé Céadaoin",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"warning": "Rabhadh!", "warning": "Rabhadh!",
"@warning": { "@warning": {
"type": "text", "type": "text",
@ -49,32 +44,17 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Dé Máirt",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thursday": "Déardaoin",
"@thursday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "Córas", "systemTheme": "Córas",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Dé Domhnaigh",
"@sunday": {
"type": "text",
"placeholders": {}
},
"submit": "Cuir isteach", "submit": "Cuir isteach",
"@submit": { "@submit": {
"type": "text", "type": "text",
@ -120,11 +100,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Dé Sathairn",
"@saturday": {
"type": "text",
"placeholders": {}
},
"reply": "Freagair", "reply": "Freagair",
"@reply": { "@reply": {
"type": "text", "type": "text",
@ -205,11 +180,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Tá cros-shíniú tosaithe",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"createNewSpace": "Spás nua", "createNewSpace": "Spás nua",
"@createNewSpace": { "@createNewSpace": {
"type": "text", "type": "text",
@ -267,11 +237,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Dé Luain",
"@monday": {
"type": "text",
"placeholders": {}
},
"moderator": "Modhnóir", "moderator": "Modhnóir",
"@moderator": { "@moderator": {
"type": "text", "type": "text",
@ -352,11 +317,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Dé hAoine",
"@friday": {
"type": "text",
"placeholders": {}
},
"forward": "Seol ar aghaidh", "forward": "Seol ar aghaidh",
"@forward": { "@forward": {
"type": "text", "type": "text",
@ -384,11 +344,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Tar ar",
"@discover": {
"type": "text",
"placeholders": {}
},
"devices": "Gléasanna", "devices": "Gléasanna",
"@devices": { "@devices": {
"type": "text", "type": "text",
@ -534,11 +489,6 @@
}, },
"sendOnEnter": "Seol ar iontráil", "sendOnEnter": "Seol ar iontráil",
"@sendOnEnter": {}, "@sendOnEnter": {},
"archivedRoom": "Seomra cartlainne",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"archive": "Cartlann", "archive": "Cartlann",
"@archive": { "@archive": {
"type": "text", "type": "text",
@ -1312,8 +1262,6 @@
}, },
"scanQrCode": "Scan cód QR", "scanQrCode": "Scan cód QR",
"@scanQrCode": {}, "@scanQrCode": {},
"typeInInviteLinkManually": "Clóscríobh an nasc cuiridh de láimh...",
"@typeInInviteLinkManually": {},
"inviteText": "Thug {username} cuireadh duit chuig FluffyChat.\n1. Suiteáil FluffyChat: https://fluffychat.im\n2. Cláraigh nó sínigh isteach\n3. Oscail an nasc cuiridh: {link}", "inviteText": "Thug {username} cuireadh duit chuig FluffyChat.\n1. Suiteáil FluffyChat: https://fluffychat.im\n2. Cláraigh nó sínigh isteach\n3. Oscail an nasc cuiridh: {link}",
"@inviteText": { "@inviteText": {
"type": "text", "type": "text",
@ -1451,11 +1399,6 @@
"targetName": {} "targetName": {}
} }
}, },
"keysCached": "Cuirtear eochracha i dtaisce",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"joinedTheChat": "Tháinig {username} isteach sa chomhrá", "joinedTheChat": "Tháinig {username} isteach sa chomhrá",
"@joinedTheChat": { "@joinedTheChat": {
"type": "text", "type": "text",
@ -1740,11 +1683,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Tá an seomra seo curtha i gcartlann.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"theyDontMatch": "Níl siad céanna", "theyDontMatch": "Níl siad céanna",
"@theyDontMatch": { "@theyDontMatch": {
"type": "text", "type": "text",
@ -2153,8 +2091,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "D'aitheantas úsáideora:",
"@yourUserId": {},
"yourChatBackupHasBeenSetUp": "Bunaíodh do chúltaca comhrá.", "yourChatBackupHasBeenSetUp": "Bunaíodh do chúltaca comhrá.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"openVideoCamera": "Oscail físcheamara", "openVideoCamera": "Oscail físcheamara",

View File

@ -23,7 +23,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"activatedEndToEndEncryption": "🔐 {username} activou o cifrado extremo-a-extremo", "activatedEndToEndEncryption": "🔐 {username} activou a cifraxe extremo-a-extremo",
"@activatedEndToEndEncryption": { "@activatedEndToEndEncryption": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -82,11 +82,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Sala arquivada",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Permitir o acceso de convidadas", "areGuestsAllowedToJoin": "Permitir o acceso de convidadas",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -319,7 +314,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"channelCorruptedDecryptError": "O cifrado está corrompido", "channelCorruptedDecryptError": "A cifraxe está estragada",
"@channelCorruptedDecryptError": { "@channelCorruptedDecryptError": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -544,11 +539,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Sinatura-Cruzada activada",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Actualmente activo", "currentlyActive": "Actualmente activo",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -634,11 +624,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Descubrir",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "O nome público mudou", "displaynameHasBeenChanged": "O nome público mudou",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -719,12 +704,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"enableEncryption": "Activar cifrado", "enableEncryption": "Activar cifraxe",
"@enableEncryption": { "@enableEncryption": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"enableEncryptionWarning": "Non poderás desactivar o cifrado posteriormente, tes certeza?", "enableEncryptionWarning": "Non poderás desactivar a cifraxe posteriormente, tes certeza?",
"@enableEncryptionWarning": { "@enableEncryptionWarning": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -734,12 +719,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"encryption": "Cifrado", "encryption": "Cifraxe",
"@encryption": { "@encryption": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"encryptionNotEnabled": "O cifrado non está activado", "encryptionNotEnabled": "A cifraxe non está activada",
"@encryptionNotEnabled": { "@encryptionNotEnabled": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -805,11 +790,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Venres",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Desde que se una", "fromJoining": "Desde que se una",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -1000,11 +980,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Chaves almacenadas",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} expulsou a {targetName}", "kicked": "👞 {username} expulsou a {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1139,17 +1114,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Luns",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Acalar chat", "muteChat": "Acalar chat",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"needPantalaimonWarning": "Ten en conta que polo de agora precisas Pantalaimon para o cifrado extremo-a-extremo.", "needPantalaimonWarning": "Ten en conta que polo de agora precisas Pantalaimon para a cifraxe extremo-a-extremo.",
"@needPantalaimonWarning": { "@needPantalaimonWarning": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1189,7 +1159,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"noEncryptionForPublicRooms": "Só podes activar o cifrado tan pronto como a sala non sexa públicamente accesible.", "noEncryptionForPublicRooms": "Só podes activar a cifraxe tan pronto como a sala non sexa públicamente accesible.",
"@noEncryptionForPublicRooms": { "@noEncryptionForPublicRooms": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1537,11 +1507,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Sábado",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Gardar ficheiro", "saveFile": "Gardar ficheiro",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1780,11 +1745,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Domingo",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Sincronizando... Agarda.", "synchronizingPleaseWait": "Sincronizando... Agarda.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1805,16 +1765,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "A sala foi arquivada.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Xoves",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1851,11 +1801,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Martes",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Non dispoñible", "unavailable": "Non dispoñible",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1879,7 +1824,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"unknownEncryptionAlgorithm": "Algoritmo de cifrado descoñecido", "unknownEncryptionAlgorithm": "Algoritmo de cifraxe descoñecido",
"@unknownEncryptionAlgorithm": { "@unknownEncryptionAlgorithm": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -2026,11 +1971,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Mércores",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Enviamosche un email", "weSentYouAnEmail": "Enviamosche un email",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2107,8 +2047,6 @@
"@addToSpace": {}, "@addToSpace": {},
"scanQrCode": "Escanear código QR", "scanQrCode": "Escanear código QR",
"@scanQrCode": {}, "@scanQrCode": {},
"typeInInviteLinkManually": "Escribe manualmente a ligazón do convite...",
"@typeInInviteLinkManually": {},
"shareYourInviteLink": "Comparte a túa ligazón de convite", "shareYourInviteLink": "Comparte a túa ligazón de convite",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"sendOnEnter": "Enter para enviar", "sendOnEnter": "Enter para enviar",
@ -2129,8 +2067,6 @@
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"unverified": "Sen verificar", "unverified": "Sen verificar",
"@unverified": {}, "@unverified": {},
"yourUserId": "O teu ID:",
"@yourUserId": {},
"pleaseEnterValidEmail": "Escribe un enderezo de email válido.", "pleaseEnterValidEmail": "Escribe un enderezo de email válido.",
"@pleaseEnterValidEmail": {}, "@pleaseEnterValidEmail": {},
"passwordsDoNotMatch": "Os contrasinais non concordan!", "passwordsDoNotMatch": "Os contrasinais non concordan!",
@ -2167,7 +2103,7 @@
"type": "text", "type": "text",
"description": "Usage hint for the command /discardsession" "description": "Usage hint for the command /discardsession"
}, },
"commandHint_create": "Crear un grupo de conversa baleiro\nUsa --no-encryption para desactivar o cifrado", "commandHint_create": "Crear un grupo de conversa baleiro\nUsa --no-encryption para desactivar a cifraxe",
"@commandHint_create": { "@commandHint_create": {
"type": "text", "type": "text",
"description": "Usage hint for the command /create" "description": "Usage hint for the command /create"
@ -2177,7 +2113,7 @@
"type": "text", "type": "text",
"description": "Usage hint for the command /clearcache" "description": "Usage hint for the command /clearcache"
}, },
"commandHint_dm": "Iniciar un chat directo\nUsa --no-encryption para desactivar o cifrado", "commandHint_dm": "Iniciar un chat directo\nUsa --no-encryption para desactivar a cifraxe",
"@commandHint_dm": { "@commandHint_dm": {
"type": "text", "type": "text",
"description": "Usage hint for the command /dm" "description": "Usage hint for the command /dm"
@ -2388,8 +2324,6 @@
"@pleaseEnterRecoveryKeyDescription": {}, "@pleaseEnterRecoveryKeyDescription": {},
"users": "Usuarias", "users": "Usuarias",
"@users": {}, "@users": {},
"enableAutoBackups": "Activar copia automática",
"@enableAutoBackups": {},
"storeInSecureStorageDescription": "Gardar a chave de recuperación na almacenaxe segura deste dispositivo.", "storeInSecureStorageDescription": "Gardar a chave de recuperación na almacenaxe segura deste dispositivo.",
"@storeInSecureStorageDescription": {}, "@storeInSecureStorageDescription": {},
"countFiles": "{count} ficheiros", "countFiles": "{count} ficheiros",
@ -2400,8 +2334,6 @@
}, },
"unlockOldMessages": "Desbloquear mensaxes antigas", "unlockOldMessages": "Desbloquear mensaxes antigas",
"@unlockOldMessages": {}, "@unlockOldMessages": {},
"dehydrateShare": "Esta é a copia de apoio privada de FluffyChat. Pon coidado en non perdela e mantela segura.",
"@dehydrateShare": {},
"dehydrateTorLong": "Para usuarias de TOR, é recomendable exportar a sesión antes de pechar a ventál.", "dehydrateTorLong": "Para usuarias de TOR, é recomendable exportar a sesión antes de pechar a ventál.",
"@dehydrateTorLong": {}, "@dehydrateTorLong": {},
"hydrateTor": "Usuarias TOR: Importar a sesión exportada", "hydrateTor": "Usuarias TOR: Importar a sesión exportada",
@ -2511,15 +2443,13 @@
"senderName": {} "senderName": {}
} }
}, },
"noSearchResult": "Non hai resultados para a busca.",
"@noSearchResult": {},
"enterInviteLinkOrMatrixId": "Escribe a ligazón de convite ou ID Matrix...", "enterInviteLinkOrMatrixId": "Escribe a ligazón de convite ou ID Matrix...",
"@enterInviteLinkOrMatrixId": {}, "@enterInviteLinkOrMatrixId": {},
"encryptThisChat": "Cifrar esta conversa", "encryptThisChat": "Cifrar esta conversa",
"@encryptThisChat": {}, "@encryptThisChat": {},
"endToEndEncryption": "Cifrado de extremo a extremo", "endToEndEncryption": "Cifraxe de extremo a extremo",
"@endToEndEncryption": {}, "@endToEndEncryption": {},
"disableEncryptionWarning": "Por razóns de seguridade non podes desactivar o cifrado dunha conversa onde foi activado previamente.", "disableEncryptionWarning": "Por razóns de seguridade non podes desactivar a cifraxe dunha conversa onde foi activada previamente.",
"@disableEncryptionWarning": {}, "@disableEncryptionWarning": {},
"sorryThatsNotPossible": "Lamentámolo... iso non é posible", "sorryThatsNotPossible": "Lamentámolo... iso non é posible",
"@sorryThatsNotPossible": {}, "@sorryThatsNotPossible": {},
@ -2558,5 +2488,27 @@
"readUpToHere": "Lin ate aquí", "readUpToHere": "Lin ate aquí",
"@readUpToHere": {}, "@readUpToHere": {},
"openLinkInBrowser": "Abrir ligazón no navegador", "openLinkInBrowser": "Abrir ligazón no navegador",
"@openLinkInBrowser": {} "@openLinkInBrowser": {},
"jump": "Ir alá",
"@jump": {},
"report": "informar",
"@report": {},
"allRooms": "Todas as Conversas en grupo",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"reportErrorDescription": "Vaia! Algo fallou. Inténtao máis tarde. Se queres, podes informar do problema aos desenvolvedores.",
"@reportErrorDescription": {},
"discover": "Descubrir",
"@discover": {
"type": "text",
"placeholders": {}
},
"signInWithPassword": "Accede con contrasinal",
"@signInWithPassword": {},
"continueWith": "Continuar con:",
"@continueWith": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "Inténtao máis tarde ou elixe un servidor diferente.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {}
} }

View File

@ -61,11 +61,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "חדר בארכיון",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "האם משתמשים אורחים מורשים להצטרף", "areGuestsAllowedToJoin": "האם משתמשים אורחים מורשים להצטרף",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -343,8 +338,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "מזהה המשתמש שלך:",
"@yourUserId": {},
"yourChatBackupHasBeenSetUp": "גיבוי הצ'אט שלך הוגדר.", "yourChatBackupHasBeenSetUp": "גיבוי הצ'אט שלך הוגדר.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"chatBackup": "גיבוי צ'אט", "chatBackup": "גיבוי צ'אט",
@ -477,11 +470,6 @@
"username": {} "username": {}
} }
}, },
"crossSigningEnabled": "חתימה צולבת על",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "פעיל כעת", "currentlyActive": "פעיל כעת",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -543,11 +531,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "לגלות",
"@discover": {
"type": "text",
"placeholders": {}
},
"downloadFile": "הורד קובץ", "downloadFile": "הורד קובץ",
"@downloadFile": { "@downloadFile": {
"type": "text", "type": "text",
@ -630,11 +613,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "יום שישי",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "מהצטרפות", "fromJoining": "מהצטרפות",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -755,11 +733,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "המפתחות נשמרים במטמון",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} בעט ב {targetName}", "kicked": "{username} בעט ב {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1146,8 +1119,6 @@
}, },
"shareYourInviteLink": "שתף את קישור ההזמנה שלך", "shareYourInviteLink": "שתף את קישור ההזמנה שלך",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"typeInInviteLinkManually": "הקלד את קישור ההזמנה באופן ידני...",
"@typeInInviteLinkManually": {},
"noRoomsFound": "לא נמצאו חדרים…", "noRoomsFound": "לא נמצאו חדרים…",
"@noRoomsFound": { "@noRoomsFound": {
"type": "text", "type": "text",
@ -1312,11 +1283,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "יום שני",
"@monday": {
"type": "text",
"placeholders": {}
},
"noGoogleServicesWarning": "נראה שאין לך שירותי גוגל בטלפון שלך. זו החלטה טובה לפרטיות שלך! כדי לקבל התרעות ב- FluffyChat אנו ממליצים להשתמש https://microg.org/ או https://unifiedpush.org/.", "noGoogleServicesWarning": "נראה שאין לך שירותי גוגל בטלפון שלך. זו החלטה טובה לפרטיות שלך! כדי לקבל התרעות ב- FluffyChat אנו ממליצים להשתמש https://microg.org/ או https://unifiedpush.org/.",
"@noGoogleServicesWarning": { "@noGoogleServicesWarning": {
"type": "text", "type": "text",

View File

@ -77,11 +77,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Arhivirana soba",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Smiju li se gosti pridružiti", "areGuestsAllowedToJoin": "Smiju li se gosti pridružiti",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -534,11 +529,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Unakrsno potpisivanje uključeno",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Trenutačno aktivni", "currentlyActive": "Trenutačno aktivni",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -624,11 +614,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Otkrij",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Prikazno ime je promijenjeno", "displaynameHasBeenChanged": "Prikazno ime je promijenjeno",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -788,11 +773,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Petak",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Od pridruživanja", "fromJoining": "Od pridruživanja",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -983,11 +963,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Ključevi su spremljeni u predmemoriji",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} je izbacio/la {targetName}", "kicked": "👞 {username} je izbacio/la {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1112,11 +1087,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Ponedjeljak",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Isključi zvuk razgovora", "muteChat": "Isključi zvuk razgovora",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1492,11 +1462,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Subota",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Spremi datoteku", "saveFile": "Spremi datoteku",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1730,11 +1695,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Nedjelja",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Sinkronizira se … Pričekaj.", "synchronizingPleaseWait": "Sinkronizira se … Pričekaj.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1755,16 +1715,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Ova soba je arhivirana.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Četvrtak",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1801,11 +1751,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Utorak",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Nedostupno", "unavailable": "Nedostupno",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1976,11 +1921,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Srijeda",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Poslali smo ti e-poruku", "weSentYouAnEmail": "Poslali smo ti e-poruku",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2109,8 +2049,6 @@
"@serverRequiresEmail": {}, "@serverRequiresEmail": {},
"scanQrCode": "Snimi QR kod", "scanQrCode": "Snimi QR kod",
"@scanQrCode": {}, "@scanQrCode": {},
"typeInInviteLinkManually": "Upiši poveznicu za pozivnicu …",
"@typeInInviteLinkManually": {},
"shareYourInviteLink": "Dijeli svoju poveznicu za pozivnicu", "shareYourInviteLink": "Dijeli svoju poveznicu za pozivnicu",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"homeserver": "Domaći poslužitelj", "homeserver": "Domaći poslužitelj",
@ -2133,8 +2071,6 @@
"@addAccount": {}, "@addAccount": {},
"oneClientLoggedOut": "Jedan od tvojih klijenata je odjavljen", "oneClientLoggedOut": "Jedan od tvojih klijenata je odjavljen",
"@oneClientLoggedOut": {}, "@oneClientLoggedOut": {},
"yourUserId": "Tvoj korisnički ID:",
"@yourUserId": {},
"unverified": "Nepotvrđeno", "unverified": "Nepotvrđeno",
"@unverified": {}, "@unverified": {},
"yourChatBackupHasBeenSetUp": "Sigurnosna kopija tvog razgovora je postavljena.", "yourChatBackupHasBeenSetUp": "Sigurnosna kopija tvog razgovora je postavljena.",
@ -2381,10 +2317,6 @@
}, },
"dehydrate": "Izvezi sesiju i izbriši uređaj", "dehydrate": "Izvezi sesiju i izbriši uređaj",
"@dehydrate": {}, "@dehydrate": {},
"dehydrateShare": "Ovo je izvoz tvog privatnog FluffyChata. Pazi da ga ne izgubiš i zadrži ga privatnim.",
"@dehydrateShare": {},
"enableAutoBackups": "Uključi automatsko spremanje sigurnosnih kopija",
"@enableAutoBackups": {},
"unlockOldMessages": "Otključaj stare poruke", "unlockOldMessages": "Otključaj stare poruke",
"@unlockOldMessages": {}, "@unlockOldMessages": {},
"storeInSecureStorageDescription": "Ključ za obnavljanje spremi u sigurno spremište na ovom uređaju.", "storeInSecureStorageDescription": "Ključ za obnavljanje spremi u sigurno spremište na ovom uređaju.",
@ -2553,12 +2485,30 @@
"senderName": {} "senderName": {}
} }
}, },
"noSearchResult": "Nema poklapajućih rezultata.",
"@noSearchResult": {},
"noKeyForThisMessage": "To se može dogoditi ako je poruka poslana prije prijave na tvoj račun na ovom uređaju.\n\nTakođer je moguće da je pošiljatelj blokirao tvoj uređaj ili je došlo do greške s internetskom vezom.\n\nMožeš li pročitati poruku na jednoj drugoj sesiji? U tom slučaju možeš prenijeti poruku iz nje! Idi na Postavke > Uređaji i uvjeri se da su se tvoji uređaji međusobno provjerili. Kada sljedeći put otvoriš sobu i obje sesije su u prednjem planu, ključevi će se automatski prenijeti.\n\nNe želiš izgubiti ključeve kada se odjaviš ili zamijeniš uređaje? Aktiviraj spremanje sigurnosne kopije razgovora u postavkama.", "noKeyForThisMessage": "To se može dogoditi ako je poruka poslana prije prijave na tvoj račun na ovom uređaju.\n\nTakođer je moguće da je pošiljatelj blokirao tvoj uređaj ili je došlo do greške s internetskom vezom.\n\nMožeš li pročitati poruku na jednoj drugoj sesiji? U tom slučaju možeš prenijeti poruku iz nje! Idi na Postavke > Uređaji i uvjeri se da su se tvoji uređaji međusobno provjerili. Kada sljedeći put otvoriš sobu i obje sesije su u prednjem planu, ključevi će se automatski prenijeti.\n\nNe želiš izgubiti ključeve kada se odjaviš ili zamijeniš uređaje? Aktiviraj spremanje sigurnosne kopije razgovora u postavkama.",
"@noKeyForThisMessage": {}, "@noKeyForThisMessage": {},
"reopenChat": "Ponovo otvori razgovor", "reopenChat": "Ponovo otvori razgovor",
"@reopenChat": {}, "@reopenChat": {},
"openLinkInBrowser": "Otvori poveznicu u pregledniku", "openLinkInBrowser": "Otvori poveznicu u pregledniku",
"@openLinkInBrowser": {} "@openLinkInBrowser": {},
"discover": "Otkrij",
"@discover": {
"type": "text",
"placeholders": {}
},
"report": "prijavi",
"@report": {},
"allRooms": "Svi grupni razgovori",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"reportErrorDescription": "Dogodila se greška. Pokušaj ponovo kasnije. Ako želiš, grešku možeš prijaviti programerima.",
"@reportErrorDescription": {},
"signInWithPassword": "Prijavi se s lozinkom",
"@signInWithPassword": {},
"continueWith": "Nastavi sa:",
"@continueWith": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "Pokušaj ponovo kasnije ili odaberi jedan drugi poslužitelj.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {}
} }

File diff suppressed because it is too large Load Diff

View File

@ -247,11 +247,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Jumat",
"@friday": {
"type": "text",
"placeholders": {}
},
"forward": "Teruskan", "forward": "Teruskan",
"@forward": { "@forward": {
"type": "text", "type": "text",
@ -449,11 +444,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Tanda tangan silang dinyalakan",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"createNewGroup": "Buat grup baru", "createNewGroup": "Buat grup baru",
"@createNewGroup": { "@createNewGroup": {
"type": "text", "type": "text",
@ -729,11 +719,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Ruangan yang Diarsipkan",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"appLock": "Kunci aplikasi", "appLock": "Kunci aplikasi",
"@appLock": { "@appLock": {
"type": "text", "type": "text",
@ -885,11 +870,6 @@
"targetName": {} "targetName": {}
} }
}, },
"keysCached": "Kunci telah ditembolok",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"joinRoom": "Bergabung dengan ruangan", "joinRoom": "Bergabung dengan ruangan",
"@joinRoom": { "@joinRoom": {
"type": "text", "type": "text",
@ -967,11 +947,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Senin",
"@monday": {
"type": "text",
"placeholders": {}
},
"moderator": "Moderator", "moderator": "Moderator",
"@moderator": { "@moderator": {
"type": "text", "type": "text",
@ -1176,11 +1151,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Rabu",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"warning": "Peringatan!", "warning": "Peringatan!",
"@warning": { "@warning": {
"type": "text", "type": "text",
@ -1334,11 +1304,6 @@
"targetName": {} "targetName": {}
} }
}, },
"tuesday": "Selasa",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"tryToSendAgain": "Coba kirim lagi", "tryToSendAgain": "Coba kirim lagi",
"@tryToSendAgain": { "@tryToSendAgain": {
"type": "text", "type": "text",
@ -1370,16 +1335,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thursday": "Kamis",
"@thursday": {
"type": "text",
"placeholders": {}
},
"thisRoomHasBeenArchived": "Ruangan ini telah diarsipkan.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"theyMatch": "Cocok", "theyMatch": "Cocok",
"@theyMatch": { "@theyMatch": {
"type": "text", "type": "text",
@ -1400,11 +1355,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Minggu",
"@sunday": {
"type": "text",
"placeholders": {}
},
"submit": "Kirim", "submit": "Kirim",
"@submit": { "@submit": {
"type": "text", "type": "text",
@ -1775,8 +1725,6 @@
}, },
"scanQrCode": "Pindai kode QR", "scanQrCode": "Pindai kode QR",
"@scanQrCode": {}, "@scanQrCode": {},
"typeInInviteLinkManually": "Masukkan tautan undangan secara manual...",
"@typeInInviteLinkManually": {},
"shareYourInviteLink": "Bagikan tautan undanganmu", "shareYourInviteLink": "Bagikan tautan undanganmu",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"noMatrixServer": "{server1} itu bukan server Matrix, gunakan {server2} saja?", "noMatrixServer": "{server1} itu bukan server Matrix, gunakan {server2} saja?",
@ -1885,11 +1833,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Temukan",
"@discover": {
"type": "text",
"placeholders": {}
},
"defaultPermissionLevel": "Level izin default", "defaultPermissionLevel": "Level izin default",
"@defaultPermissionLevel": { "@defaultPermissionLevel": {
"type": "text", "type": "text",
@ -2068,11 +2011,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Sabtu",
"@saturday": {
"type": "text",
"placeholders": {}
},
"removeDevice": "Hapus perangkat", "removeDevice": "Hapus perangkat",
"@removeDevice": { "@removeDevice": {
"type": "text", "type": "text",
@ -2134,8 +2072,6 @@
"@link": {}, "@link": {},
"yourChatBackupHasBeenSetUp": "Cadangan obrolanmu telah disiapkan.", "yourChatBackupHasBeenSetUp": "Cadangan obrolanmu telah disiapkan.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"yourUserId": "ID penggunamu:",
"@yourUserId": {},
"unverified": "Tidak terverifikasi", "unverified": "Tidak terverifikasi",
"@unverified": {}, "@unverified": {},
"pleaseEnterValidEmail": "Mohon masukkan alamat email yang valid.", "pleaseEnterValidEmail": "Mohon masukkan alamat email yang valid.",
@ -2389,8 +2325,6 @@
"@recoveryKeyLost": {}, "@recoveryKeyLost": {},
"storeInAndroidKeystore": "Simpan di Android KeyStore", "storeInAndroidKeystore": "Simpan di Android KeyStore",
"@storeInAndroidKeystore": {}, "@storeInAndroidKeystore": {},
"enableAutoBackups": "Aktifkan cadangan otomatis",
"@enableAutoBackups": {},
"storeSecurlyOnThisDevice": "Simpan secara aman di perangkat ini", "storeSecurlyOnThisDevice": "Simpan secara aman di perangkat ini",
"@storeSecurlyOnThisDevice": {}, "@storeSecurlyOnThisDevice": {},
"countFiles": "{count} file", "countFiles": "{count} file",
@ -2399,8 +2333,6 @@
"count": {} "count": {}
} }
}, },
"dehydrateShare": "Ini adalah ekspor FluffyChat privat kamu. Pastikan kamu tidak menghilangkannya dan tetap rahasia.",
"@dehydrateShare": {},
"hydrate": "Pulihkan dari file cadangan", "hydrate": "Pulihkan dari file cadangan",
"@hydrate": {}, "@hydrate": {},
"indexedDbErrorTitle": "Masalah dengan mode privat", "indexedDbErrorTitle": "Masalah dengan mode privat",
@ -2531,8 +2463,6 @@
"@endToEndEncryption": {}, "@endToEndEncryption": {},
"disableEncryptionWarning": "Demi keamanan kamu tidak bisa menonaktifkan enkripsi dalam sebuah obrolan di mana sebelumbya sudah diaktifkan.", "disableEncryptionWarning": "Demi keamanan kamu tidak bisa menonaktifkan enkripsi dalam sebuah obrolan di mana sebelumbya sudah diaktifkan.",
"@disableEncryptionWarning": {}, "@disableEncryptionWarning": {},
"noSearchResult": "Tidak ada hasil pencarian yang cocok.",
"@noSearchResult": {},
"letsStart": "Mari kita mulai", "letsStart": "Mari kita mulai",
"@letsStart": {}, "@letsStart": {},
"enterInviteLinkOrMatrixId": "Masukkan tautan undangan atau ID Matrix...", "enterInviteLinkOrMatrixId": "Masukkan tautan undangan atau ID Matrix...",
@ -2557,5 +2487,27 @@
"readUpToHere": "Baca sampai sini", "readUpToHere": "Baca sampai sini",
"@readUpToHere": {}, "@readUpToHere": {},
"jump": "Lompat", "jump": "Lompat",
"@jump": {} "@jump": {},
"openLinkInBrowser": "Buka tautan dalam peramban",
"@openLinkInBrowser": {},
"discover": "Jelajahi",
"@discover": {
"type": "text",
"placeholders": {}
},
"allRooms": "Semua Percakapan Grup",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"report": "laporkan",
"@report": {},
"reportErrorDescription": "Aduh. Ada yang salah. Silakan coba lahi nanti. Jika kamu mau, kamu bisa melaporkan kutu ini kepada para pengembang.",
"@reportErrorDescription": {},
"signInWithPassword": "Masuk dengan kata sandi",
"@signInWithPassword": {},
"continueWith": "Lanjutkan dengan:",
"@continueWith": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "Silakan coba lagi nanti atau pilih server yang lain.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {}
} }

View File

@ -34,11 +34,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Decovrir",
"@discover": {
"type": "text",
"placeholders": {}
},
"containsUserName": "Contene li nómine", "containsUserName": "Contene li nómine",
"@containsUserName": { "@containsUserName": {
"type": "text", "type": "text",
@ -189,11 +184,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Claves es in cache",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"lastActiveAgo": "Ultim activité: {localizedTimeShort}", "lastActiveAgo": "Ultim activité: {localizedTimeShort}",
"@lastActiveAgo": { "@lastActiveAgo": {
"type": "text", "type": "text",
@ -340,11 +330,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Mardí",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Índisponibil", "unavailable": "Índisponibil",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -465,11 +450,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Saturdí",
"@saturday": {
"type": "text",
"placeholders": {}
},
"dateWithYear": "{day}.{month}.{year}", "dateWithYear": "{day}.{month}.{year}",
"@dateWithYear": { "@dateWithYear": {
"type": "text", "type": "text",
@ -494,11 +474,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Venerdí",
"@friday": {
"type": "text",
"placeholders": {}
},
"lightTheme": "Lucid", "lightTheme": "Lucid",
"@lightTheme": { "@lightTheme": {
"type": "text", "type": "text",
@ -529,11 +504,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thursday": "Jovedí",
"@thursday": {
"type": "text",
"placeholders": {}
},
"username": "Nómine de usator", "username": "Nómine de usator",
"@username": { "@username": {
"type": "text", "type": "text",
@ -544,11 +514,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Mercurdí",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"submit": "Inviar", "submit": "Inviar",
"@submit": { "@submit": {
"type": "text", "type": "text",
@ -683,11 +648,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Archivat chambre",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"changePassword": "Cambiar li contrasigne", "changePassword": "Cambiar li contrasigne",
"@changePassword": { "@changePassword": {
"type": "text", "type": "text",
@ -970,8 +930,6 @@
}, },
"updateAvailable": "Un actualisament de FluffyChat es disponibil", "updateAvailable": "Un actualisament de FluffyChat es disponibil",
"@updateAvailable": {}, "@updateAvailable": {},
"yourUserId": "Vor ID de usator:",
"@yourUserId": {},
"editWidgets": "Modificar li widgets", "editWidgets": "Modificar li widgets",
"@editWidgets": {}, "@editWidgets": {},
"widgetEtherpad": "Textual nota", "widgetEtherpad": "Textual nota",
@ -1165,11 +1123,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Lunedí",
"@monday": {
"type": "text",
"placeholders": {}
},
"newGroup": "Crear un gruppe", "newGroup": "Crear un gruppe",
"@newGroup": {}, "@newGroup": {},
"newSpace": "Crear un spacie", "newSpace": "Crear un spacie",
@ -1218,11 +1171,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Soledí",
"@sunday": {
"type": "text",
"placeholders": {}
},
"unverified": "Ínverificat", "unverified": "Ínverificat",
"@unverified": {}, "@unverified": {},
"deviceId": "ID de aparate", "deviceId": "ID de aparate",

View File

@ -76,11 +76,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Stanza archiviata",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Gli utenti ospiti possono partecipare", "areGuestsAllowedToJoin": "Gli utenti ospiti possono partecipare",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -432,11 +427,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Firma incrociata abilitata",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Attualmente attivo", "currentlyActive": "Attualmente attivo",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -522,11 +512,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Scopri",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Il nominativo è stato cambiato", "displaynameHasBeenChanged": "Il nominativo è stato cambiato",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -679,11 +664,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "venerdì",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Dall'adesione", "fromJoining": "Dall'adesione",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -874,11 +854,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Le chiave sono memorizzate nella cache",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} ha espulso {targetName}", "kicked": "{username} ha espulso {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -996,11 +971,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "lunedì",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Silenzia discussione", "muteChat": "Silenzia discussione",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1346,11 +1316,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "sabato",
"@saturday": {
"type": "text",
"placeholders": {}
},
"search": "Cerca", "search": "Cerca",
"@search": { "@search": {
"type": "text", "type": "text",
@ -1550,11 +1515,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "domenica",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "Sistema", "systemTheme": "Sistema",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1570,16 +1530,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Questa stanza è stata archiviata.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "giovedì",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1616,11 +1566,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "martedì",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Non disponibile", "unavailable": "Non disponibile",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1791,11 +1736,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "mercoledì",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Ti abbiamo inviato un'e-mail", "weSentYouAnEmail": "Ti abbiamo inviato un'e-mail",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -1936,8 +1876,6 @@
"@passwordsDoNotMatch": {}, "@passwordsDoNotMatch": {},
"pleaseEnterValidEmail": "Inserire un indirizzo email valido.", "pleaseEnterValidEmail": "Inserire un indirizzo email valido.",
"@pleaseEnterValidEmail": {}, "@pleaseEnterValidEmail": {},
"yourUserId": "Il tuo ID utente:",
"@yourUserId": {},
"commandHint_leave": "Lascia questa stanza", "commandHint_leave": "Lascia questa stanza",
"@commandHint_leave": { "@commandHint_leave": {
"type": "text", "type": "text",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -71,11 +71,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Arkivert rom",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Skal gjester tillates å ta del", "areGuestsAllowedToJoin": "Skal gjester tillates å ta del",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -401,11 +396,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Videreformidling av tillit på",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Aktiv nå", "currentlyActive": "Aktiv nå",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -491,11 +481,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Oppdag",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Visningsnavn endret", "displaynameHasBeenChanged": "Visningsnavn endret",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -648,11 +633,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Fredag",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Fra å ta del", "fromJoining": "Fra å ta del",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -838,11 +818,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Nøkler hurtiglagret",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} kastet ut {targetName}", "kicked": "{username} kastet ut {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -960,11 +935,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Mandag",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Forstum sludring", "muteChat": "Forstum sludring",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1275,11 +1245,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Lørdag",
"@saturday": {
"type": "text",
"placeholders": {}
},
"search": "Søk", "search": "Søk",
"@search": { "@search": {
"type": "text", "type": "text",
@ -1474,11 +1439,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Søndag",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "System", "systemTheme": "System",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1494,16 +1454,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Dette rommet har blitt arkivert.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Torsdag",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1525,11 +1475,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Tirsdag",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Utilgjengelig", "unavailable": "Utilgjengelig",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1685,11 +1630,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Onsdag",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Du har fått en e-post", "weSentYouAnEmail": "Du har fått en e-post",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -1839,7 +1779,5 @@
"@changeYourAvatar": { "@changeYourAvatar": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, }
"yourUserId": "Din bruker ID:",
"@yourUserId": {}
} }

File diff suppressed because it is too large Load Diff

View File

@ -67,11 +67,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Zarchiwizowane pokoje",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Czy użytkownicy-goście mogą dołączyć", "areGuestsAllowedToJoin": "Czy użytkownicy-goście mogą dołączyć",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -532,7 +527,7 @@
"day": {} "day": {}
} }
}, },
"deactivateAccountWarning": "To dezaktywuje twoje konto. To jest nieodwracalne ! Czy jesteś pewien?", "deactivateAccountWarning": "To zdezaktywuje twoje konto. To jest nieodwracalne! Na pewno chcesz to zrobić?",
"@deactivateAccountWarning": { "@deactivateAccountWarning": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -704,11 +699,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Piątek",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Od dołączenia", "fromJoining": "Od dołączenia",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -879,11 +869,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Klucze są załadowane",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} wyrzucił/-a {targetName}", "kicked": "👞 {username} wyrzucił/-a {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -996,11 +981,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Poniedziałek",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Wycisz czat", "muteChat": "Wycisz czat",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1229,11 +1209,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Sobota",
"@saturday": {
"type": "text",
"placeholders": {}
},
"seenByUser": "Zobaczone przez {username}", "seenByUser": "Zobaczone przez {username}",
"@seenByUser": { "@seenByUser": {
"type": "text", "type": "text",
@ -1369,11 +1344,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Niedziela",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Synchronizacja… Proszę czekać.", "synchronizingPleaseWait": "Synchronizacja… Proszę czekać.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1384,16 +1354,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Ten pokój został przeniesiony do archiwum.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Czwartek",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1410,11 +1370,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Wtorek",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unbannedUser": "{username} odbanował/-a {targetName}", "unbannedUser": "{username} odbanował/-a {targetName}",
"@unbannedUser": { "@unbannedUser": {
"type": "text", "type": "text",
@ -1540,11 +1495,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Środa",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"whoIsAllowedToJoinThisGroup": "Kto może dołączyć do tej grupy", "whoIsAllowedToJoinThisGroup": "Kto może dołączyć do tej grupy",
"@whoIsAllowedToJoinThisGroup": { "@whoIsAllowedToJoinThisGroup": {
"type": "text", "type": "text",
@ -1821,8 +1771,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "Twoja nazwa użytkownika:",
"@yourUserId": {},
"yourChatBackupHasBeenSetUp": "Twoja kopia zapasowa chatu została ustawiona.", "yourChatBackupHasBeenSetUp": "Twoja kopia zapasowa chatu została ustawiona.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"chatHasBeenAddedToThisSpace": "Chat został dodany do tej przestrzeni", "chatHasBeenAddedToThisSpace": "Chat został dodany do tej przestrzeni",
@ -1832,11 +1780,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Odkrywaj",
"@discover": {
"type": "text",
"placeholders": {}
},
"editRoomAvatar": "Edytuj zdjęcie pokoju", "editRoomAvatar": "Edytuj zdjęcie pokoju",
"@editRoomAvatar": { "@editRoomAvatar": {
"type": "text", "type": "text",
@ -1947,8 +1890,6 @@
"@scanQrCode": {}, "@scanQrCode": {},
"addToStory": "Dodaj do relacji", "addToStory": "Dodaj do relacji",
"@addToStory": {}, "@addToStory": {},
"typeInInviteLinkManually": "Wpisz link ręcznie...",
"@typeInInviteLinkManually": {},
"createNewSpace": "Nowa przestrzeń", "createNewSpace": "Nowa przestrzeń",
"@createNewSpace": { "@createNewSpace": {
"type": "text", "type": "text",
@ -2183,12 +2124,8 @@
"@unsubscribeStories": {}, "@unsubscribeStories": {},
"updateNow": "Rozpocznij aktualizację w tle", "updateNow": "Rozpocznij aktualizację w tle",
"@updateNow": {}, "@updateNow": {},
"dehydrateShare": "To jest twój prywatny eksport FluffyChat. Upewnij się, że nie zgubisz go i zachowaj go dla siebie.",
"@dehydrateShare": {},
"hydrateTorLong": "Czy ostatnio eksportowałeś/-aś swoją sesję na TOR? Szybko ją zaimportuj i kontynuuj rozmowy.", "hydrateTorLong": "Czy ostatnio eksportowałeś/-aś swoją sesję na TOR? Szybko ją zaimportuj i kontynuuj rozmowy.",
"@hydrateTorLong": {}, "@hydrateTorLong": {},
"noSearchResult": "Brak pasujących wyników wyszukiwania.",
"@noSearchResult": {},
"dehydrateTorLong": "W przypadku użytkowników sieci TOR zaleca się eksportowanie sesji przed zamknięciem okna.", "dehydrateTorLong": "W przypadku użytkowników sieci TOR zaleca się eksportowanie sesji przed zamknięciem okna.",
"@dehydrateTorLong": {}, "@dehydrateTorLong": {},
"hydrate": "Przywracanie z pliku kopii zapasowej", "hydrate": "Przywracanie z pliku kopii zapasowej",
@ -2267,11 +2204,6 @@
}, },
"commandHint_markasdm": "Oznacz jako pokój wiadomości bezpośrednich", "commandHint_markasdm": "Oznacz jako pokój wiadomości bezpośrednich",
"@commandHint_markasdm": {}, "@commandHint_markasdm": {},
"crossSigningEnabled": "Weryfikacja krzyżowa jest włączona",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"confirmMatrixId": "Potwierdź swój identyfikator Matrix w celu usunięcia konta.", "confirmMatrixId": "Potwierdź swój identyfikator Matrix w celu usunięcia konta.",
"@confirmMatrixId": {}, "@confirmMatrixId": {},
"commandHint_markasgroup": "Oznacz jako grupę", "commandHint_markasgroup": "Oznacz jako grupę",
@ -2333,8 +2265,6 @@
}, },
"noOtherDevicesFound": "Nie znaleziono innych urządzeń", "noOtherDevicesFound": "Nie znaleziono innych urządzeń",
"@noOtherDevicesFound": {}, "@noOtherDevicesFound": {},
"enableAutoBackups": "Włącz automatyczne tworzenie kopii zapasowych",
"@enableAutoBackups": {},
"widgetUrlError": "Niepoprawny URL.", "widgetUrlError": "Niepoprawny URL.",
"@widgetUrlError": {}, "@widgetUrlError": {},
"widgetNameError": "Podaj nazwę wyświetlaną.", "widgetNameError": "Podaj nazwę wyświetlaną.",

View File

@ -10,21 +10,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "segunda-feira",
"@monday": {
"type": "text",
"placeholders": {}
},
"saturday": "sábado",
"@saturday": {
"type": "text",
"placeholders": {}
},
"wednesday": "quarta-feira",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"about": "Sobre", "about": "Sobre",
"@about": { "@about": {
"type": "text", "type": "text",
@ -107,11 +92,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "terça-feira",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"logout": "Terminar sessão", "logout": "Terminar sessão",
"@logout": { "@logout": {
"type": "text", "type": "text",
@ -122,11 +102,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "domingo",
"@sunday": {
"type": "text",
"placeholders": {}
},
"users": "Utilizadores", "users": "Utilizadores",
"@users": {}, "@users": {},
"close": "Fechar", "close": "Fechar",
@ -141,15 +116,5 @@
"month": {}, "month": {},
"day": {} "day": {}
} }
},
"friday": "sexta-feira",
"@friday": {
"type": "text",
"placeholders": {}
},
"thursday": "quinta-feira",
"@thursday": {
"type": "text",
"placeholders": {}
} }
} }

View File

@ -81,11 +81,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Sala arquivada",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Usuários convidados podem participar", "areGuestsAllowedToJoin": "Usuários convidados podem participar",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -543,11 +538,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Assinatura cruzada ativada",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Ativo", "currentlyActive": "Ativo",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -633,11 +623,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Desvendar",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "O nome de exibição foi alterado", "displaynameHasBeenChanged": "O nome de exibição foi alterado",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -804,11 +789,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Sexta-feira",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Desde que entrou", "fromJoining": "Desde que entrou",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -999,11 +979,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Chaves guardadas",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} enxotou {targetName}", "kicked": "👞 {username} enxotou {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1138,11 +1113,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Segunda-feira",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Silenciar", "muteChat": "Silenciar",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1536,11 +1506,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Sábado",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Salvar arquivo", "saveFile": "Salvar arquivo",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1779,11 +1744,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Domingo",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Sincronizando… Por favor, aguarde.", "synchronizingPleaseWait": "Sincronizando… Por favor, aguarde.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1804,16 +1764,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Esta sala foi arquivada.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Quinta-feira",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1850,11 +1800,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Terça-feira",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Indisponível", "unavailable": "Indisponível",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -2025,11 +1970,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Quarta-feira",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Enviamos um e-mail para você", "weSentYouAnEmail": "Enviamos um e-mail para você",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2102,8 +2042,6 @@
}, },
"shareYourInviteLink": "Compartilhar o link do convite", "shareYourInviteLink": "Compartilhar o link do convite",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"typeInInviteLinkManually": "Digitar o link do convite manualmente...",
"@typeInInviteLinkManually": {},
"oneClientLoggedOut": "Um dos seus clientes foi desvinculado", "oneClientLoggedOut": "Um dos seus clientes foi desvinculado",
"@oneClientLoggedOut": {}, "@oneClientLoggedOut": {},
"addAccount": "Adicionar conta", "addAccount": "Adicionar conta",
@ -2176,8 +2114,6 @@
"@sendOnEnter": {}, "@sendOnEnter": {},
"homeserver": "Servidor matriz", "homeserver": "Servidor matriz",
"@homeserver": {}, "@homeserver": {},
"yourUserId": "Seu ID de usuário:",
"@yourUserId": {},
"chatHasBeenAddedToThisSpace": "A conversa foi adicionada a este espaço", "chatHasBeenAddedToThisSpace": "A conversa foi adicionada a este espaço",
"@chatHasBeenAddedToThisSpace": {}, "@chatHasBeenAddedToThisSpace": {},
"commandHint_clearcache": "Limpar dados temporários", "commandHint_clearcache": "Limpar dados temporários",
@ -2419,8 +2355,6 @@
"@commandHint_markasdm": {}, "@commandHint_markasdm": {},
"commandHint_markasgroup": "Marcar como grupo", "commandHint_markasgroup": "Marcar como grupo",
"@commandHint_markasgroup": {}, "@commandHint_markasgroup": {},
"dehydrateShare": "Este é seu extrato FluffyChat. Cuidado para não perdê-lo e o mantenha privado.",
"@dehydrateShare": {},
"hydrateTor": "Usuários TOR: Importar sessão", "hydrateTor": "Usuários TOR: Importar sessão",
"@hydrateTor": {}, "@hydrateTor": {},
"hydrateTorLong": "Você exportou sua última sessão no TOR? Importe ela rapidamente e continue conversando.", "hydrateTorLong": "Você exportou sua última sessão no TOR? Importe ela rapidamente e continue conversando.",
@ -2491,8 +2425,6 @@
"@dehydrateWarning": {}, "@dehydrateWarning": {},
"dehydrateTorLong": "Para usuários TOR, é recomendado exportar a sessão antes de fechar a janela.", "dehydrateTorLong": "Para usuários TOR, é recomendado exportar a sessão antes de fechar a janela.",
"@dehydrateTorLong": {}, "@dehydrateTorLong": {},
"enableAutoBackups": "Habilitar backups automáticos",
"@enableAutoBackups": {},
"whyIsThisMessageEncrypted": "Por que esta mensagem está ilegível?", "whyIsThisMessageEncrypted": "Por que esta mensagem está ilegível?",
"@whyIsThisMessageEncrypted": {}, "@whyIsThisMessageEncrypted": {},
"screenSharingTitle": "Compartilhar tela", "screenSharingTitle": "Compartilhar tela",

View File

@ -90,11 +90,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Sala arquivada",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Todos os visitantes podem entrar", "areGuestsAllowedToJoin": "Todos os visitantes podem entrar",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -294,8 +289,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "O teu ID de utilizador:",
"@yourUserId": {},
"yourChatBackupHasBeenSetUp": "A cópia de segurança foi configurada.", "yourChatBackupHasBeenSetUp": "A cópia de segurança foi configurada.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"chatBackup": "Cópia de segurança de conversas", "chatBackup": "Cópia de segurança de conversas",
@ -515,11 +508,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Assinatura cruzada ativada",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Ativo(a) agora", "currentlyActive": "Ativo(a) agora",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -605,11 +593,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Descobrir",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Nome de exibição alterado", "displaynameHasBeenChanged": "Nome de exibição alterado",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -778,11 +761,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Sexta-feira",
"@friday": {
"type": "text",
"placeholders": {}
},
"goToTheNewRoom": "Ir para a nova sala", "goToTheNewRoom": "Ir para a nova sala",
"@goToTheNewRoom": { "@goToTheNewRoom": {
"type": "text", "type": "text",
@ -963,11 +941,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Chaves estão armazenadas em cache",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} expulsou {targetName}", "kicked": "{username} expulsou {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1097,11 +1070,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Segunda-feira",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Silenciar conversa", "muteChat": "Silenciar conversa",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1167,8 +1135,6 @@
}, },
"shareYourInviteLink": "Partilhar a ligação de convite", "shareYourInviteLink": "Partilhar a ligação de convite",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"typeInInviteLinkManually": "Escrever a ligação de convite manualmente...",
"@typeInInviteLinkManually": {},
"none": "Nenhum", "none": "Nenhum",
"@none": { "@none": {
"type": "text", "type": "text",
@ -1581,11 +1547,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Sábado",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Guardar ficheiro", "saveFile": "Guardar ficheiro",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1709,8 +1670,6 @@
"@dehydrate": {}, "@dehydrate": {},
"dehydrateWarning": "Esta ação não pode ser revertida. Assegura-te que guardas bem a cópia de segurança.", "dehydrateWarning": "Esta ação não pode ser revertida. Assegura-te que guardas bem a cópia de segurança.",
"@dehydrateWarning": {}, "@dehydrateWarning": {},
"dehydrateShare": "Esta é a tua exportação privada do FluffyChat. Assegura-te que não a perdes e que a manténs privada.",
"@dehydrateShare": {},
"hydrateTorLong": "Exportaste a tua sessão na última vez que estiveste no TOR? Importa-a rapidamente e continua a conversar.", "hydrateTorLong": "Exportaste a tua sessão na última vez que estiveste no TOR? Importa-a rapidamente e continua a conversar.",
"@hydrateTorLong": {}, "@hydrateTorLong": {},
"dehydrateTor": "Utilizadores do TOR: Exportar sessão", "dehydrateTor": "Utilizadores do TOR: Exportar sessão",

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -55,11 +55,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Archivovaná miestnosť",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Môžu sa pripojiť hostia", "areGuestsAllowedToJoin": "Môžu sa pripojiť hostia",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -330,11 +325,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Vzájomné overenie je zapnuté",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Momentálne prítomní", "currentlyActive": "Momentálne prítomní",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -480,11 +470,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Piatok",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Od pripojenia", "fromJoining": "Od pripojenia",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -610,11 +595,6 @@
"username": {} "username": {}
} }
}, },
"keysCached": "Kľúče sú uložené",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} vyhodili {targetName}", "kicked": "{username} vyhodili {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -717,11 +697,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Pondelok",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Stlmiť chat", "muteChat": "Stlmiť chat",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -920,11 +895,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Sobota",
"@saturday": {
"type": "text",
"placeholders": {}
},
"seenByUser": "Videné užívateľom {username}", "seenByUser": "Videné užívateľom {username}",
"@seenByUser": { "@seenByUser": {
"type": "text", "type": "text",
@ -1060,11 +1030,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Nedeľa",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "Systémová farba", "systemTheme": "Systémová farba",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1080,16 +1045,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Táto miestnosť bola archivovaná.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Štvrtok",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1101,11 +1056,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Utorok",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unbannedUser": "{username} odbanovali {targetName}", "unbannedUser": "{username} odbanovali {targetName}",
"@unbannedUser": { "@unbannedUser": {
"type": "text", "type": "text",
@ -1256,11 +1206,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Streda",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"whoIsAllowedToJoinThisGroup": "Kto môže vstúpiť do tejto skupiny", "whoIsAllowedToJoinThisGroup": "Kto môže vstúpiť do tejto skupiny",
"@whoIsAllowedToJoinThisGroup": { "@whoIsAllowedToJoinThisGroup": {
"type": "text", "type": "text",
@ -1440,8 +1385,6 @@
}, },
"sendOnEnter": "Odoslať pri vstupe", "sendOnEnter": "Odoslať pri vstupe",
"@sendOnEnter": {}, "@sendOnEnter": {},
"yourUserId": "Vaše užívateľské ID:",
"@yourUserId": {},
"ignoredUsers": "Ignorovaní užívatelia", "ignoredUsers": "Ignorovaní užívatelia",
"@ignoredUsers": { "@ignoredUsers": {
"type": "text", "type": "text",

View File

@ -71,11 +71,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Arhivirana soba",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"askSSSSSign": "Če želite podpisati drugo osebo, vnesite geslo za varno trgovino ali obnovitveni ključ.", "askSSSSSign": "Če želite podpisati drugo osebo, vnesite geslo za varno trgovino ali obnovitveni ključ.",
"@askSSSSSign": { "@askSSSSSign": {
"type": "text", "type": "text",
@ -259,8 +254,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "Vaš ID uporabnika:",
"@yourUserId": {},
"yourChatBackupHasBeenSetUp": "Varnostna kopija klepeta je nastavljena.", "yourChatBackupHasBeenSetUp": "Varnostna kopija klepeta je nastavljena.",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"chatBackup": "Varnostno kopiranje klepeta", "chatBackup": "Varnostno kopiranje klepeta",
@ -558,11 +551,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Navzkrižno podpisovanje DA",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Trenutno aktiven", "currentlyActive": "Trenutno aktiven",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",

View File

@ -76,11 +76,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Архивирана соба",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Да ли је гостима дозвољен приступ", "areGuestsAllowedToJoin": "Да ли је гостима дозвољен приступ",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -504,11 +499,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Међу-потписивање укључено",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Тренутно активно", "currentlyActive": "Тренутно активно",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -594,11 +584,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Истражи",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Име за приказ је измењено", "displaynameHasBeenChanged": "Име за приказ је измењено",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -756,11 +741,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "петак",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "од приступања", "fromJoining": "од приступања",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -951,11 +931,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Кључеви су кеширани",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} избаци корисника {targetName}", "kicked": "{username} избаци корисника {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1080,11 +1055,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "понедељак",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Ућуткај ћаскање", "muteChat": "Ућуткај ћаскање",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1460,11 +1430,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "субота",
"@saturday": {
"type": "text",
"placeholders": {}
},
"search": "Претражи", "search": "Претражи",
"@search": { "@search": {
"type": "text", "type": "text",
@ -1674,11 +1639,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "недеља",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "системски", "systemTheme": "системски",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1694,16 +1654,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Ова соба је архивирана.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "четвртак",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1740,11 +1690,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "уторак",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Недоступно", "unavailable": "Недоступно",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1915,11 +1860,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "среда",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Послали смо вам е-пошту", "weSentYouAnEmail": "Послали смо вам е-пошту",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",

File diff suppressed because it is too large Load Diff

View File

@ -1 +1 @@
{} {}

View File

@ -84,11 +84,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Arşivlenmiş Oda",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Misafir kullanıcıların katılmasına izin veriliyor mu", "areGuestsAllowedToJoin": "Misafir kullanıcıların katılmasına izin veriliyor mu",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -548,11 +543,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Çapraz imzalama açık",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Şu anda etkin", "currentlyActive": "Şu anda etkin",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -638,11 +628,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Keşfet",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Görünen ad değiştirildi", "displaynameHasBeenChanged": "Görünen ad değiştirildi",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -809,11 +794,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Cuma",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Katılmadan", "fromJoining": "Katılmadan",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -1004,11 +984,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Anahtarlar önbelleğe alındı",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username}, {targetName} kişisini attı", "kicked": "👞 {username}, {targetName} kişisini attı",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1143,11 +1118,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Pazartesi",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Sohbeti sessize al", "muteChat": "Sohbeti sessize al",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1541,11 +1511,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Cumartesi",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "Dosyayı kaydet", "saveFile": "Dosyayı kaydet",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1784,11 +1749,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Pazar",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "Eşzamanlanıyor… Lütfen bekleyin.", "synchronizingPleaseWait": "Eşzamanlanıyor… Lütfen bekleyin.",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1809,16 +1769,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Bu oda arşivlendi.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Perşembe",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1855,11 +1805,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Salı",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Yok", "unavailable": "Yok",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -2030,11 +1975,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Çarşamba",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Size bir e-posta gönderdik", "weSentYouAnEmail": "Size bir e-posta gönderdik",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2107,8 +2047,6 @@
}, },
"scanQrCode": "QR kodunu tarayın", "scanQrCode": "QR kodunu tarayın",
"@scanQrCode": {}, "@scanQrCode": {},
"typeInInviteLinkManually": "Davet bağlantısını el ile yazın...",
"@typeInInviteLinkManually": {},
"shareYourInviteLink": "Davet bağlantınızı paylaşın", "shareYourInviteLink": "Davet bağlantınızı paylaşın",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"sendOnEnter": "Enter tuşu ile gönder", "sendOnEnter": "Enter tuşu ile gönder",
@ -2137,8 +2075,6 @@
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"unverified": "Doğrulanmadı", "unverified": "Doğrulanmadı",
"@unverified": {}, "@unverified": {},
"yourUserId": "Kullanıcı kimliğiniz:",
"@yourUserId": {},
"repeatPassword": "Parolayı tekrarlayın", "repeatPassword": "Parolayı tekrarlayın",
"@repeatPassword": {}, "@repeatPassword": {},
"passwordsDoNotMatch": "Parolalar eşleşmiyor!", "passwordsDoNotMatch": "Parolalar eşleşmiyor!",
@ -2380,8 +2316,6 @@
"@users": {}, "@users": {},
"storeInSecureStorageDescription": "Kurtarma anahtarını bu aygıtın güvenli deposunda saklayın.", "storeInSecureStorageDescription": "Kurtarma anahtarını bu aygıtın güvenli deposunda saklayın.",
"@storeInSecureStorageDescription": {}, "@storeInSecureStorageDescription": {},
"enableAutoBackups": "Otomatik yedeklemeleri etkinleştir",
"@enableAutoBackups": {},
"recoveryKey": "Kurtarma anahtarı", "recoveryKey": "Kurtarma anahtarı",
"@recoveryKey": {}, "@recoveryKey": {},
"stories": "Hikayeler", "stories": "Hikayeler",
@ -2414,8 +2348,6 @@
"@indexedDbErrorTitle": {}, "@indexedDbErrorTitle": {},
"dehydrateWarning": "Bu eylem geri alınamaz. Yedekleme dosyasını güvenli bir şekilde sakladığınızdan emin olun.", "dehydrateWarning": "Bu eylem geri alınamaz. Yedekleme dosyasını güvenli bir şekilde sakladığınızdan emin olun.",
"@dehydrateWarning": {}, "@dehydrateWarning": {},
"dehydrateShare": "Bu sizin özel FluffyChat dışa aktarımınızdır. Kaybetmediğinizden ve gizli tuttuğunuzdan emin olun.",
"@dehydrateShare": {},
"hydrateTorLong": "TOR'da en son oturumunuzu dışa aktardınız mı? Hızlıca içe aktarın ve sohbete devam edin.", "hydrateTorLong": "TOR'da en son oturumunuzu dışa aktardınız mı? Hızlıca içe aktarın ve sohbete devam edin.",
"@hydrateTorLong": {}, "@hydrateTorLong": {},
"indexedDbErrorLong": "Mesaj saklama özelliği ne yazık ki öntanımlı olarak gizli modda etkin değildir.\nLütfen\n - about:config sayfasına gidin ve\n - dom.indexedDB.privateBrowsing.enabled seçeneğini true olarak ayarlayın\nAksi takdirde FluffyChat çalıştırılamaz.", "indexedDbErrorLong": "Mesaj saklama özelliği ne yazık ki öntanımlı olarak gizli modda etkin değildir.\nLütfen\n - about:config sayfasına gidin ve\n - dom.indexedDB.privateBrowsing.enabled seçeneğini true olarak ayarlayın\nAksi takdirde FluffyChat çalıştırılamaz.",
@ -2532,8 +2464,6 @@
"@sorryThatsNotPossible": {}, "@sorryThatsNotPossible": {},
"deviceKeys": "Aygıt anahtarları:", "deviceKeys": "Aygıt anahtarları:",
"@deviceKeys": {}, "@deviceKeys": {},
"noSearchResult": "Eşleşen arama sonucu yok.",
"@noSearchResult": {},
"letsStart": "Başlayalım", "letsStart": "Başlayalım",
"@letsStart": {}, "@letsStart": {},
"enterInviteLinkOrMatrixId": "Davet bağlantısını veya Matris kimliğini girin...", "enterInviteLinkOrMatrixId": "Davet bağlantısını veya Matris kimliğini girin...",
@ -2560,5 +2490,25 @@
"jump": "Atla", "jump": "Atla",
"@jump": {}, "@jump": {},
"openLinkInBrowser": "Bağlantıyı tarayıcıda aç", "openLinkInBrowser": "Bağlantıyı tarayıcıda aç",
"@openLinkInBrowser": {} "@openLinkInBrowser": {},
"allRooms": "Tüm Grup Sohbetleri",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"discover": "Keşfet",
"@discover": {
"type": "text",
"placeholders": {}
},
"reportErrorDescription": "Olamaz. Bir şeyler yanlış gitti. Lütfen daha sonra tekrar deneyin. İsterseniz hatayı geliştiricilere bildirebilirsiniz.",
"@reportErrorDescription": {},
"report": "bildir",
"@report": {},
"signInWithPassword": "Parola ile oturum aç",
"@signInWithPassword": {},
"continueWith": "Devam et:",
"@continueWith": {},
"pleaseTryAgainLaterOrChooseDifferentServer": "Lütfen daha sonra tekrar deneyin veya farklı bir sunucu seçin.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {}
} }

View File

@ -62,11 +62,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Заархівована кімната",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Чи дозволено гостям приєднуватись", "areGuestsAllowedToJoin": "Чи дозволено гостям приєднуватись",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -337,11 +332,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Перехресне підписування увімкнено",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "Зараз у мережі", "currentlyActive": "Зараз у мережі",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -494,11 +484,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "П'ятниця",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "З моменту приєднання", "fromJoining": "З моменту приєднання",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -624,11 +609,6 @@
"username": {} "username": {}
} }
}, },
"keysCached": "Ключі кешовано",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} вилучає {targetName}", "kicked": "👞 {username} вилучає {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -731,11 +711,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Понеділок",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Вимкнути сповіщення", "muteChat": "Вимкнути сповіщення",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -934,11 +909,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Субота",
"@saturday": {
"type": "text",
"placeholders": {}
},
"seenByUser": "Переглянуто {username}", "seenByUser": "Переглянуто {username}",
"@seenByUser": { "@seenByUser": {
"type": "text", "type": "text",
@ -1066,11 +1036,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Неділя",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "Системна", "systemTheme": "Системна",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1086,16 +1051,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Цю кімнату було заархівовано.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "Четвер",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1107,11 +1062,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Вівторок",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unbannedUser": "{username} розблоковує {targetName}", "unbannedUser": "{username} розблоковує {targetName}",
"@unbannedUser": { "@unbannedUser": {
"type": "text", "type": "text",
@ -1255,11 +1205,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Середа",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"whoIsAllowedToJoinThisGroup": "Кому дозволено приєднуватися до цієї групи", "whoIsAllowedToJoinThisGroup": "Кому дозволено приєднуватися до цієї групи",
"@whoIsAllowedToJoinThisGroup": { "@whoIsAllowedToJoinThisGroup": {
"type": "text", "type": "text",
@ -1494,8 +1439,6 @@
}, },
"shareYourInviteLink": "Поділіться своїм посиланням запрошення", "shareYourInviteLink": "Поділіться своїм посиланням запрошення",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"typeInInviteLinkManually": "Введіть посилання запрошення власноруч...",
"@typeInInviteLinkManually": {},
"scanQrCode": "Сканувати QR-код", "scanQrCode": "Сканувати QR-код",
"@scanQrCode": {}, "@scanQrCode": {},
"noPasswordRecoveryDescription": "Ви ще не додали спосіб відновлення пароля.", "noPasswordRecoveryDescription": "Ви ще не додали спосіб відновлення пароля.",
@ -1851,8 +1794,6 @@
"type": "text", "type": "text",
"description": "Usage hint for the command /html" "description": "Usage hint for the command /html"
}, },
"yourUserId": "Ваш ID користувача:",
"@yourUserId": {},
"commandHint_invite": "Запросіть цього користувача до цієї кімнати", "commandHint_invite": "Запросіть цього користувача до цієї кімнати",
"@commandHint_invite": { "@commandHint_invite": {
"type": "text", "type": "text",
@ -1990,11 +1931,6 @@
"senderName": {} "senderName": {}
} }
}, },
"discover": "Огляд",
"@discover": {
"type": "text",
"placeholders": {}
},
"cantOpenUri": "Не вдалося відкрити URI {uri}", "cantOpenUri": "Не вдалося відкрити URI {uri}",
"@cantOpenUri": { "@cantOpenUri": {
"type": "text", "type": "text",
@ -2384,8 +2320,6 @@
"@recoveryKey": {}, "@recoveryKey": {},
"recoveryKeyLost": "Ключ відновлення втрачено?", "recoveryKeyLost": "Ключ відновлення втрачено?",
"@recoveryKeyLost": {}, "@recoveryKeyLost": {},
"enableAutoBackups": "Увімкнути автоматичне резервне копіювання",
"@enableAutoBackups": {},
"users": "Користувачі", "users": "Користувачі",
"@users": {}, "@users": {},
"stories": "Історії", "stories": "Історії",
@ -2412,8 +2346,6 @@
"@dehydrate": {}, "@dehydrate": {},
"dehydrateWarning": "Цю дію не можна скасувати. Переконайтеся, що ви безпечно зберігаєте файл резервної копії.", "dehydrateWarning": "Цю дію не можна скасувати. Переконайтеся, що ви безпечно зберігаєте файл резервної копії.",
"@dehydrateWarning": {}, "@dehydrateWarning": {},
"dehydrateShare": "Це ваш приватний експорт FluffyChat. Переконайтеся, що ви не втратите його та зберігайте його приватно.",
"@dehydrateShare": {},
"dehydrateTor": "Користувачі TOR: експорт сеансу", "dehydrateTor": "Користувачі TOR: експорт сеансу",
"@dehydrateTor": {}, "@dehydrateTor": {},
"dehydrateTorLong": "Для користувачів TOR рекомендується експортувати сеанс перед закриттям вікна.", "dehydrateTorLong": "Для користувачів TOR рекомендується експортувати сеанс перед закриттям вікна.",
@ -2532,8 +2464,6 @@
"@sorryThatsNotPossible": {}, "@sorryThatsNotPossible": {},
"deviceKeys": "Ключі пристрою:", "deviceKeys": "Ключі пристрою:",
"@deviceKeys": {}, "@deviceKeys": {},
"noSearchResult": "Немає відповідних результатів пошуку.",
"@noSearchResult": {},
"letsStart": "Розпочнімо", "letsStart": "Розпочнімо",
"@letsStart": {}, "@letsStart": {},
"enterInviteLinkOrMatrixId": "Введіть запрошувальне посилання або Matrix ID...", "enterInviteLinkOrMatrixId": "Введіть запрошувальне посилання або Matrix ID...",
@ -2560,5 +2490,25 @@
"jump": "Перейти", "jump": "Перейти",
"@jump": {}, "@jump": {},
"openLinkInBrowser": "Відкрити посилання у браузері", "openLinkInBrowser": "Відкрити посилання у браузері",
"@openLinkInBrowser": {} "@openLinkInBrowser": {},
"allRooms": "Усі групові бесіди",
"@allRooms": {
"type": "text",
"placeholders": {}
},
"reportErrorDescription": "О, ні. Щось пішло не так. Повторіть спробу пізніше. Якщо хочете, можете повідомити про помилку розробникам.",
"@reportErrorDescription": {},
"report": "повідомити",
"@report": {},
"discover": "Огляд",
"@discover": {
"type": "text",
"placeholders": {}
},
"pleaseTryAgainLaterOrChooseDifferentServer": "Спробуйте пізніше або виберіть інший сервер.",
"@pleaseTryAgainLaterOrChooseDifferentServer": {},
"signInWithPassword": "Увійти за допомогою пароля",
"@signInWithPassword": {},
"continueWith": "Продовжити за допомогою:",
"@continueWith": {}
} }

View File

@ -61,11 +61,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Phòng hội thảo đã lưu trữ",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Khách vãng lai có được tham gia không", "areGuestsAllowedToJoin": "Khách vãng lai có được tham gia không",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",

View File

@ -77,11 +77,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "已存档的聊天室",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "是否允许游客加入", "areGuestsAllowedToJoin": "是否允许游客加入",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -522,11 +517,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "交叉签名已启用",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "目前活跃", "currentlyActive": "目前活跃",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -612,11 +602,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "探索",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "显示名称已被改变", "displaynameHasBeenChanged": "显示名称已被改变",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -774,11 +759,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "星期五",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "自加入起", "fromJoining": "自加入起",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -969,11 +949,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "密钥已被缓存",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} 踢了 {targetName}", "kicked": "👞 {username} 踢了 {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1098,11 +1073,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "星期一",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "将该聊天静音", "muteChat": "将该聊天静音",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1478,11 +1448,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "星期六",
"@saturday": {
"type": "text",
"placeholders": {}
},
"saveFile": "保存文件", "saveFile": "保存文件",
"@saveFile": { "@saveFile": {
"type": "text", "type": "text",
@ -1706,11 +1671,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "星期日",
"@sunday": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "同步中…请等待。", "synchronizingPleaseWait": "同步中…请等待。",
"@synchronizingPleaseWait": { "@synchronizingPleaseWait": {
"type": "text", "type": "text",
@ -1731,16 +1691,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "该聊天室已被归档。",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "星期四",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1777,11 +1727,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "星期二",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "不可用", "unavailable": "不可用",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1952,11 +1897,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "星期三",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "我们向您发送了一封电子邮件", "weSentYouAnEmail": "我们向您发送了一封电子邮件",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2132,12 +2072,8 @@
"@pleaseEnterValidEmail": {}, "@pleaseEnterValidEmail": {},
"repeatPassword": "再次输入密码", "repeatPassword": "再次输入密码",
"@repeatPassword": {}, "@repeatPassword": {},
"yourUserId": "您的 ID",
"@yourUserId": {},
"shareYourInviteLink": "分享您的邀请链接", "shareYourInviteLink": "分享您的邀请链接",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"typeInInviteLinkManually": "手动输入邀请链接…",
"@typeInInviteLinkManually": {},
"addAccount": "添加账户", "addAccount": "添加账户",
"@addAccount": {}, "@addAccount": {},
"editBundlesForAccount": "编辑该账户的集合", "editBundlesForAccount": "编辑该账户的集合",
@ -2388,8 +2324,6 @@
"@storeInAndroidKeystore": {}, "@storeInAndroidKeystore": {},
"storeSecurlyOnThisDevice": "安全地存储在此设备上", "storeSecurlyOnThisDevice": "安全地存储在此设备上",
"@storeSecurlyOnThisDevice": {}, "@storeSecurlyOnThisDevice": {},
"enableAutoBackups": "启用自动备份",
"@enableAutoBackups": {},
"users": "用户", "users": "用户",
"@users": {}, "@users": {},
"stories": "故事", "stories": "故事",
@ -2400,8 +2334,6 @@
"count": {} "count": {}
} }
}, },
"dehydrateShare": "这是私人的 FluffyChat 导出。 确保你不会丢失它并将其保密。",
"@dehydrateShare": {},
"dehydrateTor": "TOR 用户:导出会话", "dehydrateTor": "TOR 用户:导出会话",
"@dehydrateTor": {}, "@dehydrateTor": {},
"dehydrateTorLong": "建议 TOR 用户在关闭窗口之前导出会话。", "dehydrateTorLong": "建议 TOR 用户在关闭窗口之前导出会话。",
@ -2531,5 +2463,12 @@
"sorryThatsNotPossible": "非常抱歉……这是做不到的", "sorryThatsNotPossible": "非常抱歉……这是做不到的",
"@sorryThatsNotPossible": {}, "@sorryThatsNotPossible": {},
"deviceKeys": "设备密钥:", "deviceKeys": "设备密钥:",
"@deviceKeys": {} "@deviceKeys": {},
"report": "举报",
"@report": {},
"discover": "探索",
"@discover": {
"type": "text",
"placeholders": {}
}
} }

View File

@ -76,11 +76,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "已封存的對話",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "是否允許訪客加入", "areGuestsAllowedToJoin": "是否允許訪客加入",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -427,11 +422,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "第三方登入已啟用",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "目前活躍", "currentlyActive": "目前活躍",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -517,11 +507,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "探索",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "顯示名稱已被變更", "displaynameHasBeenChanged": "顯示名稱已被變更",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -674,11 +659,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "星期五",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "自加入起", "fromJoining": "自加入起",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -864,11 +844,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "金鑰已被快取",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username}踢了{targetName}", "kicked": "{username}踢了{targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -986,11 +961,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "星期一",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "將該聊天室靜音", "muteChat": "將該聊天室靜音",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1326,11 +1296,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "星期六",
"@saturday": {
"type": "text",
"placeholders": {}
},
"search": "搜尋", "search": "搜尋",
"@search": { "@search": {
"type": "text", "type": "text",
@ -1530,11 +1495,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "星期日",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "自動", "systemTheme": "自動",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1550,16 +1510,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "這個聊天室已被封存。",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"thursday": "星期四",
"@thursday": {
"type": "text",
"placeholders": {}
},
"title": "FluffyChat", "title": "FluffyChat",
"@title": { "@title": {
"description": "Title for the application", "description": "Title for the application",
@ -1596,11 +1546,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "星期二",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "無法取得", "unavailable": "無法取得",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1771,11 +1716,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "星期三",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "我們向您傳送了一封電子郵件", "weSentYouAnEmail": "我們向您傳送了一封電子郵件",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -1972,8 +1912,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "您的ID",
"@yourUserId": {},
"chatHasBeenAddedToThisSpace": "聊天室已添加到此空間", "chatHasBeenAddedToThisSpace": "聊天室已添加到此空間",
"@chatHasBeenAddedToThisSpace": {}, "@chatHasBeenAddedToThisSpace": {},
"clearArchive": "清除存檔", "clearArchive": "清除存檔",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 212 KiB

After

Width:  |  Height:  |  Size: 146 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 52 KiB

View File

@ -55,7 +55,7 @@
<div class="flex mb-8 justify-center content-center"> <div class="flex mb-8 justify-center content-center">
<a rel="me" <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" 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://metalhead.club/@krille"> 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" <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" 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;"> style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:1.41421;">
@ -116,4 +116,4 @@
</body> </body>
</html> </html>

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -291,6 +291,7 @@
files = ( files = (
); );
inputPaths = ( inputPaths = (
"${TARGET_BUILD_DIR}/${INFOPLIST_PATH}",
); );
name = "Thin Binary"; name = "Thin Binary";
outputPaths = ( outputPaths = (

View File

@ -33,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';

View File

@ -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';
@ -27,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';
@ -266,23 +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(),
@ -358,23 +339,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(

View File

@ -41,6 +41,22 @@ abstract class FluffyThemes {
titleSmall: fallbackTextStyle, titleSmall: fallbackTextStyle,
); );
static LinearGradient backgroundGradient(
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 Duration animationDuration = Duration(milliseconds: 250);
static const Curve animationCurve = Curves.easeInOut; static const Curve animationCurve = Curves.easeInOut;

View File

@ -23,6 +23,7 @@ import 'package:fluffychat/pages/chat/chat_view.dart';
import 'package:fluffychat/pages/chat/event_info_dialog.dart'; import 'package:fluffychat/pages/chat/event_info_dialog.dart';
import 'package:fluffychat/pages/chat/recording_dialog.dart'; import 'package:fluffychat/pages/chat/recording_dialog.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
import 'package:fluffychat/utils/error_reporter.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/ios_badge_client_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/ios_badge_client_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
@ -76,7 +77,7 @@ class ChatPageWithRoom extends StatefulWidget {
} }
class ChatController extends State<ChatPageWithRoom> { class ChatController extends State<ChatPageWithRoom> {
Room get room => widget.room; Room get room => sendingClient.getRoomById(roomId) ?? widget.room;
late Client sendingClient; late Client sendingClient;
@ -151,7 +152,10 @@ class ChatController extends State<ChatPageWithRoom> {
Event? editEvent; Event? editEvent;
bool showScrollDownButton = false; bool _scrolledUp = false;
bool get showScrollDownButton =>
_scrolledUp || timeline?.allowNewEvent == false;
bool get selectMode => selectedEvents.isNotEmpty; bool get selectMode => selectedEvents.isNotEmpty;
@ -200,6 +204,7 @@ class ChatController extends State<ChatPageWithRoom> {
void requestHistory() async { void requestHistory() async {
if (!timeline!.canRequestHistory) return; if (!timeline!.canRequestHistory) return;
Logs().v('Requesting history...');
try { try {
await timeline!.requestHistory(historyCount: _loadHistoryCount); await timeline!.requestHistory(historyCount: _loadHistoryCount);
} catch (err) { } catch (err) {
@ -218,6 +223,7 @@ class ChatController extends State<ChatPageWithRoom> {
final timeline = this.timeline; final timeline = this.timeline;
if (timeline == null) return; if (timeline == null) return;
if (!timeline.canRequestFuture) return; if (!timeline.canRequestFuture) return;
Logs().v('Requesting future...');
try { try {
final mostRecentEventId = timeline.events.first.eventId; final mostRecentEventId = timeline.events.first.eventId;
await timeline.requestFuture(historyCount: _loadHistoryCount); await timeline.requestFuture(historyCount: _loadHistoryCount);
@ -240,18 +246,11 @@ class ChatController extends State<ChatPageWithRoom> {
} }
setReadMarker(); setReadMarker();
if (!scrollController.hasClients) return; if (!scrollController.hasClients) return;
if (scrollController.position.pixels ==
scrollController.position.maxScrollExtent) {
requestHistory();
} else if (scrollController.position.pixels == 0) {
requestFuture();
}
if (timeline?.allowNewEvent == false || if (timeline?.allowNewEvent == false ||
scrollController.position.pixels > 0 && showScrollDownButton == false) { scrollController.position.pixels > 0 && _scrolledUp == false) {
setState(() => showScrollDownButton = true); setState(() => _scrolledUp = true);
} else if (scrollController.position.pixels == 0 && } else if (scrollController.position.pixels == 0 && _scrolledUp == true) {
showScrollDownButton == true) { setState(() => _scrolledUp = false);
setState(() => showScrollDownButton = false);
} }
} }
@ -272,7 +271,10 @@ class ChatController extends State<ChatPageWithRoom> {
super.initState(); super.initState();
sendingClient = Matrix.of(context).client; sendingClient = Matrix.of(context).client;
readMarkerEventId = room.fullyRead; readMarkerEventId = room.fullyRead;
loadTimelineFuture = _getTimeline(); loadTimelineFuture =
_getTimeline(eventContextId: readMarkerEventId).onError(
ErrorReporter(context, 'Unable to load timeline').onErrorCallback,
);
} }
void updateView() { void updateView() {
@ -284,12 +286,12 @@ class ChatController extends State<ChatPageWithRoom> {
Future<void> _getTimeline({ Future<void> _getTimeline({
String? eventContextId, String? eventContextId,
Duration timeout = const Duration(seconds: 5), Duration timeout = const Duration(seconds: 7),
}) async { }) async {
await Matrix.of(context).client.roomsLoading; await Matrix.of(context).client.roomsLoading;
await Matrix.of(context).client.accountDataLoading; await Matrix.of(context).client.accountDataLoading;
eventContextId ??= room.fullyRead; if (eventContextId != null &&
if (!eventContextId.isValidMatrixId || eventContextId.sigil != '\$') { (!eventContextId.isValidMatrixId || eventContextId.sigil != '\$')) {
eventContextId = null; eventContextId = null;
} }
try { try {
@ -299,19 +301,22 @@ class ChatController extends State<ChatPageWithRoom> {
eventContextId: eventContextId, eventContextId: eventContextId,
) )
.timeout(timeout); .timeout(timeout);
} on TimeoutException catch (_) { } catch (e, s) {
Logs().w('Unable to load timeline on event ID $eventContextId', e, s);
if (!mounted) return; if (!mounted) return;
timeline = await room.getTimeline(onUpdate: updateView); timeline = await room.getTimeline(onUpdate: updateView);
if (!mounted) return; if (!mounted) return;
ScaffoldMessenger.of(context).showSnackBar( if (e is TimeoutException || e is IOException) {
SnackBar( ScaffoldMessenger.of(context).showSnackBar(
content: Text(L10n.of(context)!.jumpToLastReadMessage), SnackBar(
action: SnackBarAction( content: Text(L10n.of(context)!.jumpToLastReadMessage),
label: L10n.of(context)!.jump, action: SnackBarAction(
onPressed: () => scrollToEventId(eventContextId!), label: L10n.of(context)!.jump,
onPressed: () => scrollToEventId(eventContextId!),
),
), ),
), );
); }
} }
timeline!.requestKeys(onlineKeyBackupOnly: false); timeline!.requestKeys(onlineKeyBackupOnly: false);
if (timeline!.events.isNotEmpty) { if (timeline!.events.isNotEmpty) {
@ -351,7 +356,7 @@ class ChatController extends State<ChatPageWithRoom> {
eventId ??= timeline.events.first.eventId; eventId ??= timeline.events.first.eventId;
Logs().v('Set read marker...', eventId); Logs().v('Set read marker...', eventId);
// ignore: unawaited_futures // ignore: unawaited_futures
_setReadMarkerFuture = timeline.setReadMarker(eventId).then((_) { _setReadMarkerFuture = timeline.setReadMarker(eventId: eventId).then((_) {
_setReadMarkerFuture = null; _setReadMarkerFuture = null;
}); });
room.client.updateIosBadge(); room.client.updateIosBadge();
@ -368,7 +373,7 @@ class ChatController extends State<ChatPageWithRoom> {
TextEditingController sendController = TextEditingController(); TextEditingController sendController = TextEditingController();
void setSendingClient(Client c) { void setSendingClient(Client c) {
// first cancle typing with the old sending client // first cancel typing with the old sending client
if (currentlyTyping) { if (currentlyTyping) {
// no need to have the setting typing to false be blocking // no need to have the setting typing to false be blocking
typingCoolDown?.cancel(); typingCoolDown?.cancel();
@ -376,6 +381,15 @@ class ChatController extends State<ChatPageWithRoom> {
room.setTyping(false); room.setTyping(false);
currentlyTyping = false; currentlyTyping = false;
} }
// then cancel the old timeline
// fixes bug with read reciepts and quick switching
loadTimelineFuture = _getTimeline(eventContextId: room.fullyRead).onError(
ErrorReporter(
context,
'Unable to load timeline after changing sending Client',
).onErrorCallback,
);
// then set the new sending client // then set the new sending client
setState(() => sendingClient = c); setState(() => sendingClient = c);
} }
@ -393,7 +407,7 @@ class ChatController extends State<ChatPageWithRoom> {
final commandMatch = RegExp(r'^\/(\w+)').firstMatch(sendController.text); final commandMatch = RegExp(r'^\/(\w+)').firstMatch(sendController.text);
if (commandMatch != null && if (commandMatch != null &&
!room.client.commands.keys.contains(commandMatch[1]!.toLowerCase())) { !sendingClient.commands.keys.contains(commandMatch[1]!.toLowerCase())) {
final l10n = L10n.of(context)!; final l10n = L10n.of(context)!;
final dialogResult = await showOkCancelAlertDialog( final dialogResult = await showOkCancelAlertDialog(
context: context, context: context,
@ -801,9 +815,13 @@ class ChatController extends State<ChatPageWithRoom> {
if (eventIndex == -1) { if (eventIndex == -1) {
setState(() { setState(() {
timeline = null; timeline = null;
_scrolledUp = false;
loadTimelineFuture = _getTimeline( loadTimelineFuture = _getTimeline(
eventContextId: eventId, eventContextId: eventId,
timeout: const Duration(seconds: 30), timeout: const Duration(seconds: 30),
).onError(
ErrorReporter(context, 'Unable to load timeline after scroll to ID')
.onErrorCallback,
); );
}); });
await loadTimelineFuture; await loadTimelineFuture;
@ -823,7 +841,11 @@ class ChatController extends State<ChatPageWithRoom> {
if (!timeline!.allowNewEvent) { if (!timeline!.allowNewEvent) {
setState(() { setState(() {
timeline = null; timeline = null;
loadTimelineFuture = _getTimeline(); _scrolledUp = false;
loadTimelineFuture = _getTimeline().onError(
ErrorReporter(context, 'Unable to load timeline after scroll down')
.onErrorCallback,
);
}); });
await loadTimelineFuture; await loadTimelineFuture;
setReadMarker(eventId: timeline!.events.first.eventId); setReadMarker(eventId: timeline!.events.first.eventId);
@ -847,8 +869,11 @@ class ChatController extends State<ChatPageWithRoom> {
setState(() => showEmojiPicker = false); setState(() => showEmojiPicker = false);
if (emoji == null) return; if (emoji == null) return;
// make sure we don't send the same emoji twice // make sure we don't send the same emoji twice
if (_allReactionEvents if (_allReactionEvents.any(
.any((e) => e.content['m.relates_to']['key'] == emoji.emoji)) return; (e) => e.content.tryGetMap('m.relates_to')?['key'] == emoji.emoji,
)) {
return;
}
return sendEmojiAction(emoji.emoji); return sendEmojiAction(emoji.emoji);
} }

View File

@ -1,6 +1,5 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:scroll_to_index/scroll_to_index.dart'; import 'package:scroll_to_index/scroll_to_index.dart';
@ -54,14 +53,18 @@ class ChatEventList extends StatelessWidget {
); );
} }
if (controller.timeline!.canRequestFuture) { if (controller.timeline!.canRequestFuture) {
Center( return Builder(
child: OutlinedButton( builder: (context) {
style: OutlinedButton.styleFrom( WidgetsBinding.instance.addPostFrameCallback(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, (_) => controller.requestFuture(),
), );
onPressed: controller.requestFuture, return Center(
child: Text(L10n.of(context)!.loadMore), child: IconButton(
), onPressed: controller.requestFuture,
icon: const Icon(Icons.refresh_outlined),
),
);
},
); );
} }
return Column( return Column(
@ -81,14 +84,18 @@ class ChatEventList extends StatelessWidget {
); );
} }
if (controller.timeline!.canRequestHistory) { if (controller.timeline!.canRequestHistory) {
Center( return Builder(
child: OutlinedButton( builder: (context) {
style: OutlinedButton.styleFrom( WidgetsBinding.instance.addPostFrameCallback(
backgroundColor: Theme.of(context).scaffoldBackgroundColor, (_) => controller.requestHistory(),
), );
onPressed: controller.requestHistory, return Center(
child: Text(L10n.of(context)!.loadMore), child: IconButton(
), onPressed: controller.requestHistory,
icon: const Icon(Icons.refresh_outlined),
),
);
},
); );
} }
return const SizedBox.shrink(); return const SizedBox.shrink();

View File

@ -146,7 +146,6 @@ class ChatView extends StatelessWidget {
); );
} }
final bottomSheetPadding = FluffyThemes.isColumnMode(context) ? 16.0 : 8.0; final bottomSheetPadding = FluffyThemes.isColumnMode(context) ? 16.0 : 8.0;
final colorScheme = Theme.of(context).colorScheme;
return VWidgetGuard( return VWidgetGuard(
onSystemPop: (redirector) async { onSystemPop: (redirector) async {
@ -197,6 +196,7 @@ class ChatView extends StatelessWidget {
padding: const EdgeInsets.only(bottom: 56.0), padding: const EdgeInsets.only(bottom: 56.0),
child: FloatingActionButton( child: FloatingActionButton(
onPressed: controller.scrollDown, onPressed: controller.scrollDown,
heroTag: null,
mini: true, mini: true,
child: const Icon(Icons.arrow_downward_outlined), child: const Icon(Icons.arrow_downward_outlined),
), ),
@ -219,14 +219,9 @@ class ChatView extends StatelessWidget {
else else
Container( Container(
decoration: BoxDecoration( decoration: BoxDecoration(
gradient: LinearGradient( gradient: FluffyThemes.backgroundGradient(
begin: Alignment.topCenter, context,
colors: [ 64,
colorScheme.primaryContainer.withAlpha(64),
colorScheme.secondaryContainer.withAlpha(64),
colorScheme.tertiaryContainer.withAlpha(64),
colorScheme.primaryContainer.withAlpha(64),
],
), ),
), ),
), ),

View File

@ -20,7 +20,9 @@ class EncryptionButton extends StatelessWidget {
.where((s) => s.deviceLists != null), .where((s) => s.deviceLists != null),
builder: (context, snapshot) { builder: (context, snapshot) {
return FutureBuilder<EncryptionHealthState>( return FutureBuilder<EncryptionHealthState>(
future: room.calcEncryptionHealthState(), future: room.encrypted
? room.calcEncryptionHealthState()
: Future.value(EncryptionHealthState.allVerified),
builder: (BuildContext context, snapshot) => IconButton( builder: (BuildContext context, snapshot) => IconButton(
tooltip: room.encrypted tooltip: room.encrypted
? L10n.of(context)!.encrypted ? L10n.of(context)!.encrypted

View File

@ -4,12 +4,12 @@ import 'dart:io';
import 'package:flutter/foundation.dart'; import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:just_audio/just_audio.dart'; import 'package:just_audio/just_audio.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:path_provider/path_provider.dart'; import 'package:path_provider/path_provider.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/utils/error_reporter.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart';
import '../../../utils/matrix_sdk_extensions/event_extension.dart'; import '../../../utils/matrix_sdk_extensions/event_extension.dart';
@ -132,14 +132,10 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
} else { } else {
await audioPlayer.setAudioSource(MatrixFileAudioSource(matrixFile!)); await audioPlayer.setAudioSource(MatrixFileAudioSource(matrixFile!));
} }
audioPlayer.play().catchError((e, s) { audioPlayer.play().onError(
ScaffoldMessenger.of(context).showSnackBar( ErrorReporter(context, 'Unable to play audio message')
SnackBar( .onErrorCallback,
content: Text(L10n.of(context)!.oopsSomethingWentWrong), );
),
);
Logs().w('Error while playing audio', e, s);
});
} }
static const double buttonSize = 36; static const double buttonSize = 36;

View File

@ -36,19 +36,16 @@ class _CuteContentState extends State<CuteContent> {
return GestureDetector( return GestureDetector(
onTap: addOverlay, onTap: addOverlay,
child: SizedBox.square( child: Column(
dimension: 300, mainAxisSize: MainAxisSize.min,
child: Column( mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min, children: [
mainAxisAlignment: MainAxisAlignment.center, Text(
children: [ widget.event.text,
Text( style: const TextStyle(fontSize: 150),
widget.event.text, ),
style: const TextStyle(fontSize: 150), if (label != null) Text(label)
), ],
if (label != null) Text(label)
],
),
), ),
); );
}, },
@ -144,24 +141,26 @@ class _CuteEventOverlayState extends State<CuteEventOverlay>
return SizedBox( return SizedBox(
height: constraints.maxHeight, height: constraints.maxHeight,
width: constraints.maxWidth, width: constraints.maxWidth,
child: Stack( child: OverflowBox(
alignment: Alignment.bottomLeft, child: Stack(
fit: StackFit.expand, alignment: Alignment.bottomLeft,
children: items fit: StackFit.expand,
.map( children: items
(position) => Positioned( .map(
left: position.width * width, (position) => Positioned(
bottom: (height * left: position.width * width,
.25 * bottom: (height *
position.height * .25 *
(controller?.value ?? 0)) - position.height *
_CuteOverlayContent.size, (controller?.value ?? 0)) -
child: _CuteOverlayContent( _CuteOverlayContent.size,
emoji: widget.emoji, child: _CuteOverlayContent(
emoji: widget.emoji,
),
), ),
), )
) .toList(),
.toList(), ),
), ),
); );
}, },

View File

@ -1,31 +1,29 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:collection/collection.dart';
import 'package:flutter_matrix_html/flutter_html.dart'; import 'package:flutter_highlighter/flutter_highlighter.dart';
import 'package:flutter_highlighter/themes/shades-of-purple.dart';
import 'package:flutter_html/flutter_html.dart';
import 'package:flutter_html_table/flutter_html_table.dart';
import 'package:flutter_math_fork/flutter_math.dart';
import 'package:linkify/linkify.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/config/app_config.dart';
import '../../../config/app_config.dart'; import 'package:fluffychat/widgets/avatar.dart';
import '../../../config/setting_keys.dart'; import 'package:fluffychat/widgets/mxc_image.dart';
import '../../../utils/matrix_sdk_extensions/matrix_locals.dart';
import '../../../utils/url_launcher.dart'; import '../../../utils/url_launcher.dart';
class HtmlMessage extends StatelessWidget { class HtmlMessage extends StatelessWidget {
final String html; final String html;
final int? maxLines;
final Room room; final Room room;
final TextStyle? defaultTextStyle; final Color textColor;
final TextStyle? linkStyle;
final double? emoteSize;
const HtmlMessage({ const HtmlMessage({
Key? key, Key? key,
required this.html, required this.html,
this.maxLines,
required this.room, required this.room,
this.defaultTextStyle, this.textColor = Colors.black,
this.linkStyle,
this.emoteSize,
}) : super(key: key); }) : super(key: key);
@override @override
@ -46,101 +44,461 @@ class HtmlMessage extends StatelessWidget {
'', '',
); );
// there is no need to pre-validate the html, as we validate it while rendering final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor;
final matrix = Matrix.of(context); final linkifiedRenderHtml = linkify(
renderHtml,
final themeData = Theme.of(context); options: const LinkifyOptions(humanize: false),
return Html( )
data: renderHtml, .map(
defaultTextStyle: defaultTextStyle, (element) {
emoteSize: emoteSize, if (element is! UrlElement ||
linkStyle: linkStyle ?? element.text.contains('<') ||
themeData.textTheme.bodyMedium!.copyWith( element.text.contains('>') ||
color: themeData.colorScheme.secondary, element.text.contains('"')) {
decoration: TextDecoration.underline, return element.text;
decorationColor: themeData.colorScheme.secondary,
),
shrinkToFit: true,
maxLines: maxLines,
onLinkTap: (url) => UrlLauncher(context, url).launchUrl(),
onPillTap: (url) => UrlLauncher(context, url).launchUrl(),
getMxcUrl: (
String mxc,
double? width,
double? height, {
bool? animated = false,
}) {
final ratio = MediaQuery.of(context).devicePixelRatio;
return Uri.parse(mxc)
.getThumbnail(
matrix.client,
width: (width ?? 800) * ratio,
height: (height ?? 800) * ratio,
method: ThumbnailMethod.scale,
animated: AppConfig.autoplayImages ? animated : false,
)
.toString();
},
onImageTap: (url) => UrlLauncher(context, url).launchUrl(),
setCodeLanguage: (String key, String value) async {
await matrix.store.setItem('${SettingKeys.codeLanguage}.$key', value);
},
getCodeLanguage: (String key) async {
return await matrix.store.getItem('${SettingKeys.codeLanguage}.$key');
},
getPillInfo: (String url) async {
final identityParts = url.parseIdentifierIntoParts();
final identifier = identityParts?.primaryIdentifier;
if (identifier == null) {
return {};
}
if (identifier.sigil == '@') {
// we have a user pill
final user = room.getState('m.room.member', identifier);
if (user != null) {
return user.content;
}
// there might still be a profile...
final profile = await room.client.getProfileFromUserId(identifier);
return {
'displayname': profile.displayName,
'avatar_url': profile.avatarUrl.toString(),
};
}
if (identifier.sigil == '#') {
// we have an alias pill
for (final r in room.client.rooms) {
final state = r.getState('m.room.canonical_alias');
if (state != null &&
((state.content['alias'] is String &&
state.content['alias'] == identifier) ||
(state.content['alt_aliases'] is List &&
state.content['alt_aliases'].contains(identifier)))) {
// we have a room!
return {
'displayname':
r.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)),
'avatar_url': r.getState('m.room.avatar')?.content['url'],
};
} }
} return '<a href="${element.url}">${element.text}</a>';
return {}; },
} )
if (identifier.sigil == '!') { .join('')
// we have a room ID pill .replaceAll('\n', '');
final r = room.client.getRoomById(identifier);
if (r == null) { final linkColor = textColor.withAlpha(150);
return {};
} // there is no need to pre-validate the html, as we validate it while rendering
return { return Html(
'displayname': data: linkifiedRenderHtml,
r.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)), style: {
'avatar_url': r.getState('m.room.avatar')?.content['url'], '*': Style(
}; color: textColor,
} margin: Margins.all(0),
return {}; fontSize: FontSize(fontSize),
),
'a': Style(color: linkColor, textDecorationColor: linkColor),
'h1': Style(
fontSize: FontSize(fontSize * 2),
lineHeight: LineHeight.number(1.5),
fontWeight: FontWeight.w600,
),
'h2': Style(
fontSize: FontSize(fontSize * 1.75),
lineHeight: LineHeight.number(1.5),
fontWeight: FontWeight.w500,
),
'h3': Style(
fontSize: FontSize(fontSize * 1.5),
lineHeight: LineHeight.number(1.5),
),
'h4': Style(
fontSize: FontSize(fontSize * 1.25),
lineHeight: LineHeight.number(1.5),
),
'h5': Style(
fontSize: FontSize(fontSize * 1.25),
lineHeight: LineHeight.number(1.5),
),
'h6': Style(
fontSize: FontSize(fontSize),
lineHeight: LineHeight.number(1.5),
),
'blockquote': Style(
border: Border(
left: BorderSide(
width: 3,
color: textColor,
),
),
padding: HtmlPaddings.only(left: 6, bottom: 0),
),
'hr': Style(
border: Border.all(color: textColor, width: 0.5),
),
'table': Style(
border: Border.all(color: textColor, width: 0.5),
),
'tr': Style(
border: Border.all(color: textColor, width: 0.5),
),
'td': Style(
border: Border.all(color: textColor, width: 0.5),
padding: HtmlPaddings.all(2),
),
'th': Style(
border: Border.all(color: textColor, width: 0.5),
),
}, },
extensions: [
RoomPillExtension(context, room),
CodeExtension(fontSize: fontSize),
MatrixMathExtension(
style: TextStyle(fontSize: fontSize, color: textColor),
),
const TableHtmlExtension(),
SpoilerExtension(textColor: textColor),
const ImageExtension(),
FontColorExtension(),
],
onLinkTap: (url, _, __) => UrlLauncher(context, url).launchUrl(),
onlyRenderTheseTags: const {
...allowedHtmlTags,
// Needed to make it work properly
'body',
'html',
},
shrinkWrap: true,
);
}
/// Keep in sync with: https://spec.matrix.org/v1.6/client-server-api/#mroommessage-msgtypes
static const Set<String> allowedHtmlTags = {
'font',
'del',
'h1',
'h2',
'h3',
'h4',
'h5',
'h6',
'blockquote',
'p',
'a',
'ul',
'ol',
'sup',
'sub',
'li',
'b',
'i',
'u',
'strong',
'em',
'strike',
'code',
'hr',
'br',
'div',
'table',
'thead',
'tbody',
'tr',
'th',
'td',
'caption',
'pre',
'span',
'img',
'details',
'summary',
// Not in the allowlist of the matrix spec yet but should be harmless:
'ruby',
'rp',
'rt',
};
}
class FontColorExtension extends HtmlExtension {
static const String colorAttribute = 'color';
static const String mxColorAttribute = 'data-mx-color';
static const String bgColorAttribute = 'data-mx-bg-color';
@override
Set<String> get supportedTags => {'font', 'span'};
@override
bool matches(ExtensionContext context) {
if (!supportedTags.contains(context.elementName)) return false;
return context.element?.attributes.keys.any(
{
colorAttribute,
mxColorAttribute,
bgColorAttribute,
}.contains,
) ??
false;
}
Color? hexToColor(String? hexCode) {
if (hexCode == null) return null;
if (hexCode.startsWith('#')) hexCode = hexCode.substring(1);
if (hexCode.length == 6) hexCode = 'FF$hexCode';
final colorValue = int.tryParse(hexCode, radix: 16);
return colorValue == null ? null : Color(colorValue);
}
@override
InlineSpan build(
ExtensionContext context,
) {
final colorText = context.element?.attributes[colorAttribute] ??
context.element?.attributes[mxColorAttribute];
final bgColor = context.element?.attributes[bgColorAttribute];
return TextSpan(
style: TextStyle(
color: hexToColor(colorText),
backgroundColor: hexToColor(bgColor),
),
text: context.innerHtml,
);
}
}
class ImageExtension extends HtmlExtension {
final double defaultDimension;
const ImageExtension({this.defaultDimension = 64});
@override
Set<String> get supportedTags => {'img'};
@override
InlineSpan build(ExtensionContext context) {
final mxcUrl = Uri.tryParse(context.attributes['src'] ?? '');
if (mxcUrl == null || mxcUrl.scheme != 'mxc') {
return TextSpan(text: context.attributes['alt']);
}
final width = double.tryParse(context.attributes['width'] ?? '');
final height = double.tryParse(context.attributes['height'] ?? '');
return WidgetSpan(
child: SizedBox(
width: width ?? height ?? defaultDimension,
height: height ?? width ?? defaultDimension,
child: MxcImage(
uri: mxcUrl,
width: width ?? height ?? defaultDimension,
height: height ?? width ?? defaultDimension,
cacheKey: mxcUrl.toString(),
),
),
);
}
}
class SpoilerExtension extends HtmlExtension {
final Color textColor;
const SpoilerExtension({required this.textColor});
@override
Set<String> get supportedTags => {'span'};
static const String customDataAttribute = 'data-mx-spoiler';
@override
bool matches(ExtensionContext context) {
if (context.elementName != 'span') return false;
return context.element?.attributes.containsKey(customDataAttribute) ??
false;
}
@override
InlineSpan build(ExtensionContext context) {
var obscure = true;
final children = context.inlineSpanChildren;
return WidgetSpan(
child: StatefulBuilder(
builder: (context, setState) {
return InkWell(
onTap: () => setState(() {
obscure = !obscure;
}),
child: RichText(
text: TextSpan(
style: obscure ? TextStyle(backgroundColor: textColor) : null,
children: children,
),
),
);
},
),
);
}
}
class MatrixMathExtension extends HtmlExtension {
final TextStyle? style;
MatrixMathExtension({this.style});
@override
Set<String> get supportedTags => {'div'};
@override
bool matches(ExtensionContext context) {
if (context.elementName != 'div') return false;
final mathData = context.element?.attributes['data-mx-maths'];
return mathData != null;
}
@override
InlineSpan build(ExtensionContext context) {
final data = context.element?.attributes['data-mx-maths'] ?? '';
return WidgetSpan(
child: Math.tex(
data,
textStyle: style,
onErrorFallback: (e) {
Logs().d('Flutter math parse error', e);
return Text(
data,
style: style,
);
},
),
);
}
}
class CodeExtension extends HtmlExtension {
final double fontSize;
CodeExtension({required this.fontSize});
@override
Set<String> get supportedTags => {'code'};
@override
InlineSpan build(ExtensionContext context) => WidgetSpan(
child: Material(
clipBehavior: Clip.hardEdge,
borderRadius: BorderRadius.circular(4),
child: SingleChildScrollView(
scrollDirection: Axis.horizontal,
child: HighlightView(
context.element?.text ?? '',
language: context.element?.className
.split(' ')
.singleWhereOrNull(
(className) => className.startsWith('language-'),
)
?.split('language-')
.last ??
'md',
theme: shadesOfPurpleTheme,
padding: EdgeInsets.symmetric(
horizontal: 6,
vertical: context.element?.parent?.localName == 'pre' ? 6 : 0,
),
textStyle: TextStyle(fontSize: fontSize),
),
),
),
);
}
class RoomPillExtension extends HtmlExtension {
final Room room;
final BuildContext context;
RoomPillExtension(this.context, this.room);
@override
Set<String> get supportedTags => {'a'};
@override
bool matches(ExtensionContext context) {
if (context.elementName != 'a') return false;
final userId = context.element?.attributes['href']
?.parseIdentifierIntoParts()
?.primaryIdentifier;
return userId != null;
}
static final _cachedUsers = <String, User?>{};
Future<User?> _fetchUser(String matrixId) async =>
_cachedUsers[room.id + matrixId] ??= await room.requestUser(matrixId);
@override
InlineSpan build(ExtensionContext context) {
final href = context.element?.attributes['href'];
final matrixId = href?.parseIdentifierIntoParts()?.primaryIdentifier;
if (href == null || matrixId == null) {
return TextSpan(text: context.innerHtml);
}
if (matrixId.sigil == '@') {
return WidgetSpan(
child: FutureBuilder<User?>(
future: _fetchUser(matrixId),
builder: (context, snapshot) => MatrixPill(
key: Key('user_pill_$matrixId'),
name: _cachedUsers[room.id + matrixId]?.calcDisplayname() ??
matrixId.localpart ??
matrixId,
avatar: _cachedUsers[room.id + matrixId]?.avatarUrl,
uri: href,
outerContext: this.context,
),
),
);
}
if (matrixId.sigil == '#' || matrixId.sigil == '!') {
final room = matrixId.sigil == '!'
? this.room.client.getRoomById(matrixId)
: this.room.client.getRoomByAlias(matrixId);
if (room != null) {
return WidgetSpan(
child: MatrixPill(
name: room.getLocalizedDisplayname(),
avatar: room.avatar,
uri: href,
outerContext: this.context,
),
);
}
}
return TextSpan(text: context.innerHtml);
}
}
class MatrixPill extends StatelessWidget {
final String name;
final BuildContext outerContext;
final Uri? avatar;
final String uri;
const MatrixPill({
super.key,
required this.name,
required this.outerContext,
this.avatar,
required this.uri,
});
@override
Widget build(BuildContext context) {
return InkWell(
onTap: UrlLauncher(outerContext, uri).launchUrl,
child: Material(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
side: BorderSide(
color: Theme.of(outerContext).colorScheme.onPrimaryContainer,
width: 0.5,
),
),
color: Theme.of(outerContext).colorScheme.primaryContainer,
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 6.0),
child: Row(
mainAxisSize: MainAxisSize.min,
children: [
Avatar(
mxContent: avatar,
name: name,
size: 16,
),
const SizedBox(width: 6),
Text(
name,
style: TextStyle(
color: Theme.of(outerContext).colorScheme.onPrimaryContainer,
),
),
],
),
),
),
); );
} }
} }

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:matrix_link_text/link_text.dart';
import 'package:fluffychat/pages/chat/events/video_player.dart'; import 'package:fluffychat/pages/chat/events/video_player.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
@ -150,23 +150,10 @@ class MessageContent extends StatelessWidget {
if (event.messageType == MessageTypes.Emote) { if (event.messageType == MessageTypes.Emote) {
html = '* $html'; html = '* $html';
} }
final bigEmotes = event.onlyEmotes &&
event.numberEmotes > 0 &&
event.numberEmotes <= 10;
return HtmlMessage( return HtmlMessage(
html: html, html: html,
defaultTextStyle: TextStyle( textColor: textColor,
color: textColor,
fontSize: bigEmotes ? fontSize * 3 : fontSize,
),
linkStyle: TextStyle(
color: textColor.withAlpha(150),
fontSize: bigEmotes ? fontSize * 3 : fontSize,
decoration: TextDecoration.underline,
decorationColor: textColor.withAlpha(150),
),
room: event.room, room: event.room,
emoteSize: bigEmotes ? fontSize * 3 : fontSize * 1.5,
); );
} }
// else we fall through to the normal message rendering // else we fall through to the normal message rendering
@ -242,25 +229,26 @@ class MessageContent extends StatelessWidget {
hideReply: true, hideReply: true,
), ),
builder: (context, snapshot) { builder: (context, snapshot) {
return LinkText( return Linkify(
text: snapshot.data ?? text: snapshot.data ??
event.calcLocalizedBodyFallback( event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!), MatrixLocals(L10n.of(context)!),
hideReply: true, hideReply: true,
), ),
textStyle: TextStyle( style: TextStyle(
color: textColor, color: textColor,
fontSize: bigEmotes ? fontSize * 3 : fontSize, fontSize: bigEmotes ? fontSize * 3 : fontSize,
decoration: decoration:
event.redacted ? TextDecoration.lineThrough : null, event.redacted ? TextDecoration.lineThrough : null,
), ),
options: const LinkifyOptions(humanize: false),
linkStyle: TextStyle( linkStyle: TextStyle(
color: textColor.withAlpha(150), color: textColor.withAlpha(150),
fontSize: bigEmotes ? fontSize * 3 : fontSize, fontSize: bigEmotes ? fontSize * 3 : fontSize,
decoration: TextDecoration.underline, decoration: TextDecoration.underline,
decorationColor: textColor.withAlpha(150), decorationColor: textColor.withAlpha(150),
), ),
onLinkTap: (url) => UrlLauncher(context, url).launchUrl(), onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
); );
}, },
); );

View File

@ -37,14 +37,17 @@ class MessageDownloadContent extends StatelessWidget {
color: textColor, color: textColor,
), ),
const SizedBox(width: 16), const SizedBox(width: 16),
Text( Flexible(
filename, child: Text(
maxLines: 1, filename,
style: TextStyle( maxLines: 1,
color: textColor, style: TextStyle(
fontWeight: FontWeight.bold, color: textColor,
fontWeight: FontWeight.bold,
),
overflow: TextOverflow.ellipsis,
), ),
), )
], ],
), ),
), ),

View File

@ -61,7 +61,7 @@ class MessageReactions extends StatelessWidget {
final evt = allReactionEvents.firstWhereOrNull( final evt = allReactionEvents.firstWhereOrNull(
(e) => (e) =>
e.senderId == e.room.client.userID && e.senderId == e.room.client.userID &&
e.content['m.relates_to']['key'] == r.key, e.content.tryGetMap('m.relates_to')?['key'] == r.key,
); );
if (evt != null) { if (evt != null) {
showFutureLoadingDialog( showFutureLoadingDialog(

View File

@ -5,7 +5,6 @@ import 'package:matrix/matrix.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/matrix_locals.dart';
import '../../../config/app_config.dart'; import '../../../config/app_config.dart';
import 'html_message.dart';
class ReplyContent extends StatelessWidget { class ReplyContent extends StatelessWidget {
final Event replyEvent; final Event replyEvent;
@ -26,47 +25,23 @@ class ReplyContent extends StatelessWidget {
final displayEvent = final displayEvent =
timeline != null ? replyEvent.getDisplayEvent(timeline) : replyEvent; timeline != null ? replyEvent.getDisplayEvent(timeline) : replyEvent;
final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor; final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor;
if (AppConfig.renderHtml &&
[EventTypes.Message, EventTypes.Encrypted] replyBody = Text(
.contains(displayEvent.type) && displayEvent.calcLocalizedBodyFallback(
[MessageTypes.Text, MessageTypes.Notice, MessageTypes.Emote] MatrixLocals(L10n.of(context)!),
.contains(displayEvent.messageType) && withSenderNamePrefix: false,
!displayEvent.redacted && hideReply: true,
displayEvent.content['format'] == 'org.matrix.custom.html' && ),
displayEvent.content['formatted_body'] is String) { overflow: TextOverflow.ellipsis,
String? html = displayEvent.content['formatted_body']; maxLines: 1,
if (displayEvent.messageType == MessageTypes.Emote) { style: TextStyle(
html = '* $html'; color: ownMessage
} ? Theme.of(context).colorScheme.onPrimary
replyBody = HtmlMessage( : Theme.of(context).colorScheme.onBackground,
html: html!, fontSize: fontSize,
defaultTextStyle: TextStyle( ),
color: ownMessage );
? Theme.of(context).colorScheme.onPrimary
: Theme.of(context).colorScheme.onBackground,
fontSize: fontSize,
),
maxLines: 1,
room: displayEvent.room,
emoteSize: fontSize * 1.5,
);
} else {
replyBody = Text(
displayEvent.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false,
hideReply: true,
),
overflow: TextOverflow.ellipsis,
maxLines: 1,
style: TextStyle(
color: ownMessage
? Theme.of(context).colorScheme.onPrimary
: Theme.of(context).colorScheme.onBackground,
fontSize: fontSize,
),
);
}
return Row( return Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: <Widget>[ children: <Widget>[

View File

@ -14,6 +14,7 @@ import 'package:video_player/video_player.dart';
import 'package:fluffychat/pages/chat/events/image_bubble.dart'; import 'package:fluffychat/pages/chat/events/image_bubble.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart'; import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/event_extension.dart';
import '../../../utils/error_reporter.dart';
class EventVideoPlayer extends StatefulWidget { class EventVideoPlayer extends StatefulWidget {
final Event event; final Event event;
@ -51,7 +52,8 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
final networkUri = _networkUri; final networkUri = _networkUri;
if (kIsWeb && networkUri != null && _chewieManager == null) { if (kIsWeb && networkUri != null && _chewieManager == null) {
_chewieManager ??= ChewieController( _chewieManager ??= ChewieController(
videoPlayerController: VideoPlayerController.network(networkUri), videoPlayerController:
VideoPlayerController.networkUrl(Uri.parse(networkUri)),
autoPlay: true, autoPlay: true,
autoInitialize: true, autoInitialize: true,
); );
@ -69,12 +71,7 @@ class EventVideoPlayerState extends State<EventVideoPlayer> {
), ),
); );
} catch (e, s) { } catch (e, s) {
ScaffoldMessenger.of(context).showSnackBar( ErrorReporter(context, 'Unable to play video').onErrorCallback(e, s);
SnackBar(
content: Text(e.toLocalizedString(context)),
),
);
Logs().w('Error while playing video', e, s);
} finally { } finally {
// Workaround for Chewie needs time to get the aspectRatio // Workaround for Chewie needs time to get the aspectRatio
await Future.delayed(const Duration(milliseconds: 100)); await Future.delayed(const Duration(milliseconds: 100));

View File

@ -183,12 +183,13 @@ class InputBar extends StatelessWidget {
final state = r.getState(EventTypes.RoomCanonicalAlias); final state = r.getState(EventTypes.RoomCanonicalAlias);
if ((state != null && if ((state != null &&
((state.content['alias'] is String && ((state.content['alias'] is String &&
state.content['alias'] state.content
.tryGet<String>('alias')!
.split(':')[0] .split(':')[0]
.toLowerCase() .toLowerCase()
.contains(roomSearch)) || .contains(roomSearch)) ||
(state.content['alt_aliases'] is List && (state.content['alt_aliases'] is List &&
state.content['alt_aliases'].any( (state.content['alt_aliases'] as List).any(
(l) => (l) =>
l is String && l is String &&
l l
@ -263,6 +264,8 @@ class InputBar extends StatelessWidget {
crossAxisAlignment: CrossAxisAlignment.center, crossAxisAlignment: CrossAxisAlignment.center,
children: <Widget>[ children: <Widget>[
MxcImage( MxcImage(
// ensure proper ordering ...
key: ValueKey(suggestion['name']),
uri: suggestion['mxc'] is String uri: suggestion['mxc'] is String
? Uri.parse(suggestion['mxc'] ?? '') ? Uri.parse(suggestion['mxc'] ?? '')
: null, : null,

View File

@ -4,8 +4,8 @@ import 'package:flutter/material.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart'; import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:matrix_link_text/link_text.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/chat/chat.dart'; import 'package:fluffychat/pages/chat/chat.dart';
@ -101,15 +101,16 @@ class PinnedEvents extends StatelessWidget {
hideReply: true, hideReply: true,
), ),
builder: (context, snapshot) { builder: (context, snapshot) {
return LinkText( return Linkify(
text: snapshot.data ?? text: snapshot.data ??
event.calcLocalizedBodyFallback( event.calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!), MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: true, withSenderNamePrefix: true,
hideReply: true, hideReply: true,
), ),
options: const LinkifyOptions(humanize: false),
maxLines: 2, maxLines: 2,
textStyle: TextStyle( style: TextStyle(
color: color:
Theme.of(context).colorScheme.onSurfaceVariant, Theme.of(context).colorScheme.onSurfaceVariant,
overflow: TextOverflow.ellipsis, overflow: TextOverflow.ellipsis,
@ -126,8 +127,8 @@ class PinnedEvents extends StatelessWidget {
decorationColor: decorationColor:
Theme.of(context).colorScheme.onSurfaceVariant, Theme.of(context).colorScheme.onSurfaceVariant,
), ),
onLinkTap: (url) => onOpen: (url) =>
UrlLauncher(context, url).launchUrl(), UrlLauncher(context, url.url).launchUrl(),
); );
}, },
), ),

View File

@ -52,7 +52,7 @@ class ReactionsPicker extends StatelessWidget {
for (final event in allReactionEvents) { for (final event in allReactionEvents) {
try { try {
emojis.remove(event.content['m.relates_to']['key']); emojis.remove(event.content.tryGetMap('m.relates_to')!['key']);
} catch (_) {} } catch (_) {}
} }
return Row( return Row(

View File

@ -83,7 +83,9 @@ class ChatDetailsController extends State<ChatDetails> {
RequestType.GET, RequestType.GET,
'/client/unstable/org.matrix.msc2432/rooms/${Uri.encodeComponent(room.id)}/aliases', '/client/unstable/org.matrix.msc2432/rooms/${Uri.encodeComponent(room.id)}/aliases',
) )
.then((response) => List<String>.from(response['aliases'])), .then(
(response) => List<String>.from(response['aliases'] as Iterable),
),
); );
// Switch to the stable api once it is implemented. // Switch to the stable api once it is implemented.

View File

@ -1,8 +1,8 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_linkify/flutter_linkify.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:matrix_link_text/link_text.dart';
import 'package:vrouter/vrouter.dart'; import 'package:vrouter/vrouter.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
@ -125,13 +125,14 @@ class ChatDetailsView extends StatelessWidget {
padding: const EdgeInsets.symmetric( padding: const EdgeInsets.symmetric(
horizontal: 16.0, horizontal: 16.0,
), ),
child: LinkText( child: Linkify(
text: room.topic.isEmpty text: room.topic.isEmpty
? L10n.of(context)!.addGroupDescription ? L10n.of(context)!.addGroupDescription
: room.topic, : room.topic,
options: const LinkifyOptions(humanize: false),
linkStyle: linkStyle:
const TextStyle(color: Colors.blueAccent), const TextStyle(color: Colors.blueAccent),
textStyle: TextStyle( style: TextStyle(
fontSize: 14, fontSize: 14,
color: Theme.of(context) color: Theme.of(context)
.textTheme .textTheme
@ -142,8 +143,8 @@ class ChatDetailsView extends StatelessWidget {
.bodyMedium! .bodyMedium!
.color, .color,
), ),
onLinkTap: (url) => onOpen: (url) =>
UrlLauncher(context, url).launchUrl(), UrlLauncher(context, url.url).launchUrl(),
), ),
), ),
const SizedBox(height: 8), const SizedBox(height: 8),

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
@ -29,7 +30,7 @@ class ChatEncryptionSettingsView extends StatelessWidget {
onPressed: () => onPressed: () =>
VRouter.of(context).toSegments(['rooms', controller.roomId!]), VRouter.of(context).toSegments(['rooms', controller.roomId!]),
), ),
title: Text(L10n.of(context)!.endToEndEncryption), title: Text(L10n.of(context)!.encryption),
actions: [ actions: [
TextButton( TextButton(
onPressed: () => launchUrlString(AppConfig.encryptionTutorial), onPressed: () => launchUrlString(AppConfig.encryptionTutorial),
@ -50,13 +51,12 @@ class ChatEncryptionSettingsView extends StatelessWidget {
value: room.encrypted, value: room.encrypted,
onChanged: controller.enableEncryption, onChanged: controller.enableEncryption,
), ),
Center( Icon(
child: Image.asset( CupertinoIcons.lock_shield,
'assets/encryption.png', size: 128,
width: 212, color: Theme.of(context).colorScheme.onInverseSurface,
),
), ),
const Divider(height: 1), const Divider(),
if (room.isDirectChat) if (room.isDirectChat)
Padding( Padding(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),

View File

@ -253,7 +253,7 @@ class ChatListController extends State<ChatList>
BoxConstraints? snappingSheetContainerSize; BoxConstraints? snappingSheetContainerSize;
final ScrollController scrollController = ScrollController(); final ScrollController scrollController = ScrollController();
bool scrolledToTop = true; final ValueNotifier<bool> scrolledToTop = ValueNotifier(true);
final StreamController<Client> _clientStream = StreamController.broadcast(); final StreamController<Client> _clientStream = StreamController.broadcast();
@ -263,10 +263,8 @@ class ChatListController extends State<ChatList>
void _onScroll() { void _onScroll() {
final newScrolledToTop = scrollController.position.pixels <= 0; final newScrolledToTop = scrollController.position.pixels <= 0;
if (newScrolledToTop != scrolledToTop) { if (newScrolledToTop != scrolledToTop.value) {
setState(() { scrolledToTop.value = newScrolledToTop;
scrolledToTop = newScrolledToTop;
});
} }
} }

View File

@ -1,3 +1,4 @@
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:animations/animations.dart'; import 'package:animations/animations.dart';
@ -8,7 +9,6 @@ import 'package:fluffychat/pages/chat_list/chat_list.dart';
import 'package:fluffychat/pages/chat_list/chat_list_item.dart'; import 'package:fluffychat/pages/chat_list/chat_list_item.dart';
import 'package:fluffychat/pages/chat_list/search_title.dart'; import 'package:fluffychat/pages/chat_list/search_title.dart';
import 'package:fluffychat/pages/chat_list/space_view.dart'; import 'package:fluffychat/pages/chat_list/space_view.dart';
import 'package:fluffychat/pages/chat_list/start_chat_fab.dart';
import 'package:fluffychat/pages/chat_list/stories_header.dart'; import 'package:fluffychat/pages/chat_list/stories_header.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/adaptive_bottom_sheet.dart';
import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart'; import 'package:fluffychat/utils/matrix_sdk_extensions/client_stories_extension.dart';
@ -32,6 +32,11 @@ class ChatListViewBody extends StatelessWidget {
final roomSearchResult = controller.roomSearchResult; final roomSearchResult = controller.roomSearchResult;
final userSearchResult = controller.userSearchResult; final userSearchResult = controller.userSearchResult;
final client = Matrix.of(context).client; final client = Matrix.of(context).client;
const dummyChatCount = 4;
final titleColor =
Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(100);
final subtitleColor =
Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(50);
return PageTransitionSwitcher( return PageTransitionSwitcher(
transitionBuilder: ( transitionBuilder: (
@ -65,157 +70,203 @@ class ChatListViewBody extends StatelessWidget {
key: Key(controller.activeSpaceId ?? 'Spaces'), key: Key(controller.activeSpaceId ?? 'Spaces'),
); );
} }
if (controller.waitForFirstSync && client.prevBatch != null) { final rooms = controller.filteredRooms;
final rooms = controller.filteredRooms; final displayStoriesHeader = {
final displayStoriesHeader = { ActiveFilter.allChats,
ActiveFilter.allChats, ActiveFilter.messages,
ActiveFilter.messages, }.contains(controller.activeFilter) &&
}.contains(controller.activeFilter) && client.storiesRooms.isNotEmpty;
client.storiesRooms.isNotEmpty; return SafeArea(
return SafeArea( child: CustomScrollView(
child: CustomScrollView( controller: controller.scrollController,
controller: controller.scrollController, slivers: [
slivers: [ ChatListHeader(controller: controller),
ChatListHeader(controller: controller), SliverList(
SliverList( delegate: SliverChildListDelegate(
delegate: SliverChildListDelegate( [
[ if (controller.isSearchMode) ...[
if (controller.isSearchMode) ...[ SearchTitle(
SearchTitle( title: L10n.of(context)!.publicRooms,
title: L10n.of(context)!.publicRooms, icon: const Icon(Icons.explore_outlined),
icon: const Icon(Icons.explore_outlined), ),
),
AnimatedContainer(
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(),
height: roomSearchResult == null ||
roomSearchResult.chunk.isEmpty
? 0
: 106,
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
child: roomSearchResult == null
? null
: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: roomSearchResult.chunk.length,
itemBuilder: (context, i) => _SearchItem(
title: roomSearchResult.chunk[i].name ??
roomSearchResult.chunk[i]
.canonicalAlias?.localpart ??
L10n.of(context)!.group,
avatar:
roomSearchResult.chunk[i].avatarUrl,
onPressed: () => showAdaptiveBottomSheet(
context: context,
builder: (c) => PublicRoomBottomSheet(
roomAlias: roomSearchResult
.chunk[i].canonicalAlias ??
roomSearchResult.chunk[i].roomId,
outerContext: context,
chunk: roomSearchResult.chunk[i],
),
),
),
),
),
SearchTitle(
title: L10n.of(context)!.users,
icon: const Icon(Icons.group_outlined),
),
AnimatedContainer(
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(),
height: userSearchResult == null ||
userSearchResult.results.isEmpty
? 0
: 106,
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
child: userSearchResult == null
? null
: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: userSearchResult.results.length,
itemBuilder: (context, i) => _SearchItem(
title: userSearchResult
.results[i].displayName ??
userSearchResult
.results[i].userId.localpart ??
L10n.of(context)!.unknownDevice,
avatar:
userSearchResult.results[i].avatarUrl,
onPressed: () => showAdaptiveBottomSheet(
context: context,
builder: (c) => ProfileBottomSheet(
userId: userSearchResult
.results[i].userId,
outerContext: context,
),
),
),
),
),
SearchTitle(
title: L10n.of(context)!.stories,
icon: const Icon(Icons.camera_alt_outlined),
),
],
if (displayStoriesHeader)
StoriesHeader(
key: const Key('stories_header'),
filter: controller.searchController.text,
),
const ConnectionStatusHeader(),
AnimatedContainer( AnimatedContainer(
height: controller.isTorBrowser ? 64 : 0,
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
clipBehavior: Clip.hardEdge, clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(), decoration: const BoxDecoration(),
child: Material( height: roomSearchResult == null ||
color: Theme.of(context).colorScheme.surface, roomSearchResult.chunk.isEmpty
child: ListTile( ? 0
leading: const Icon(Icons.vpn_key), : 106,
title: Text(L10n.of(context)!.dehydrateTor), duration: FluffyThemes.animationDuration,
subtitle: curve: FluffyThemes.animationCurve,
Text(L10n.of(context)!.dehydrateTorLong), child: roomSearchResult == null
trailing: ? null
const Icon(Icons.chevron_right_outlined), : ListView.builder(
onTap: controller.dehydrate, scrollDirection: Axis.horizontal,
), itemCount: roomSearchResult.chunk.length,
itemBuilder: (context, i) => _SearchItem(
title: roomSearchResult.chunk[i].name ??
roomSearchResult.chunk[i].canonicalAlias
?.localpart ??
L10n.of(context)!.group,
avatar: roomSearchResult.chunk[i].avatarUrl,
onPressed: () => showAdaptiveBottomSheet(
context: context,
builder: (c) => PublicRoomBottomSheet(
roomAlias: roomSearchResult
.chunk[i].canonicalAlias ??
roomSearchResult.chunk[i].roomId,
outerContext: context,
chunk: roomSearchResult.chunk[i],
),
),
),
),
),
SearchTitle(
title: L10n.of(context)!.users,
icon: const Icon(Icons.group_outlined),
),
AnimatedContainer(
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(),
height: userSearchResult == null ||
userSearchResult.results.isEmpty
? 0
: 106,
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
child: userSearchResult == null
? null
: ListView.builder(
scrollDirection: Axis.horizontal,
itemCount: userSearchResult.results.length,
itemBuilder: (context, i) => _SearchItem(
title: userSearchResult
.results[i].displayName ??
userSearchResult
.results[i].userId.localpart ??
L10n.of(context)!.unknownDevice,
avatar:
userSearchResult.results[i].avatarUrl,
onPressed: () => showAdaptiveBottomSheet(
context: context,
builder: (c) => ProfileBottomSheet(
userId:
userSearchResult.results[i].userId,
outerContext: context,
),
),
),
),
),
SearchTitle(
title: L10n.of(context)!.stories,
icon: const Icon(Icons.camera_alt_outlined),
),
],
if (displayStoriesHeader)
StoriesHeader(
key: const Key('stories_header'),
filter: controller.searchController.text,
),
const ConnectionStatusHeader(),
AnimatedContainer(
height: controller.isTorBrowser ? 64 : 0,
duration: FluffyThemes.animationDuration,
curve: FluffyThemes.animationCurve,
clipBehavior: Clip.hardEdge,
decoration: const BoxDecoration(),
child: Material(
color: Theme.of(context).colorScheme.surface,
child: ListTile(
leading: const Icon(Icons.vpn_key),
title: Text(L10n.of(context)!.dehydrateTor),
subtitle: Text(L10n.of(context)!.dehydrateTorLong),
trailing: const Icon(Icons.chevron_right_outlined),
onTap: controller.dehydrate,
), ),
), ),
if (controller.isSearchMode) ),
SearchTitle( if (controller.isSearchMode)
title: L10n.of(context)!.chats, SearchTitle(
icon: const Icon(Icons.forum_outlined), title: L10n.of(context)!.chats,
icon: const Icon(Icons.forum_outlined),
),
if (client.prevBatch != null &&
rooms.isEmpty &&
!controller.isSearchMode) ...[
Padding(
padding: const EdgeInsets.all(32.0),
child: Icon(
CupertinoIcons.chat_bubble_2,
size: 128,
color:
Theme.of(context).colorScheme.onInverseSurface,
), ),
if (rooms.isEmpty && !controller.isSearchMode) ...[ ),
Padding(
padding: const EdgeInsets.all(32.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
children: [
Image.asset(
'assets/start_chat.png',
height: 256,
),
const Divider(height: 1),
],
),
),
Center(
child: StartChatFloatingActionButton(
activeFilter: controller.activeFilter,
roomsIsEmpty: true,
scrolledToTop: controller.scrolledToTop,
),
),
],
], ],
],
),
),
if (client.prevBatch == null)
SliverList(
delegate: SliverChildBuilderDelegate(
(context, i) => Opacity(
opacity: (dummyChatCount - i) / dummyChatCount,
child: ListTile(
leading: CircleAvatar(
backgroundColor: titleColor,
child: CircularProgressIndicator(
strokeWidth: 1,
color:
Theme.of(context).textTheme.bodyLarge!.color,
),
),
title: Row(
children: [
Expanded(
child: Container(
height: 14,
decoration: BoxDecoration(
color: titleColor,
borderRadius: BorderRadius.circular(3),
),
),
),
const SizedBox(width: 36),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
const SizedBox(width: 12),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
],
),
subtitle: Container(
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(3),
),
height: 12,
margin: const EdgeInsets.only(right: 22),
),
),
),
childCount: dummyChatCount,
), ),
), ),
if (client.prevBatch != null)
SliverList( SliverList(
delegate: SliverChildBuilderDelegate( delegate: SliverChildBuilderDelegate(
(BuildContext context, int i) { (BuildContext context, int i) {
@ -245,68 +296,7 @@ class ChatListViewBody extends StatelessWidget {
childCount: rooms.length, childCount: rooms.length,
), ),
), ),
], ],
),
);
}
const dummyChatCount = 5;
final titleColor =
Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(100);
final subtitleColor =
Theme.of(context).textTheme.bodyLarge!.color!.withAlpha(50);
return ListView.builder(
key: const Key('dummychats'),
itemCount: dummyChatCount,
itemBuilder: (context, i) => Opacity(
opacity: (dummyChatCount - i) / dummyChatCount,
child: ListTile(
leading: CircleAvatar(
backgroundColor: titleColor,
child: CircularProgressIndicator(
strokeWidth: 1,
color: Theme.of(context).textTheme.bodyLarge!.color,
),
),
title: Row(
children: [
Expanded(
child: Container(
height: 14,
decoration: BoxDecoration(
color: titleColor,
borderRadius: BorderRadius.circular(3),
),
),
),
const SizedBox(width: 36),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
const SizedBox(width: 12),
Container(
height: 14,
width: 14,
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(14),
),
),
],
),
subtitle: Container(
decoration: BoxDecoration(
color: subtitleColor,
borderRadius: BorderRadius.circular(3),
),
height: 12,
margin: const EdgeInsets.only(right: 22),
),
),
), ),
); );
}, },

View File

@ -192,7 +192,6 @@ class ChatListView extends StatelessWidget {
VRouter.of(context).to('/newprivatechat'), VRouter.of(context).to('/newprivatechat'),
helpLabel: L10n.of(context)!.newChat, helpLabel: L10n.of(context)!.newChat,
child: selectMode == SelectMode.normal && child: selectMode == SelectMode.normal &&
controller.filteredRooms.isNotEmpty &&
!controller.isSearchMode !controller.isSearchMode
? StartChatFloatingActionButton( ? StartChatFloatingActionButton(
activeFilter: controller.activeFilter, activeFilter: controller.activeFilter,

View File

@ -8,7 +8,7 @@ import 'chat_list.dart';
class StartChatFloatingActionButton extends StatelessWidget { class StartChatFloatingActionButton extends StatelessWidget {
final ActiveFilter activeFilter; final ActiveFilter activeFilter;
final bool scrolledToTop; final ValueNotifier<bool> scrolledToTop;
final bool roomsIsEmpty; final bool roomsIsEmpty;
const StartChatFloatingActionButton({ const StartChatFloatingActionButton({
@ -61,27 +61,26 @@ class StartChatFloatingActionButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return AnimatedContainer( return ValueListenableBuilder<bool>(
duration: FluffyThemes.animationDuration, valueListenable: scrolledToTop,
curve: FluffyThemes.animationCurve, builder: (context, scrolledToTop, _) => AnimatedSize(
width: roomsIsEmpty duration: FluffyThemes.animationDuration,
? null curve: FluffyThemes.animationCurve,
: scrolledToTop clipBehavior: Clip.none,
? 144 child: scrolledToTop
: 56, ? FloatingActionButton.extended(
child: scrolledToTop onPressed: () => _onPressed(context),
? FloatingActionButton.extended( icon: Icon(icon),
onPressed: () => _onPressed(context), label: Text(
icon: Icon(icon), getLabel(context),
label: Text( overflow: TextOverflow.fade,
getLabel(context), ),
overflow: TextOverflow.fade, )
: FloatingActionButton(
onPressed: () => _onPressed(context),
child: Icon(icon),
), ),
) ),
: FloatingActionButton(
onPressed: () => _onPressed(context),
child: Icon(icon),
),
); );
} }
} }

View File

@ -73,8 +73,10 @@ class ChatPermissionsSettingsController extends State<ChatPermissionsSettings> {
void updateRoomAction(Capabilities capabilities) async { void updateRoomAction(Capabilities capabilities) async {
final room = Matrix.of(context).client.getRoomById(roomId!)!; final room = Matrix.of(context).client.getRoomById(roomId!)!;
final String roomVersion = final roomVersion = room
room.getState(EventTypes.RoomCreate)!.content['room_version'] ?? '1'; .getState(EventTypes.RoomCreate)!
.content['room_version'] as String? ??
'1';
final newVersion = await showConfirmationDialog<String>( final newVersion = await showConfirmationDialog<String>(
context: context, context: context,
title: L10n.of(context)!.replaceRoomWithNewerVersion, title: L10n.of(context)!.replaceRoomWithNewerVersion,

View File

@ -127,9 +127,9 @@ class ChatPermissionsSettingsView extends StatelessWidget {
), ),
); );
} }
final String roomVersion = room final roomVersion = room
.getState(EventTypes.RoomCreate)! .getState(EventTypes.RoomCreate)!
.content['room_version'] ?? .content['room_version'] as String? ??
'1'; '1';
return ListTile( return ListTile(

View File

@ -1,197 +0,0 @@
import 'package:flutter/foundation.dart';
import 'package:flutter/material.dart';
import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart';
import 'package:universal_html/html.dart' as html;
import 'package:vrouter/vrouter.dart';
import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/connect/connect_page_view.dart';
import 'package:fluffychat/utils/localized_exception_extension.dart';
import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/matrix.dart';
class ConnectPage extends StatefulWidget {
const ConnectPage({Key? key}) : super(key: key);
@override
State<ConnectPage> createState() => ConnectPageController();
}
class ConnectPageController extends State<ConnectPage> {
final TextEditingController usernameController = TextEditingController();
String? signupError;
bool loading = false;
void pickAvatar() async {
final source = !PlatformInfos.isMobile
? ImageSource.gallery
: await showModalActionSheet<ImageSource>(
context: context,
title: L10n.of(context)!.changeYourAvatar,
actions: [
SheetAction(
key: ImageSource.camera,
label: L10n.of(context)!.openCamera,
isDefaultAction: true,
icon: Icons.camera_alt_outlined,
),
SheetAction(
key: ImageSource.gallery,
label: L10n.of(context)!.openGallery,
icon: Icons.photo_outlined,
),
],
);
if (source == null) return;
final picked = await ImagePicker().pickImage(
source: source,
imageQuality: 50,
maxWidth: 512,
maxHeight: 512,
);
setState(() {
Matrix.of(context).loginAvatar = picked;
});
}
void signUp() async {
usernameController.text = usernameController.text.trim();
final localpart =
usernameController.text.toLowerCase().replaceAll(' ', '_');
if (localpart.isEmpty) {
setState(() {
signupError = L10n.of(context)!.pleaseChooseAUsername;
});
return;
}
setState(() {
signupError = null;
loading = true;
});
try {
try {
await Matrix.of(context).getLoginClient().register(username: localpart);
} on MatrixException catch (e) {
if (!e.requireAdditionalAuthentication) rethrow;
}
setState(() {
loading = false;
});
Matrix.of(context).loginUsername = usernameController.text;
VRouter.of(context).to('signup');
} catch (e, s) {
Logs().d('Sign up failed', e, s);
setState(() {
signupError = e.toLocalizedString(context);
loading = false;
});
}
}
bool _supportsFlow(String flowType) =>
Matrix.of(context)
.loginHomeserverSummary
?.loginFlows
.any((flow) => flow.type == flowType) ??
false;
bool get supportsSso => _supportsFlow('m.login.sso');
bool isDefaultPlatform =
(PlatformInfos.isMobile || PlatformInfos.isWeb || PlatformInfos.isMacOS);
bool get supportsLogin => _supportsFlow('m.login.password');
void login() => VRouter.of(context).to('login');
Map<String, dynamic>? _rawLoginTypes;
List<IdentityProvider>? get identityProviders {
final loginTypes = _rawLoginTypes;
if (loginTypes == null) return null;
final rawProviders = loginTypes.tryGetList('flows')!.singleWhere(
(flow) => flow['type'] == AuthenticationTypes.sso,
)['identity_providers'];
final list = (rawProviders as List)
.map((json) => IdentityProvider.fromJson(json))
.toList();
if (PlatformInfos.isCupertinoStyle) {
list.sort((a, b) => a.brand == 'apple' ? -1 : 1);
}
return list;
}
void ssoLoginAction(String id) async {
final redirectUrl = kIsWeb
? '${html.window.origin!}/web/auth.html'
: isDefaultPlatform
? '${AppConfig.appOpenUrlScheme.toLowerCase()}://login'
: 'http://localhost:3001//login';
final url =
'${Matrix.of(context).getLoginClient().homeserver?.toString()}/_matrix/client/r0/login/sso/redirect/${Uri.encodeComponent(id)}?redirectUrl=${Uri.encodeQueryComponent(redirectUrl)}';
final urlScheme = isDefaultPlatform
? Uri.parse(redirectUrl).scheme
: "http://localhost:3001";
final result = await FlutterWebAuth2.authenticate(
url: url,
callbackUrlScheme: urlScheme,
);
final token = Uri.parse(result).queryParameters['loginToken'];
if (token?.isEmpty ?? false) return;
await showFutureLoadingDialog(
context: context,
future: () => Matrix.of(context).getLoginClient().login(
LoginType.mLoginToken,
token: token,
initialDeviceDisplayName: PlatformInfos.clientName,
),
);
}
@override
void initState() {
super.initState();
if (supportsSso) {
Matrix.of(context)
.getLoginClient()
.request(
RequestType.GET,
'/client/r0/login',
)
.then(
(loginTypes) => setState(() {
_rawLoginTypes = loginTypes;
}),
);
}
}
@override
Widget build(BuildContext context) => ConnectPageView(this);
}
class IdentityProvider {
final String? id;
final String? name;
final String? icon;
final String? brand;
IdentityProvider({this.id, this.name, this.icon, this.brand});
factory IdentityProvider.fromJson(Map<String, dynamic> json) =>
IdentityProvider(
id: json['id'],
name: json['name'],
icon: json['icon'],
brand: json['brand'],
);
}

View File

@ -1,226 +0,0 @@
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/pages/connect/connect_page.dart';
import 'package:fluffychat/widgets/layouts/login_scaffold.dart';
import 'package:fluffychat/widgets/matrix.dart';
import 'sso_button.dart';
class ConnectPageView extends StatelessWidget {
final ConnectPageController controller;
const ConnectPageView(this.controller, {Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
final avatar = Matrix.of(context).loginAvatar;
final identityProviders = controller.identityProviders;
return LoginScaffold(
appBar: AppBar(
leading: controller.loading ? null : const BackButton(),
automaticallyImplyLeading: !controller.loading,
centerTitle: true,
title: Text(
Matrix.of(context).getLoginClient().homeserver?.host ?? '',
),
),
body: ListView(
key: const Key('ConnectPageListView'),
children: [
if (Matrix.of(context).loginRegistrationSupported ?? false) ...[
Padding(
padding: const EdgeInsets.all(12.0),
child: Center(
child: Stack(
children: [
Material(
borderRadius: BorderRadius.circular(64),
elevation: Theme.of(context)
.appBarTheme
.scrolledUnderElevation ??
10,
color: Colors.transparent,
shadowColor: Theme.of(context)
.colorScheme
.onBackground
.withAlpha(64),
clipBehavior: Clip.hardEdge,
child: CircleAvatar(
radius: 64,
backgroundColor: Colors.white,
child: avatar == null
? const Icon(
Icons.person,
color: Colors.black,
size: 64,
)
: FutureBuilder<Uint8List>(
future: avatar.readAsBytes(),
builder: (context, snapshot) {
final bytes = snapshot.data;
if (bytes == null) {
return const CircularProgressIndicator
.adaptive();
}
return Image.memory(
bytes,
fit: BoxFit.cover,
width: 128,
height: 128,
);
},
),
),
),
Positioned(
bottom: 0,
right: 0,
child: FloatingActionButton(
mini: true,
onPressed: controller.pickAvatar,
backgroundColor: Colors.white,
foregroundColor: Colors.black,
child: const Icon(Icons.camera_alt_outlined),
),
),
],
),
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: TextField(
controller: controller.usernameController,
onSubmitted: (_) => controller.signUp(),
decoration: InputDecoration(
prefixIcon: const Icon(Icons.account_box_outlined),
hintText: L10n.of(context)!.chooseAUsername,
errorText: controller.signupError,
errorStyle: const TextStyle(color: Colors.orange),
),
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Hero(
tag: 'loginButton',
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context).colorScheme.primary,
foregroundColor: Theme.of(context).colorScheme.onPrimary,
),
onPressed: controller.loading ? () {} : controller.signUp,
icon: const Icon(Icons.person_add_outlined),
label: controller.loading
? const LinearProgressIndicator()
: Text(L10n.of(context)!.signUp),
),
),
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 16.0),
child: Row(
children: [
Expanded(
child: Divider(
thickness: 1,
color: Theme.of(context).dividerColor,
),
),
Padding(
padding: const EdgeInsets.all(12.0),
child: Text(
L10n.of(context)!.or,
style: const TextStyle(fontSize: 18),
),
),
Expanded(
child: Divider(
thickness: 1,
color: Theme.of(context).dividerColor,
),
),
],
),
),
],
if (controller.supportsSso)
identityProviders == null
? const SizedBox(
height: 74,
child: Center(child: CircularProgressIndicator.adaptive()),
)
: Center(
child: identityProviders.length == 1
? Container(
width: double.infinity,
padding: const EdgeInsets.all(12.0),
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
backgroundColor: Theme.of(context)
.colorScheme
.primaryContainer,
foregroundColor: Theme.of(context)
.colorScheme
.onPrimaryContainer,
),
icon: identityProviders.single.icon == null
? const Icon(
Icons.web_outlined,
size: 16,
)
: Image.network(
Uri.parse(identityProviders.single.icon!)
.getDownloadLink(
Matrix.of(context).getLoginClient(),
)
.toString(),
width: 32,
height: 32,
),
onPressed: () => controller
.ssoLoginAction(identityProviders.single.id!),
label: Text(
identityProviders.single.name ??
identityProviders.single.brand ??
L10n.of(context)!.loginWithOneClick,
),
),
)
: Wrap(
children: [
for (final identityProvider in identityProviders)
SsoButton(
onPressed: () => controller
.ssoLoginAction(identityProvider.id!),
identityProvider: identityProvider,
),
].toList(),
),
),
if (controller.supportsLogin)
Padding(
padding: const EdgeInsets.all(12.0),
child: Hero(
tag: 'signinButton',
child: ElevatedButton.icon(
icon: const Icon(Icons.login_outlined),
style: ElevatedButton.styleFrom(
backgroundColor:
Theme.of(context).colorScheme.primaryContainer,
foregroundColor:
Theme.of(context).colorScheme.onPrimaryContainer,
),
onPressed: controller.loading ? () {} : controller.login,
label: Text(L10n.of(context)!.login),
),
),
),
],
),
);
}
}

View File

@ -1,63 +0,0 @@
import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:matrix/matrix.dart';
import 'package:fluffychat/pages/connect/connect_page.dart';
import 'package:fluffychat/widgets/matrix.dart';
class SsoButton extends StatelessWidget {
final IdentityProvider identityProvider;
final void Function()? onPressed;
const SsoButton({
Key? key,
required this.identityProvider,
this.onPressed,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return InkWell(
onTap: onPressed,
borderRadius: BorderRadius.circular(7),
child: Padding(
padding: const EdgeInsets.symmetric(horizontal: 10.0, vertical: 6.0),
child: Column(
mainAxisAlignment: MainAxisAlignment.center,
mainAxisSize: MainAxisSize.min,
children: [
Material(
color: Colors.white,
borderRadius: BorderRadius.circular(8),
clipBehavior: Clip.hardEdge,
child: Padding(
padding: const EdgeInsets.all(4.0),
child: identityProvider.icon == null
? const Icon(Icons.web_outlined)
: Image.network(
Uri.parse(identityProvider.icon!)
.getDownloadLink(
Matrix.of(context).getLoginClient(),
)
.toString(),
width: 32,
height: 32,
),
),
),
const SizedBox(height: 8),
Text(
identityProvider.name ??
identityProvider.brand ??
L10n.of(context)!.singlesignon,
style: const TextStyle(
fontSize: 12,
fontWeight: FontWeight.bold,
),
),
],
),
),
);
}
}

View File

@ -1,8 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_typeahead/flutter_typeahead.dart';
import 'package:matrix_homeserver_recommendations/matrix_homeserver_recommendations.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'homeserver_bottom_sheet.dart';
import 'homeserver_picker.dart'; import 'homeserver_picker.dart';
class HomeserverAppBar extends StatelessWidget { class HomeserverAppBar extends StatelessWidget {
@ -13,25 +16,57 @@ class HomeserverAppBar extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return TextField( return TypeAheadField<HomeserverBenchmarkResult>(
focusNode: controller.homeserverFocusNode, suggestionsBoxDecoration: SuggestionsBoxDecoration(
controller: controller.homeserverController, borderRadius: BorderRadius.circular(AppConfig.borderRadius),
onChanged: controller.onChanged, elevation: Theme.of(context).appBarTheme.scrolledUnderElevation ?? 4,
decoration: InputDecoration( shadowColor: Theme.of(context).appBarTheme.shadowColor ?? Colors.black,
prefixIcon: Navigator.of(context).canPop() constraints: const BoxConstraints(maxHeight: 256),
? IconButton( ),
onPressed: Navigator.of(context).pop, itemBuilder: (context, homeserver) => ListTile(
icon: const Icon(Icons.arrow_back), title: Text(homeserver.homeserver.baseUrl.toString()),
) subtitle: Text(homeserver.homeserver.description ?? ''),
: null, trailing: IconButton(
prefixText: '${L10n.of(context)!.homeserver}: ', icon: const Icon(Icons.info_outlined),
hintText: L10n.of(context)!.enterYourHomeserver, onPressed: () => showModalBottomSheet(
suffixIcon: const Icon(Icons.search), context: context,
errorText: controller.error, builder: (_) => HomeserverBottomSheet(
homeserver: homeserver,
),
),
),
),
suggestionsCallback: (pattern) async {
final homeserverList =
await const JoinmatrixOrgParser().fetchHomeservers();
final benchmark = await HomeserverListProvider.benchmarkHomeserver(
homeserverList,
timeout: const Duration(seconds: 3),
);
return benchmark;
},
onSuggestionSelected: (suggestion) {
controller.homeserverController.text =
suggestion.homeserver.baseUrl.host;
controller.checkHomeserverAction();
},
textFieldConfiguration: TextFieldConfiguration(
controller: controller.homeserverController,
decoration: InputDecoration(
prefixIcon: Navigator.of(context).canPop()
? IconButton(
onPressed: Navigator.of(context).pop,
icon: const Icon(Icons.arrow_back),
)
: null,
prefixText: '${L10n.of(context)!.homeserver}: ',
hintText: L10n.of(context)!.enterYourHomeserver,
suffixIcon: const Icon(Icons.search),
),
textInputAction: TextInputAction.search,
onSubmitted: controller.checkHomeserverAction,
autocorrect: false,
), ),
readOnly: !AppConfig.allowOtherHomeservers,
onSubmitted: (_) => controller.checkHomeserverAction(),
autocorrect: false,
); );
} }
} }

View File

@ -7,16 +7,16 @@ import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:collection/collection.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart'; import 'package:file_picker/file_picker.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:flutter_web_auth_2/flutter_web_auth_2.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:hive_flutter/hive_flutter.dart'; import 'package:hive_flutter/hive_flutter.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
import 'package:matrix_homeserver_recommendations/matrix_homeserver_recommendations.dart'; import 'package:universal_html/html.dart' as html;
import 'package:vrouter/vrouter.dart'; import 'package:vrouter/vrouter.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/pages/homeserver_picker/homeserver_bottom_sheet.dart';
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker_view.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker_view.dart';
import 'package:fluffychat/utils/adaptive_bottom_sheet.dart'; import 'package:fluffychat/utils/platform_infos.dart';
import 'package:fluffychat/widgets/matrix.dart'; import 'package:fluffychat/widgets/matrix.dart';
import '../../utils/localized_exception_extension.dart'; import '../../utils/localized_exception_extension.dart';
@ -35,14 +35,8 @@ class HomeserverPickerController extends State<HomeserverPicker> {
final TextEditingController homeserverController = TextEditingController( final TextEditingController homeserverController = TextEditingController(
text: AppConfig.defaultHomeserver, text: AppConfig.defaultHomeserver,
); );
final FocusNode homeserverFocusNode = FocusNode();
String? error;
List<HomeserverBenchmarkResult>? benchmarkResults;
bool displayServerList = false;
bool get loadingHomeservers => String? error;
AppConfig.allowOtherHomeservers && benchmarkResults == null;
String searchTerm = '';
bool isTorBrowser = false; bool isTorBrowser = false;
@ -65,98 +59,34 @@ class HomeserverPickerController extends State<HomeserverPicker> {
isTorBrowser = isTor; isTorBrowser = isTor;
} }
void _updateFocus() { String? _lastCheckedUrl;
if (benchmarkResults == null) _loadHomeserverList();
if (homeserverFocusNode.hasFocus) {
setState(() {
displayServerList = true;
});
}
}
void showServerInfo(HomeserverBenchmarkResult server) =>
showAdaptiveBottomSheet(
context: context,
builder: (_) => HomeserverBottomSheet(
homeserver: server,
),
);
void onChanged(String text) => setState(() {
searchTerm = text;
});
List<HomeserverBenchmarkResult> get filteredHomeservers => benchmarkResults!
.where(
(element) =>
element.homeserver.baseUrl.host.contains(searchTerm) ||
(element.homeserver.description?.contains(searchTerm) ?? false),
)
.toList();
void _loadHomeserverList() async {
try {
final homeserverList =
await const JoinmatrixOrgParser().fetchHomeservers();
final benchmark = await HomeserverListProvider.benchmarkHomeserver(
homeserverList,
timeout: const Duration(seconds: 10),
);
if (!mounted) return;
setState(() {
benchmarkResults = benchmark;
});
} catch (e, s) {
Logs().e('Homeserver benchmark failed', e, s);
benchmarkResults = [];
}
}
void setServer(String server) => setState(() {
homeserverController.text = server;
searchTerm = '';
homeserverFocusNode.unfocus();
displayServerList = false;
});
/// Starts an analysis of the given homeserver. It uses the current domain and /// Starts an analysis of the given homeserver. It uses the current domain and
/// makes sure that it is prefixed with https. Then it searches for the /// makes sure that it is prefixed with https. Then it searches for the
/// well-known information and forwards to the login page depending on the /// well-known information and forwards to the login page depending on the
/// login type. /// login type.
Future<void> checkHomeserverAction() async { Future<void> checkHomeserverAction([_]) async {
homeserverController.text =
homeserverController.text.trim().toLowerCase().replaceAll(' ', '-');
if (homeserverController.text == _lastCheckedUrl) return;
_lastCheckedUrl = homeserverController.text;
setState(() { setState(() {
homeserverFocusNode.unfocus(); error = _rawLoginTypes = loginHomeserverSummary = null;
error = null;
isLoading = true; isLoading = true;
searchTerm = '';
displayServerList = false;
}); });
try { try {
homeserverController.text =
homeserverController.text.trim().toLowerCase().replaceAll(' ', '-');
var homeserver = Uri.parse(homeserverController.text); var homeserver = Uri.parse(homeserverController.text);
if (homeserver.scheme.isEmpty) { if (homeserver.scheme.isEmpty) {
homeserver = Uri.https(homeserverController.text, ''); homeserver = Uri.https(homeserverController.text, '');
} }
final matrix = Matrix.of(context); final client = Matrix.of(context).getLoginClient();
matrix.loginHomeserverSummary = loginHomeserverSummary = await client.checkHomeserver(homeserver);
await matrix.getLoginClient().checkHomeserver(homeserver); if (supportsSso) {
final ssoSupported = matrix.loginHomeserverSummary!.loginFlows _rawLoginTypes = await client.request(
.any((flow) => flow.type == 'm.login.sso'); RequestType.GET,
'/client/r0/login',
try { );
await Matrix.of(context).getLoginClient().register();
matrix.loginRegistrationSupported = true;
} on MatrixException catch (e) {
matrix.loginRegistrationSupported = e.requireAdditionalAuthentication;
}
if (!ssoSupported && matrix.loginRegistrationSupported == false) {
// Server does not support SSO or registration. We can skip to login page:
VRouter.of(context).to('login');
} else {
VRouter.of(context).to('connect');
} }
} catch (e) { } catch (e) {
setState(() => error = (e).toLocalizedString(context)); setState(() => error = (e).toLocalizedString(context));
@ -167,17 +97,71 @@ class HomeserverPickerController extends State<HomeserverPicker> {
} }
} }
@override HomeserverSummary? loginHomeserverSummary;
void dispose() {
homeserverFocusNode.removeListener(_updateFocus); bool _supportsFlow(String flowType) =>
super.dispose(); loginHomeserverSummary?.loginFlows.any((flow) => flow.type == flowType) ??
false;
bool get supportsSso => _supportsFlow('m.login.sso');
bool isDefaultPlatform =
(PlatformInfos.isMobile || PlatformInfos.isWeb || PlatformInfos.isMacOS);
bool get supportsPasswordLogin => _supportsFlow('m.login.password');
Map<String, dynamic>? _rawLoginTypes;
void ssoLoginAction(String id) async {
final redirectUrl = kIsWeb
? '${html.window.origin!}/web/auth.html'
: isDefaultPlatform
? '${AppConfig.appOpenUrlScheme.toLowerCase()}://login'
: 'http://localhost:3001//login';
final url =
'${Matrix.of(context).getLoginClient().homeserver?.toString()}/_matrix/client/r0/login/sso/redirect/${Uri.encodeComponent(id)}?redirectUrl=${Uri.encodeQueryComponent(redirectUrl)}';
final urlScheme = isDefaultPlatform
? Uri.parse(redirectUrl).scheme
: "http://localhost:3001";
final result = await FlutterWebAuth2.authenticate(
url: url,
callbackUrlScheme: urlScheme,
);
final token = Uri.parse(result).queryParameters['loginToken'];
if (token?.isEmpty ?? false) return;
await showFutureLoadingDialog(
context: context,
future: () => Matrix.of(context).getLoginClient().login(
LoginType.mLoginToken,
token: token,
initialDeviceDisplayName: PlatformInfos.clientName,
),
);
} }
List<IdentityProvider>? get identityProviders {
final loginTypes = _rawLoginTypes;
if (loginTypes == null) return null;
final rawProviders = loginTypes.tryGetList('flows')!.singleWhere(
(flow) => flow['type'] == AuthenticationTypes.sso,
)['identity_providers'];
final list = (rawProviders as List)
.map((json) => IdentityProvider.fromJson(json))
.toList();
if (PlatformInfos.isCupertinoStyle) {
list.sort((a, b) => a.brand == 'apple' ? -1 : 1);
}
return list;
}
void login() => VRouter.of(context).to('login');
@override @override
void initState() { void initState() {
homeserverFocusNode.addListener(_updateFocus);
_checkTorBrowser(); _checkTorBrowser();
super.initState(); super.initState();
WidgetsBinding.instance.addPostFrameCallback(checkHomeserverAction);
} }
@override @override
@ -204,3 +188,20 @@ class HomeserverPickerController extends State<HomeserverPicker> {
); );
} }
} }
class IdentityProvider {
final String? id;
final String? name;
final String? icon;
final String? brand;
IdentityProvider({this.id, this.name, this.icon, this.brand});
factory IdentityProvider.fromJson(Map<String, dynamic> json) =>
IdentityProvider(
id: json['id'],
name: json['name'],
icon: json['icon'],
brand: json['brand'],
);
}

View File

@ -1,11 +1,11 @@
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_gen/gen_l10n/l10n.dart'; import 'package:flutter_gen/gen_l10n/l10n.dart';
import 'package:url_launcher/url_launcher_string.dart';
import 'package:fluffychat/config/app_config.dart'; import 'package:fluffychat/config/app_config.dart';
import 'package:fluffychat/widgets/layouts/login_scaffold.dart'; import 'package:fluffychat/widgets/layouts/login_scaffold.dart';
import '../../config/themes.dart'; import '../../config/themes.dart';
import '../../widgets/mxc_image.dart';
import 'homeserver_app_bar.dart'; import 'homeserver_app_bar.dart';
import 'homeserver_picker.dart'; import 'homeserver_picker.dart';
@ -16,15 +16,19 @@ class HomeserverPickerView extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final benchmarkResults = controller.benchmarkResults; final identityProviders = controller.identityProviders;
final errorText = controller.error;
return LoginScaffold( return LoginScaffold(
appBar: AppBar(
titleSpacing: 12,
title: Padding(
padding: const EdgeInsets.all(0.0),
child: HomeserverAppBar(controller: controller),
),
),
body: SafeArea( body: SafeArea(
child: Column( child: Column(
children: [ children: [
Padding(
padding: const EdgeInsets.all(12.0),
child: HomeserverAppBar(controller: controller),
),
// display a prominent banner to import session for TOR browser // display a prominent banner to import session for TOR browser
// users. This feature is just some UX sugar as TOR users are // users. This feature is just some UX sugar as TOR users are
// usually forced to logout as TOR browser is non-persistent // usually forced to logout as TOR browser is non-persistent
@ -49,108 +53,119 @@ class HomeserverPickerView extends StatelessWidget {
), ),
), ),
Expanded( Expanded(
child: controller.displayServerList child: controller.isLoading
? ListView( ? const Center(child: CircularProgressIndicator.adaptive())
: ListView(
children: [ children: [
if (controller.displayServerList) Image.asset(
Padding( 'assets/info-logo.png',
padding: const EdgeInsets.all(12.0), height: 96,
child: Material( ),
borderRadius: Padding(
BorderRadius.circular(AppConfig.borderRadius), padding: const EdgeInsets.symmetric(horizontal: 12.0),
color: Theme.of(context) child: Row(
.colorScheme children: [
.onInverseSurface, Expanded(
clipBehavior: Clip.hardEdge, child: Divider(
child: benchmarkResults == null thickness: 1,
? const Center( height: 1,
child: Padding( color: Theme.of(context).dividerColor,
padding: EdgeInsets.all(12.0), ),
child: CircularProgressIndicator ),
.adaptive(), Padding(
), padding: const EdgeInsets.all(12.0),
) child: Text(
: Column( L10n.of(context)!.continueWith,
children: controller.filteredHomeservers style: const TextStyle(fontSize: 12),
.map( ),
(server) => ListTile( ),
trailing: IconButton( Expanded(
icon: const Icon( child: Divider(
Icons.info_outlined, thickness: 1,
color: Colors.black, height: 1,
), color: Theme.of(context).dividerColor,
onPressed: () => controller ),
.showServerInfo(server), ),
), ],
onTap: () => controller.setServer( ),
server.homeserver.baseUrl.host, ),
), if (errorText != null) ...[
title: Text( const Center(
server.homeserver.baseUrl.host, child: Icon(
style: const TextStyle( Icons.error_outline,
color: Colors.black, size: 48,
), color: Colors.orange,
),
subtitle: Text(
server.homeserver.description ??
'',
style: TextStyle(
color: Colors.grey.shade700,
),
),
),
)
.toList(),
),
), ),
), ),
], const SizedBox(height: 12),
) Center(
: Container( child: Text(
alignment: Alignment.topCenter, errorText,
child: Image.asset( textAlign: TextAlign.center,
'assets/banner_transparent.png', style: TextStyle(
filterQuality: FilterQuality.medium, color: Theme.of(context).colorScheme.error,
), fontSize: 18,
), ),
), ),
SafeArea( ),
child: Container( Center(
padding: const EdgeInsets.all(12), child: Text(
width: double.infinity, L10n.of(context)!
child: Column( .pleaseTryAgainLaterOrChooseDifferentServer,
mainAxisSize: MainAxisSize.min, textAlign: TextAlign.center,
crossAxisAlignment: CrossAxisAlignment.stretch, style: TextStyle(
children: [ color: Theme.of(context).colorScheme.error,
TextButton( fontSize: 12,
onPressed: () => launchUrlString(AppConfig.privacyUrl), ),
child: Text(L10n.of(context)!.privacy), ),
), ),
TextButton( const SizedBox(height: 12),
onPressed: controller.restoreBackup, ],
child: Text(L10n.of(context)!.hydrate), if (identityProviders != null) ...[
), ...identityProviders.map(
Hero( (provider) => _LoginButton(
tag: 'loginButton', icon: provider.icon == null
child: ElevatedButton.icon( ? const Icon(Icons.open_in_new_outlined)
style: ElevatedButton.styleFrom( : Material(
backgroundColor: color: Colors.white,
Theme.of(context).colorScheme.primary, borderRadius: BorderRadius.circular(
foregroundColor: AppConfig.borderRadius,
Theme.of(context).colorScheme.onPrimary, ),
clipBehavior: Clip.hardEdge,
child: MxcImage(
placeholder: (_) =>
const Icon(Icons.web_outlined),
uri: Uri.parse(provider.icon!),
width: 24,
height: 24,
),
),
label: provider.name ??
provider.brand ??
L10n.of(context)!.singlesignon,
onPressed: () =>
controller.ssoLoginAction(provider.id!),
),
),
],
if (controller.supportsPasswordLogin)
_LoginButton(
onPressed: controller.login,
icon: const Icon(Icons.login_outlined),
label: L10n.of(context)!.signInWithPassword,
),
Padding(
padding: const EdgeInsets.symmetric(horizontal: 12),
child: TextButton(
style: TextButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
onPressed: controller.restoreBackup,
child: Text(L10n.of(context)!.hydrate),
),
), ),
onPressed: controller.isLoading ],
? null
: controller.checkHomeserverAction,
icon: const Icon(Icons.start_outlined),
label: controller.isLoading
? const LinearProgressIndicator()
: Text(L10n.of(context)!.letsStart),
),
), ),
],
),
),
), ),
], ],
), ),
@ -158,3 +173,33 @@ class HomeserverPickerView extends StatelessWidget {
); );
} }
} }
class _LoginButton extends StatelessWidget {
final Widget icon;
final String label;
final void Function() onPressed;
const _LoginButton({
required this.icon,
required this.label,
required this.onPressed,
Key? key,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Container(
padding: const EdgeInsets.symmetric(horizontal: 12),
margin: const EdgeInsets.only(bottom: 16),
width: double.infinity,
child: ElevatedButton.icon(
style: ElevatedButton.styleFrom(
padding: const EdgeInsets.symmetric(vertical: 12),
),
onPressed: onPressed,
icon: icon,
label: Text(label),
),
);
}
}

Some files were not shown because too many files have changed in this diff Show More