Compare commits

...

318 Commits
v1.9.0 ... main

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
Krille
dd86a0fb00
chore: Bump version 2023-05-05 09:59:04 +02:00
Krille
a603597b20
fix: Chats do not load 2023-05-05 07:54:19 +02:00
Jelv
23b14e8730
Translated using Weblate (Dutch)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/nl/
2023-05-04 18:50:33 +02:00
Ihor Hordiichuk
c4a7650e39
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-05-04 18:50:33 +02:00
Oğuz Ersen
c4bb5fa523
Translated using Weblate (Turkish)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-05-04 18:50:32 +02:00
Eryk Michalak
fa684d265d
Translated using Weblate (Polish)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/pl/
2023-05-04 18:50:32 +02:00
Milo Ivir
3eeaad17f0
Translated using Weblate (Croatian)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/hr/
2023-05-04 18:50:31 +02:00
josé m
8d2697ffc6
Translated using Weblate (Galician)
Currently translated at 99.8% (558 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-05-04 18:50:31 +02:00
Priit Jõerüüt
150ba308e9
Translated using Weblate (Estonian)
Currently translated at 100.0% (559 of 559 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-05-04 18:50:30 +02:00
Krille
ce18cfdf2a
feat: Permission dialog before open link in browser 2023-05-02 14:09:46 +02:00
MohammadSaleh Kamyab
17bccc0dea
Translated using Weblate (Persian)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-04-21 17:52:20 +02:00
Milo Ivir
f8b7a6fef5
Translated using Weblate (Croatian)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/hr/
2023-04-21 17:52:20 +02:00
Priit Jõerüüt
a68f7e8936
Translated using Weblate (Estonian)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-04-21 17:52:19 +02:00
Krille
74ef50af49
chore: Update appleid 2023-04-20 08:43:22 +02:00
Krille
70698cf4ec
chore: Bump version 2023-04-20 08:38:39 +02:00
Krille
9bed679568
chore: Follow up file download type fix 2023-04-19 15:51:53 +02:00
Krille
99595caee5
chore: Disable integration tests until fixed 2023-04-19 08:49:56 +02:00
Krille
b39018e454
chore: Update to flutter 3.7.11 2023-04-18 07:19:44 +02:00
Linerly
08bed5d668
Translated using Weblate (Indonesian)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-04-18 03:58:58 +02:00
Jelv
b78868397c
Translated using Weblate (Dutch)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/nl/
2023-04-18 03:58:58 +02:00
Eryk Michalak
cbb4553fc0
Translated using Weblate (Polish)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/pl/
2023-04-18 03:58:57 +02:00
Ihor Hordiichuk
3ddd661fb5
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-04-15 07:52:52 +02:00
Oğuz Ersen
4e8f2c3040
Translated using Weblate (Turkish)
Currently translated at 100.0% (558 of 558 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-04-15 07:52:52 +02:00
Krille
52ee4b923a
chore: Bump version 2023-04-14 14:27:45 +02:00
Krille
166fcce8ba
style: Make emptypage logo bigger 2023-04-14 14:24:18 +02:00
Krille
92072904e6
chore: Load chat at last read marker 2023-04-14 14:23:58 +02:00
Krille
9ace2fe07b
chore: Follow up push android priority and channels 2023-04-12 09:32:18 +02:00
Krille
8913b42803
fix: Set fcm priority to max on android 2023-04-12 09:18:20 +02:00
Krille
253a3afbdd Merge branch 'krille/update-flutter-3-7-10' into 'main'
chore: Update flutter to 3.7.10 and switch to self hosted cirruslabs image

See merge request famedly/fluffychat!1108
2023-04-12 06:38:20 +00:00
Krille
af2907b946
chore: Update flutter to 3.7.10 and switch to self hosted cirruslabs image 2023-04-12 08:37:59 +02:00
Jelv
02a0c4760a
Translated using Weblate (Dutch)
Currently translated at 99.1% (552 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/nl/
2023-04-11 06:42:12 +02:00
josé m
e9899fce8e
Translated using Weblate (Galician)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-04-03 07:38:07 +02:00
Krille
63a9f9ca90
chore: Follow up jump to event 2023-04-02 09:33:27 +02:00
Kristoffer Grundström
b5364e1619
Translated using Weblate (Swedish)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/sv/
2023-04-01 00:39:58 +02:00
Krille
742dcb8f41
chore: ScrollToEventId duration for jump in timeline 2023-03-31 12:18:24 +02:00
Siavash
dda90c85a4
Translated using Weblate (Persian)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-03-30 12:37:13 +02:00
Siavash
16455da39f
Translated using Weblate (Persian)
Currently translated at 99.6% (555 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-03-29 11:17:52 +02:00
Parsa
b69e3969cb
Translated using Weblate (Persian)
Currently translated at 99.6% (555 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-03-29 11:17:51 +02:00
Anne Onyme 017
14c904b214
Translated using Weblate (French)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fr/
2023-03-29 11:17:50 +02:00
Krille
0d12c31393
chore: Follow up sso for desktop 2023-03-26 11:20:54 +02:00
Krille
d6b3482ce2
chore: Downgrade flutter to 3.7.7 2023-03-26 10:58:52 +02:00
Krille
f4eb6318cc Merge branch 'flutterwebauto2' into 'main'
feat: change to flutterwebauth2

See merge request famedly/fluffychat!1100
2023-03-26 08:57:01 +00:00
Linerly
c8b421d43e
Translated using Weblate (Indonesian)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-03-26 09:37:00 +02:00
Parsa
87280a0e21
Translated using Weblate (Persian)
Currently translated at 66.7% (372 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-03-26 09:36:59 +02:00
Ihor Hordiichuk
96d3f83933
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-03-26 09:36:59 +02:00
Oğuz Ersen
bb3eddb021
Translated using Weblate (Turkish)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-03-26 09:36:58 +02:00
Priit Jõerüüt
59c403603b
Translated using Weblate (Estonian)
Currently translated at 100.0% (557 of 557 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-03-26 09:36:58 +02:00
Krille
fd7d732762
chore: Update flutter version 2023-03-25 15:53:54 +01:00
Krille
fc8fe60613
chore: Follow up jump to unread message 2023-03-25 15:23:14 +01:00
Krille
2acf49a12b
refactor: Not nullable room in ChatPage 2023-03-25 15:06:12 +01:00
Krille
2f6799470c
refactor: Client in ChatPage 2023-03-25 14:58:51 +01:00
Krille
507cd1f17e
refactor: Use correct Matrix instance 2023-03-25 14:57:27 +01:00
Linerly
f1a8716832
Translated using Weblate (Indonesian)
Currently translated at 100.0% (556 of 556 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-03-24 08:31:42 +01:00
Parsa
f99aad5a18
Translated using Weblate (Persian)
Currently translated at 60.7% (338 of 556 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-03-24 08:31:42 +01:00
Ihor Hordiichuk
caa816beec
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (556 of 556 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-03-24 08:31:42 +01:00
Oğuz Ersen
605ba186d6
Translated using Weblate (Turkish)
Currently translated at 100.0% (556 of 556 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-03-24 08:31:42 +01:00
josé m
8fa14659be
Translated using Weblate (Galician)
Currently translated at 100.0% (556 of 556 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-03-24 08:31:42 +01:00
Priit Jõerüüt
e1fe8c2ed5
Translated using Weblate (Estonian)
Currently translated at 100.0% (556 of 556 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-03-24 08:31:42 +01:00
Krille
2e73051b81
feat: Add read marker 2023-03-24 08:31:28 +01:00
Krille
1a61ed5d85 Merge branch 'main' into 'main'
treewide: Container -> SizedBox.shrink()

See merge request famedly/fluffychat!1093
2023-03-24 07:30:58 +00:00
noob_tea
9ad8550449 treewide: Container -> SizedBox.shrink()
This helps performance without any user-facing changes,
since SizedBox is constant while Container isn't
2023-03-22 20:30:59 +01:00
Krille
8422c2bf3c
chore: Follow up lastreadeventisvisible marker 2023-03-22 15:06:40 +01:00
Linerly
bf2e6b2787
Translated using Weblate (Indonesian)
Currently translated at 100.0% (555 of 555 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-03-22 13:57:42 +01:00
Siavash
9e01d51520
Translated using Weblate (Persian)
Currently translated at 40.3% (224 of 555 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-03-22 13:57:42 +01:00
Eric
07b92bf876
Translated using Weblate (Chinese (Simplified))
Currently translated at 98.5% (547 of 555 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/zh_Hans/
2023-03-22 13:57:42 +01:00
Ihor Hordiichuk
4863c4a8f3
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (555 of 555 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-03-22 13:57:42 +01:00
Oğuz Ersen
9def8de5a8
Translated using Weblate (Turkish)
Currently translated at 100.0% (555 of 555 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-03-22 13:57:42 +01:00
josé m
f08968800e
Translated using Weblate (Galician)
Currently translated at 100.0% (555 of 555 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-03-22 13:57:42 +01:00
Priit Jõerüüt
d8dee5905d
Translated using Weblate (Estonian)
Currently translated at 100.0% (555 of 555 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-03-22 13:57:42 +01:00
Krille
c2768ae40a
feat: Jump to last read event 2023-03-22 13:16:00 +01:00
Krille
a4a852ede8
feat: Use fragmented timeline to jump to event 2023-03-22 09:16:07 +01:00
Krille
ede1e289ce
chore: Follow up new sliverappbar in chatlist 2023-03-22 08:54:36 +01:00
Krille
d211dd4aeb
chore: Follow up styling 2023-03-20 07:56:49 +01:00
Krille
20c1dbd00a
style: Use SliverList for chatlist 2023-03-19 19:59:50 +01:00
ShootingStarDragons
fa02384808 feat: change to flutterwebauth2 2023-03-19 23:18:31 +08:00
Krille
dd4f2fcc35
chore: Finish arm64 linux workaround 2023-03-19 14:02:49 +01:00
Krille
1b2708f4b0
chore: Final try workaround arm64 linux 2023-03-19 10:06:27 +01:00
Krille
7c9e2bfe3c
chore: Workaround adjustments 2023-03-19 09:35:18 +01:00
Krille
13365488b4
chore: Try again workaround linux arm64 build 2023-03-19 09:33:20 +01:00
Krille
02f564f7ed
chore: Remove workaround for linux arm 2023-03-19 09:06:49 +01:00
Krille
0222e6ecd5
chore: Follow up android download dir 2023-03-19 09:04:08 +01:00
Krille
df91290a18
chore: Follow up download android 2023-03-19 09:01:14 +01:00
Krille
57618417a1
chore: Maybe fix arm64 2023-03-19 08:38:28 +01:00
Krille
5e3c47a433 Merge branch 'krille/clean-up-ci' into 'main'
refactor: CI scripts and old workarounds for build scripts

See merge request famedly/fluffychat!1101
2023-03-19 07:33:17 +00:00
Krille
b30622c1b9
refactor: CI scripts and old workarounds for build scripts 2023-03-19 08:17:16 +01:00
Krille
eb651212e6
CI: Use external runners only for integration tests 2023-03-19 07:35:16 +01:00
Krille
78aa686699
chore: Follow up fix google services patch 2023-03-19 07:28:44 +01:00
Krille
156217c3ae
refactor: Switch to file_picker package and get rid of some dependency overrides 2023-03-18 17:02:12 +01:00
Krille
644ef388de
chore: Follow up redesign listtiles in user bottom sheet 2023-03-18 15:26:17 +01:00
Krille
71eac7078e style: Move chats to top 2023-03-15 21:07:36 +01:00
Krille
511dd41d30 fix: Join public room 2023-03-15 19:39:05 +01:00
Krille
f24b3ee09b style: Minor adjustments for modal bottom sheets 2023-03-15 19:31:14 +01:00
Christian Kußowski
3b6321383e chore: Update matrix sdk to 0.18.0 2023-03-15 09:44:51 +01:00
Oğuz Ersen
8888fd5884
Translated using Weblate (Turkish)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-03-12 21:07:57 +01:00
Luna
0accfe4a26
Translated using Weblate (Polish)
Currently translated at 99.2% (550 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/pl/
2023-03-12 21:07:56 +01:00
Christian Kußowski
535081b483 chore: Follow up qr code width 2023-03-12 17:39:04 +01:00
Christian Kußowski
0f10dfaf91 chore: Update build number 2023-03-12 17:21:17 +01:00
Krille
f0ac88c9ee Merge branch 'nico/fix-emote-rooms-without-default' into 'main'
fix: type error in emote pack list in rooms with only non-default packs

Closes #1138

See merge request famedly/fluffychat!1098
2023-03-11 16:54:38 +00:00
Krille
f4d13e86b6 chore: disable webrtc on linux again 2023-03-11 17:47:52 +01:00
Nicolas Werner
303ccbe965
fix: type error in emote pack list in rooms with only non-default packs
If a room has emote packs, but none of them have an empty state key, we
insert 'null' to also add a default pack people can easily edit.
However, in that case we initialized the Map<String, Event?> variable
with a Map<String, Event>. As such assigning null will throw. Converting
manually with Map.of fixes that.

fixes #1138
2023-03-11 15:05:08 +01:00
Christian
ade164d824
Translated using Weblate (Polish)
Currently translated at 83.3% (462 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/pl/
2023-03-11 07:04:09 +01:00
Luna
e40c86c7e6
Translated using Weblate (Polish)
Currently translated at 83.3% (462 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/pl/
2023-03-11 06:43:50 +01:00
Very Able
a87946a34b
Translated using Weblate (German)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/de/
2023-03-11 06:43:50 +01:00
Krille
863c5f1c13 Merge branch 'eighthave-main-patch-71793' into 'main'
docs: let f-droid.org show the right language to the user

See merge request famedly/fluffychat!1092
2023-03-11 05:43:44 +00:00
Krille
6d21b54c62 Merge branch 'no-key-typo-fix' into 'main'
Fix typo (loose->lose)

See merge request famedly/fluffychat!1094
2023-03-11 05:42:54 +00:00
Krille
c984a272b3 Merge branch 'malin/flutter-3-7-7' into 'main'
chore: Update to Flutter 3.7.7

See merge request famedly/fluffychat!1096
2023-03-11 05:41:49 +00:00
Malin Errenst
6cf0903af3 chore: Update to Flutter 3.7.7 2023-03-10 11:35:50 +01:00
Krille
16a533cf40 refactor: Remove unused dependency 2023-03-09 20:34:32 +01:00
Krille
3e8d14a53f chore: Switch back to main webrtc 2023-03-09 20:32:59 +01:00
Anonimas
1925578a86
Translated using Weblate (Lithuanian)
Currently translated at 96.0% (532 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/lt/
2023-03-07 23:32:43 +01:00
Christian Kußowski
fc62ff3eaa chore: update to flutter 3.7.6 2023-03-07 11:15:52 +01:00
Vivianne Langdon
15dbe4433d Fix typo 2023-03-05 20:14:04 +00:00
Christian Pauly
a8d6dadf84 chore: Update to Flutter 3.7.5 2023-03-03 14:35:37 +01:00
Hans-Christoph Steiner
ee2b55ca78 let f-droid.org show the right language to the user
The old URL forces the page language to German e,g, `de`.  Removing the locale makes f-droid.org show the language that the browser is using.
2023-03-02 10:56:06 +00:00
Christian Pauly
090b026b92 chore: Fix formatting 2023-03-02 11:54:20 +01:00
Krille
e461cb1f53 Merge branch 'malin/addRequireTrailingCommasRule' into 'main'
refactor: Added and applied require_trailing_commas linter rule

See merge request famedly/fluffychat!1091
2023-03-02 10:28:45 +00:00
Malin Errenst
5212d7ce4d refactor: Added and applied require_trailing_commas linter rule 2023-03-02 11:21:40 +01:00
MohammadSaleh Kamyab
ed9e58d0bf
Translated using Weblate (Persian)
Currently translated at 40.0% (222 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-02-27 14:49:21 +01:00
Krille
2b2c230fcf style: Adjust new chat page 2023-02-26 21:13:56 +01:00
Krille
ecf5adcdea chore: Bump version 2023-02-25 15:28:02 +01:00
Krille
6851d34d35 chore: Lookup l10n in pushhelper if null 2023-02-25 15:26:17 +01:00
Krille
006f2f527f Merge branch 'notification_error' into 'main'
Default hardcoded message when l10n is not available

Closes #1146

See merge request famedly/fluffychat!1090
2023-02-25 14:22:08 +00:00
Linerly
1cb20c9ec5
Translated using Weblate (Indonesian)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-02-25 14:37:56 +01:00
Farooq Karimi Zadeh
ec49c5a541
Translated using Weblate (Persian)
Currently translated at 40.0% (222 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fa/
2023-02-25 14:37:56 +01:00
Ihor Hordiichuk
7bbd898131
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-02-25 14:37:55 +01:00
Oğuz Ersen
031da77da6
Translated using Weblate (Turkish)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-02-25 14:37:55 +01:00
josé m
bfd76fdb79
Translated using Weblate (Galician)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-02-25 14:37:55 +01:00
Priit Jõerüüt
0c28169043
Translated using Weblate (Estonian)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-02-25 14:37:54 +01:00
fabienli
fc1b49cf69 Default hardcoded message when l10n is not available 2023-02-25 08:13:50 +01:00
Wphaoka
2b701cf56c
Added translation using Weblate (Thai) 2023-02-24 11:25:27 +01:00
xabirequejo
8b386142cf
Translated using Weblate (Basque)
Currently translated at 96.9% (537 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/eu/
2023-02-23 07:59:45 +01:00
Christian Pauly
cd7e27a6e0 style: Adjust key verification dialog 2023-02-22 15:21:38 +01:00
Christian Pauly
9ab3332824 chore: Follow up formatting 2023-02-21 15:08:01 +01:00
Krille
a60e1435c2 Merge branch 'fix_url_launch_mode' into 'main'
utils/url_launcher: force opening http(s) links in external browser

Closes #519

See merge request famedly/fluffychat!1089
2023-02-21 10:43:49 +00:00
Joaquim Homrighausen
d56ca697ea
Translated using Weblate (Swedish)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/sv/
2023-02-21 11:38:35 +01:00
Marcus Hoffmann
9eaaef1048 utils/url_launcher: force opening http(s) links in external browser
The (mobile) platform implementations for url_launcher default to
opening any http(s) link inside a webview instead of the platform
browser. This seems to be a longer-time problem for iOS
(https://gitlab.com/famedly/fluffychat/-/issues/519) but very recently
started to affect Android as well.

Force url_launcher to always use an external application (the browser,
most likely, but possibly other apps might handle those links as well)
as opening links from a messaging app in a webview provides terrible UX.

(For instance a link might lead to some webpage where you start to fill
in some info but then you need to ask someone via the messanger but
can't go back without closing the webview and losing all state. Or if
you happen to re-launch FluffyChat via the home-screen than it goes back
to the home view and the webview state is completely lost as well.)
2023-02-18 21:42:09 +01:00
josé m
a95cd85eb0
Translated using Weblate (Galician)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/gl/
2023-02-17 20:39:34 +01:00
Krille
32f347ee6f chore: Update matrix package to 0.17.0 2023-02-17 18:28:18 +01:00
Krille
d9645480ac chore: Follow up chat encryption desgin 2023-02-17 16:34:01 +01:00
Christian Pauly
73174003a9 style: Encryption page adjustments 2023-02-17 13:01:44 +01:00
Christian Pauly
3c17d812b3 style: Bootstrap design adjustments 2023-02-17 09:34:23 +01:00
Christian Pauly
e08f601bfd style: Use robotomono to display device keys 2023-02-17 08:45:49 +01:00
Nathan Freitas
799bec5ad9
Added translation using Weblate (Tibetan) 2023-02-15 17:12:44 +01:00
Christian Pauly
a602dc08d5 chore: Follow up fix audioplayer on android 2023-02-15 15:46:14 +01:00
Christian Pauly
a48e42dfcf refactor: Remove syncstatus verbose logs 2023-02-15 15:27:23 +01:00
Linerly
9384ef0503
Translated using Weblate (Indonesian)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-02-15 11:37:10 +01:00
Jelv
d8d9df4e50
Translated using Weblate (Dutch)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/nl/
2023-02-15 11:37:10 +01:00
Ihor Hordiichuk
db2c768029
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-02-15 11:37:09 +01:00
Oğuz Ersen
3353eef728
Translated using Weblate (Turkish)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-02-15 11:37:09 +01:00
Priit Jõerüüt
fba6f60500
Translated using Weblate (Estonian)
Currently translated at 100.0% (554 of 554 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-02-15 11:37:09 +01:00
Krille
10fcf2bac4 chore: Follow up audioplayer on linux 2023-02-14 17:21:06 +01:00
Krille
1cbfb592e9 refactor: Store cached files in tmp directory so OS will clear file cache from time to time 2023-02-14 17:19:28 +01:00
Krille
dfc933115f chore: Disable stable for web until script is fixed 2023-02-14 17:03:26 +01:00
Christian Pauly
2d0e7a491e style: Link underline color 2023-02-14 14:05:18 +01:00
Christian Pauly
e49408e5b0 refactor: Do only instantiate AudioPlayer() object when in use 2023-02-14 12:54:57 +01:00
Christian Pauly
69e0c48c8e feat: Enable audioplayer for web and linux 2023-02-14 09:15:47 +01:00
Suguru Hirahara
4345ab9772
Translated using Weblate (Japanese)
Currently translated at 96.2% (532 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ja/
2023-02-13 15:38:22 +01:00
Christian Pauly
a76ea48d84 fix: Display error when user tries to send too large file 2023-02-13 15:38:08 +01:00
Jelv
78a5206ba7
Translated using Weblate (Dutch)
Currently translated at 100.0% (553 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/nl/
2023-02-10 11:35:41 +01:00
Suguru Hirahara
ac11341677
Translated using Weblate (Japanese)
Currently translated at 64.9% (359 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/ja/
2023-02-09 06:37:52 +01:00
Anne Onyme 017
446fa75a90
Translated using Weblate (French)
Currently translated at 100.0% (553 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/fr/
2023-02-09 06:37:51 +01:00
Priit Jõerüüt
d52bba3523
Translated using Weblate (Estonian)
Currently translated at 100.0% (553 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/et/
2023-02-09 06:37:51 +01:00
Christian Pauly
55c8475eba chore: Follow up settings page design 2023-02-07 13:52:14 +01:00
Christian Pauly
80b5a2b3d4 style: Use emojis on web as well 2023-02-07 12:24:22 +01:00
Linerly
da91c2bd9f
Translated using Weblate (Indonesian)
Currently translated at 100.0% (553 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/id/
2023-02-06 14:34:12 +01:00
Ihor Hordiichuk
116b4ca361
Translated using Weblate (Ukrainian)
Currently translated at 100.0% (553 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/uk/
2023-02-06 14:34:11 +01:00
Oğuz Ersen
5fc4230f9b
Translated using Weblate (Turkish)
Currently translated at 100.0% (553 of 553 strings)

Translation: FluffyChat/Translations
Translate-URL: https://hosted.weblate.org/projects/fluffychat/translations/tr/
2023-02-06 14:34:10 +01:00
Krille
cf88eb1fd7 style: Make invite page more pretty 2023-02-05 13:08:58 +01:00
Krille
cef5fbe3c8 style: Enhance user device settings design 2023-02-05 10:41:28 +01:00
Krille
2ccc30879b chore: Display warning when logout without backup 2023-02-05 10:34:50 +01:00
Krille
c670dc2700 chore: Follow up style adjustments 2023-02-05 10:22:24 +01:00
Krille
d3240fd261 chore: Follow up remove hero animation 2023-02-05 10:09:31 +01:00
9cfffdfa66 docs/qr-stable.svg: update the QR code 2023-02-05 06:39:40 +00:00
Krille
564d1180ed chore: Follow up formatting 2023-02-05 07:39:03 +01:00
Krille
ca03042ff8 chore: Downgrade flutter CI version 2023-02-04 22:00:12 +01:00
Krille
50dc19b0de chore: Follow up settings page 2023-02-04 21:59:53 +01:00
Krille
72767f0716 style: Enhanced chat details design 2023-02-04 19:10:27 +01:00
Krille
59d3793060 chore: Follow up secrity settings design 2023-02-04 18:52:04 +01:00
Krille
a090346046 style: Give chat list list tiles rounded corners 2023-02-04 18:50:15 +01:00
Krille
ede5fdc348 style: New settings design 2023-02-04 18:32:56 +01:00
Krille
90482009fc style: Make adaptive bottom sheets scrollable by default 2023-02-04 17:00:05 +01:00
Krille
4c91ea6002 style: Nicer chips in encryption settings and icons showing device status 2023-02-04 16:56:42 +01:00
Krille
92fa8e1ca5 chore: Update to Flutter 3.7.1 2023-02-04 14:11:12 +00:00
machiav3lli
3442e44a07 Fix: The stable repo fingerprint (TODO the qr-code should be updated) 2023-02-04 01:14:39 +00:00
261 changed files with 45277 additions and 40155 deletions

View File

@ -1,9 +1,7 @@
variables: variables:
FLUTTER_VERSION: 3.7.0 FLUTTER_VERSION: 3.10.0
image: image: ghcr.io/cirruslabs/flutter:${FLUTTER_VERSION}
name: cirrusci/flutter:${FLUTTER_VERSION}
pull_policy: if-not-present
.shared_windows_runners: .shared_windows_runners:
tags: tags:
@ -18,23 +16,25 @@ stages:
code_analyze: code_analyze:
stage: test stage: test
script: [ ./scripts/code_analyze.sh ] script:
- flutter pub get
- dart run import_sorter:main --no-comments --exit-if-changed
- dart format lib/ test/ --set-exit-if-changed
- flutter analyze
- git apply ./scripts/enable-android-google-services.patch
- flutter pub get
- flutter analyze
- flutter pub run dart_code_metrics:metrics lib -r gitlab > code-quality-report.json || true
artifacts: artifacts:
reports: reports:
codequality: code-quality-report.json codequality: code-quality-report.json
tags:
- docker
- famedly
widget_test: widget_test:
stage: test stage: test
script: [ flutter test ] script: [flutter test]
tags:
- docker
- famedly
# the basic integration test configuration testing FLOSS builds on Synapse # the basic integration test configuration testing FLOSS builds on Synapse
integration_test: .integration_test:
image: registry.gitlab.com/famedly/company/frontend/flutter-dockerimages/integration/stable:${FLUTTER_VERSION} image: registry.gitlab.com/famedly/company/frontend/flutter-dockerimages/integration/stable:${FLUTTER_VERSION}
stage: test stage: test
services: services:
@ -74,9 +74,8 @@ integration_test:
- ffmpeg -i video.mkv -vf scale=iw/2:-2 -crf 40 -b:v 2000k -preset fast video.mp4 || true - ffmpeg -i video.mkv -vf scale=iw/2:-2 -crf 40 -b:v 2000k -preset fast video.mp4 || true
timeout: 30m timeout: 30m
retry: 2 retry: 2
rules: only:
- if: '$CI_PIPELINE_SOURCE == "merge_request_event"' - tags
when: always
artifacts: artifacts:
when: always when: always
paths: paths:
@ -85,12 +84,10 @@ integration_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:
image: cirrusci/flutter:${FLUTTER_VERSION} extends: .integration_test
extends: integration_test
parallel: parallel:
matrix: matrix:
- HOMESERVER_IMPLEMENTATION: - HOMESERVER_IMPLEMENTATION:
@ -100,12 +97,12 @@ integration_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
integration_test_proprietary: .integration_test_proprietary:
extends: integration_test extends: .integration_test
parallel: parallel:
matrix: matrix:
- HOMESERVER_IMPLEMENTATION: - HOMESERVER_IMPLEMENTATION:
@ -137,6 +134,8 @@ release_mode_launches:
# generate temporary release build configuration and ensure app launches # generate temporary release build configuration and ensure app launches
- scripts/integration-check-release-build.sh - scripts/integration-check-release-build.sh
timeout: 20m timeout: 20m
only:
- tags
tags: tags:
- docker - docker
- famedly - famedly
@ -144,14 +143,12 @@ 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: [ ./scripts/build-web.sh ] script:
- flutter build web --release --verbose --source-maps
artifacts: artifacts:
paths: paths:
- build/web/ - build/web/
tags:
- docker
- famedly
# yes, we *do* build a Windows DLL on Linux. More reliable. # yes, we *do* build a Windows DLL on Linux. More reliable.
build_olm_windows: build_olm_windows:
@ -197,28 +194,28 @@ build_windows:
build_android_debug: build_android_debug:
stage: build stage: build
script: [ ./scripts/build-android-debug.sh ] script: [flutter build apk --debug]
artifacts: artifacts:
when: on_success when: on_success
paths: paths:
- build/app/outputs/apk/debug/app-debug.apk - build/app/outputs/apk/debug/app-debug.apk
except:
- main
- tags
tags: tags:
- docker - docker
- famedly - famedly
except:
- main
- tags
build_android_apk: build_android_apk:
stage: build stage: build
before_script: before_script:
- git apply ./scripts/enable-android-google-services.patch - git apply ./scripts/enable-android-google-services.patch
- ./scripts/prepare-android-release.sh - ./scripts/prepare-android-release.sh
script: [ ./scripts/build-android-apk.sh ] script: [flutter build apk --release]
artifacts: artifacts:
when: on_success when: on_success
paths: paths:
- build/android/app-release.apk - build/app/outputs/apk/release/app-release.apk
tags: tags:
- docker - docker
- famedly - famedly
@ -231,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:
@ -258,9 +255,6 @@ fdroid_repo:
needs: needs:
- "build_android_apk" - "build_android_apk"
resource_group: playstore_release resource_group: playstore_release
tags:
- docker
- famedly
allow_failure: true allow_failure: true
only: only:
- main - main
@ -280,12 +274,7 @@ pages:
- cd .. - cd ..
- mv docs public - mv docs public
- mv repo public || true - mv repo public || true
- mv build/web/ public/nightly - mv build/web/ public/web
# ensure the nightly deployment knows its location
- sed -i "s/href=\"\/web\/\"/href=\"\/nightly\/\"/g" public/nightly/index.html
- rm -rf build
- ./scripts/download-web-stable.sh
- mv stable public/web
artifacts: artifacts:
paths: paths:
- public - public
@ -294,12 +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 && DEBIAN_FRONTEND=noninteractive apt-get install keyboard-configuration -y && sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 -y, - sudo apt-get install curl clang cmake ninja-build pkg-config libgtk-3-dev libblkid-dev liblzma-dev libjsoncpp-dev cmake-data libsecret-1-dev libsecret-1-0 librhash0 -y
] script: [flutter build linux --release]
script: [ ./scripts/build-linux.sh ]
tags: tags:
- docker - docker
- famedly - famedly
@ -310,9 +298,10 @@ build_linux_x86:
build_linux_arm64: build_linux_arm64:
stage: build stage: build
before_script: [ flutter upgrade ] before_script:
script: [ ./scripts/build-linux.sh ] - flutter upgrade $FLUTTER_VERSION --force
tags: [ docker_arm64 ] script: [flutter build linux --release]
tags: [docker_arm64]
only: only:
- main - main
- tags - tags
@ -324,9 +313,7 @@ build_linux_arm64:
update_dependencies: update_dependencies:
stage: build stage: build
needs: [ ] needs: []
tags:
- docker
only: only:
- schedules - schedules
variables: variables:
@ -351,9 +338,6 @@ update_dependencies:
.release: .release:
stage: deploy stage: deploy
image: curlimages/curl:latest image: curlimages/curl:latest
tags:
- docker
- famedly
rules: rules:
- if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/' - if: '$CI_COMMIT_TAG =~ /^v\d+\.\d+\.\d+$/'
- if: '$CI_COMMIT_TAG =~ /^rc\d+\.\d+\.\d+-\d+$/' - if: '$CI_COMMIT_TAG =~ /^rc\d+\.\d+\.\d+-\d+$/'
@ -366,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
@ -398,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,165 @@
## v1.12.0
- Added translation using Weblate (Toki Pona) (Mæve Rey)
- Translated using Weblate (Arabic) (Rex_sa)
- Translated using Weblate (Chinese (Simplified)) (Eric)
- Translated using Weblate (Croatian) (Milo Ivir)
- Translated using Weblate (Estonian) (Priit Jõerüüt)
- Translated using Weblate (Galician) (josé m)
- Translated using Weblate (Indonesian) (Linerly)
- Translated using Weblate (Polish) (lauren n. liberda)
- Translated using Weblate (Romanian) (Riley)
- Translated using Weblate (Russian) (DarkCoder15)
- Translated using Weblate (Spanish) (José Muñoz)
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
- build: Remove dependency overwrite for ffi (Krille)
- build: Update dependencies (Krille)
- builds: Change minsdkversion of Android from 16 to 19 (Krille)
- builds: Do not allow failure for linux x86 (Krille)
- builds: Do not use verbose mode on building linux (Krille)
- builds: Linux with flutter 3.10 (Krille)
- builds: Remove workaround for building linux arm64 (Krille)
- builds: Update file_picker to 5.3.0 (Krille)
- builds: Update flutter table html (Krille)
- builds: Update flutter_html (Krille)
- builds: migrate to dart 3.0/flutter 3.10 (lauren n. liberda)
- chore: Add missing blockquote style (Krille)
- chore: Allow failure in build linux for now (Krille)
- chore: Ask for storage persistence (Krille)
- chore: Clean unused translations (Malin Errenst)
- chore: Enhance room pills (Krille)
- chore: Minor code clean up (Krille)
- chore: Update flutter webrtc (Krille)
- chore: Upgrade to Flutter 3.10.1 (Malin Errenst)
- chore: change release curl calls to use --fail-with-body (Tim Flink)
- chore: update macOS icons and add build script (TheOneWithTheBraid)
- design: Replace anime images with neutral cupertino icons (Krille)
- feat: Add toggle to mute notifications from chat groups (fbievan)
- feat: Allow ruby tags in html (Krille)
- feat: Display progress value for initial sync (Krille)
- feat: Implement new error reporting tool when critical features break like playing audio or video messages or opening a chat (Krille)
- feat: clean up macOS build metadata (TheOneWithTheBraid)
- feat: set display information correctly (TheOneWithTheBraid)
- feat: update macOS build files (TheOneWithTheBraid)
- feat: update macOS build information for macOS Ventura (TheOneWithTheBraid)
- fix "Unhandled Exception: VRouter.of(context) was called with a context which does not contain a VRouter." (Lauren N. Liberda)
- fix: Broken arb file (Krille)
- fix: Do not unnecessary request all members in public rooms (Krille)
- fix: Remove wrong rendered linebreak in html (Krille)
- fix: Scroll down button (Krille)
- fix: Scroll up and scroll down buttons in chat list (Krille)
- fix: Scrolldown button (Krille)
- fix: Too long file name cause a render overflow (Skying)
- fix: Try to reload timeline on IOException (Krille)
- fix: User pills (Krille)
- fix: broken CI artifact uploads (TheOneWithTheBraid)
- fix: custom emote placeholder (TheOneWithTheBraid)
- fix: path of libolm (TheOneWithTheBraid)
- fix: Quick account switching (JHansen)
- fix: read reciepts (JHansen)
- perf: Use valuenotifier to not rebuild chatlist (Krille)
- refactor: Reimplement flutter matrix html locally (Krille)
- refactor: Update Roboto and Noto Emoji (The one with the Braid)
- refactor: Use AnimatedSize for FAB (Krille)
- refactor: Use DateTime for weekday localization (Malin Errenst)
## v1.11.2
- Translated using Weblate (Croatian) (Milo Ivir)
- Translated using Weblate (Dutch) (Jelv)
- Translated using Weblate (Estonian) (Priit Jõerüüt)
- Translated using Weblate (Galician) (josé m)
- Translated using Weblate (Polish) (Eryk Michalak)
- Translated using Weblate (Turkish) (Oğuz Ersen)
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
- feat: Permission dialog before open link in browser (Krille)
- fix: Chats do not load (Krille)
## v1.11.1 - 2023-04-20
- fix: Download files on web and iOS with correct mimetype
## v1.11.0 - 2023-04-14
- feat: Add visual read marker (Krille)
- feat: Jump to last read event (Krille)
- feat: Use fragmented timeline to jump to event (Krille)
- feat: change to flutterwebauth2 (ShootingStarDragons)
- fix: Join public room (Krille)
- fix: Set fcm priority to max on android (Krille)
- refactor: CI scripts and old workarounds for build scripts (Krille)
- refactor: Client in ChatPage (Krille)
- refactor: Not nullable room in ChatPage (Krille)
- refactor: Switch to file_picker package and get rid of some dependency overrides (Krille)
- refactor: Use correct Matrix instance (Krille)
- style: Make emptypage logo bigger (Krille)
- style: Minor adjustments for modal bottom sheets (Krille)
- style: Move chats to top (Krille)
- style: Use SliverList for chatlist (Krille)
- refactor: Container -> SizedBox.shrink() (noob_tea)
- Translated using Weblate (Chinese (Simplified)) (Eric)
- Translated using Weblate (Dutch) (Jelv)
- Translated using Weblate (Estonian) (Priit Jõerüüt)
- Translated using Weblate (French) (Anne Onyme 017)
- Translated using Weblate (Galician) (josé m)
- Translated using Weblate (Indonesian) (Linerly)
- Translated using Weblate (Persian) (Parsa)
- Translated using Weblate (Persian) (Siavash)
- Translated using Weblate (Polish) (Luna)
- Translated using Weblate (Swedish) (Kristoffer Grundström)
- Translated using Weblate (Turkish) (Oğuz Ersen)
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
## v1.10.0 - 2023-02-25
- Added translation using Weblate (Thai) (Wphaoka)
- Added translation using Weblate (Tibetan) (Nathan Freitas)
- Default hardcoded message when l10n is not available (fabienli)
- Fix: The stable repo fingerprint (TODO the qr-code should be updated) (machiav3lli)
- Translated using Weblate (Basque) (xabirequejo)
- Translated using Weblate (Dutch) (Jelv)
- Translated using Weblate (Estonian) (Priit Jõerüüt)
- Translated using Weblate (French) (Anne Onyme 017)
- Translated using Weblate (Galician) (josé m)
- Translated using Weblate (Galician) (josé m)
- Translated using Weblate (Indonesian) (Linerly)
- Translated using Weblate (Japanese) (Suguru Hirahara)
- Translated using Weblate (Persian) (Farooq Karimi Zadeh)
- Translated using Weblate (Swedish) (Joaquim Homrighausen)
- Translated using Weblate (Turkish) (Oğuz Ersen)
- Translated using Weblate (Ukrainian) (Ihor Hordiichuk)
- chore: Disable stable for web until script is fixed (Krille)
- chore: Display warning when logout without backup (Krille)
- chore: Downgrade flutter CI version (Krille)
- chore: Follow up audioplayer on linux (Krille)
- chore: Follow up chat encryption desgin (Krille)
- chore: Follow up fix audioplayer on android (Christian Pauly)
- chore: Follow up formatting (Christian Pauly)
- chore: Follow up formatting (Krille)
- chore: Follow up remove hero animation (Krille)
- chore: Follow up secrity settings design (Krille)
- chore: Follow up settings page (Krille)
- chore: Follow up settings page design (Christian Pauly)
- chore: Follow up style adjustments (Krille)
- chore: Lookup l10n in pushhelper if null (Krille)
- chore: Update matrix package to 0.17.0 (Krille)
- chore: Update to Flutter 3.7.1 (Krille)
- docs/qr-stable.svg: update the QR code (Aminda Suomalainen)
- feat: Enable audioplayer for web and linux (Christian Pauly)
- fix: Display error when user tries to send too large file (Christian Pauly)
- refactor: Do only instantiate AudioPlayer() object when in use (Christian Pauly)
- refactor: Remove syncstatus verbose logs (Christian Pauly)
- refactor: Store cached files in tmp directory so OS will clear file cache from time to time (Krille)
- style: Adjust key verification dialog (Christian Pauly)
- style: Bootstrap design adjustments (Christian Pauly)
- style: Encryption page adjustments (Christian Pauly)
- style: Enhance user device settings design (Krille)
- style: Enhanced chat details design (Krille)
- style: Give chat list list tiles rounded corners (Krille)
- style: Link underline color (Christian Pauly)
- style: Make adaptive bottom sheets scrollable by default (Krille)
- style: Make invite page more pretty (Krille)
- style: New settings design (Krille)
- style: Nicer chips in encryption settings and icons showing device status (Krille)
- style: Use emojis on web as well (Christian Pauly)
- style: Use robotomono to display device keys (Christian Pauly)
- utils/url_launcher: force opening http(s) links in external browser (Marcus Hoffmann)
## v1.9.0 - 2023-01-29 ## v1.9.0 - 2023-01-29
- Translated using Weblate (Czech) (Michal Bedáň) - Translated using Weblate (Czech) (Michal Bedáň)
- Translated using Weblate (Czech) (grreby) - Translated using Weblate (Czech) (grreby)

View File

@ -1,4 +1,4 @@
FROM cirrusci/flutter as builder FROM ghcr.io/cirruslabs/flutter as builder
RUN sudo apt update && sudo apt install curl -y RUN sudo apt update && sudo apt install curl -y
COPY . /app COPY . /app
WORKDIR /app WORKDIR /app

View File

@ -8,6 +8,7 @@ linter:
- prefer_final_locals - prefer_final_locals
- prefer_final_in_for_each - prefer_final_in_for_each
- sort_pub_dependencies - sort_pub_dependencies
- require_trailing_commas
analyzer: analyzer:
errors: errors:

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

@ -93,8 +93,9 @@
</intent-filter> </intent-filter>
</activity> </activity>
<activity android:name="com.linusu.flutter_web_auth.CallbackActivity" <activity
android:exported="true"> android:name="com.linusu.flutter_web_auth_2.CallbackActivity"
android:exported="true">
<intent-filter android:label="flutter_web_auth"> <intent-filter android:label="flutter_web_auth">
<action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.VIEW" />
<category android:name="android.intent.category.DEFAULT" /> <category android:name="android.intent.category.DEFAULT" />

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

View File

@ -5,12 +5,17 @@
<testcase classname="fastlane.lanes" name="0: update_fastlane" time="0.000202"> <testcase classname="fastlane.lanes" name="0: update_fastlane" time="1.455419">
</testcase> </testcase>
<testcase classname="fastlane.lanes" name="1: default_platform" time="7.9e-05"> <testcase classname="fastlane.lanes" name="1: default_platform" time="0.000127">
</testcase>
<testcase classname="fastlane.lanes" name="2: google_play_track_version_codes" time="2.638619">
</testcase> </testcase>

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

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

@ -0,0 +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",
@ -537,12 +530,12 @@
}, },
"description": "State that {command} is not a valid /command." "description": "State that {command} is not a valid /command."
}, },
"compareEmojiMatch": "Compare and make sure the following emoji match those of the other device:", "compareEmojiMatch": "Please compare the emojis",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Compare and make sure the following numbers match those of the other device:", "compareNumbersMatch": "Please compare the numbers",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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.",
@ -2480,7 +2421,7 @@
"@otherCallingPermissions": {}, "@otherCallingPermissions": {},
"whyIsThisMessageEncrypted": "Why is this message unreadable?", "whyIsThisMessageEncrypted": "Why is this message unreadable?",
"@whyIsThisMessageEncrypted": {}, "@whyIsThisMessageEncrypted": {},
"noKeyForThisMessage": "This can happen if the message was sent before you have signed in to your account at this device.\n\nIt is also possible that the sender has blocked your device or something went wrong with the internet connection.\n\nAre you able to read the message on another session? Then you can transfer the message from it! Go to Settings > Devices and make sure that your devices have verified each other. When you open the room the next time and both sessions are in the foreground, the keys will be transmitted automatically.\n\nDo you not want to loose the keys when logging out or switching devices? Make sure that you have enabled the chat backup in the settings.", "noKeyForThisMessage": "This can happen if the message was sent before you have signed in to your account at this device.\n\nIt is also possible that the sender has blocked your device or something went wrong with the internet connection.\n\nAre you able to read the message on another session? Then you can transfer the message from it! Go to Settings > Devices and make sure that your devices have verified each other. When you open the room the next time and both sessions are in the foreground, the keys will be transmitted automatically.\n\nDo you not want to lose the keys when logging out or switching devices? Make sure that you have enabled the chat backup in the settings.",
"@noKeyForThisMessage": {}, "@noKeyForThisMessage": {},
"newGroup": "New group", "newGroup": "New group",
"@newGroup": {}, "@newGroup": {},
@ -2516,5 +2457,24 @@
"deviceKeys": "Device keys:", "deviceKeys": "Device keys:",
"letsStart": "Let's start", "letsStart": "Let's start",
"enterInviteLinkOrMatrixId": "Enter invite link or Matrix ID...", "enterInviteLinkOrMatrixId": "Enter invite link or Matrix ID...",
"reopenChat": "Reopen chat" "reopenChat": "Reopen chat",
} "noBackupWarning": "Warning! Without enabling chat backup, you will lose access to your encrypted messages. It is highly recommended to enable the chat backup first before logging out.",
"noOtherDevicesFound": "No other devices found",
"fileIsTooBigForServer": "The server reports that the file is too large to be sent.",
"fileHasBeenSavedAt": "File has been saved at {path}",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"jumpToLastReadMessage": "Jump to last read message",
"readUpToHere": "Read up to here",
"jump": "Jump",
"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",
@ -448,12 +443,12 @@
}, },
"description": "State that {command} is not a valid /command." "description": "State that {command} is not a valid /command."
}, },
"compareEmojiMatch": "Võrdle ja kontrolli, et emotikonid on teises seadmes täpselt samad:", "compareEmojiMatch": "Palun võrdle emotikone",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Võrdle ja kontrolli, et järgnevad numbrid on teises seadmes täpselt samad:", "compareNumbersMatch": "Palun võrdle numbreid",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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,12 +2464,51 @@
"@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!",
"@letsStart": {}, "@letsStart": {},
"reopenChat": "Alusta vestlust uuesti", "reopenChat": "Alusta vestlust uuesti",
"@reopenChat": {} "@reopenChat": {},
"noOtherDevicesFound": "Muid seadmeid ei leidu",
"@noOtherDevicesFound": {},
"noBackupWarning": "Hoiatus! Kui sa ei lülita sisse vestluse varundust, siis sul puudub hiljem ligipääs krüptitud sõnumitele. Me tungivalt soovitame, et palun lülita vestluse varundamine sisse enne väljalogimist.",
"@noBackupWarning": {},
"fileIsTooBigForServer": "Serveri seadistuste alusel on see fail saatmiseks liiga suur.",
"@fileIsTooBigForServer": {},
"fileHasBeenSavedAt": "Fail on salvestatud kausta: {path}",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"jumpToLastReadMessage": "Liigu viimase loetud sõnumini",
"@jumpToLastReadMessage": {},
"readUpToHere": "Siiamaani on loetud",
"@readUpToHere": {},
"jump": "Hüppa",
"@jump": {},
"openLinkInBrowser": "Ava link veebibrauseris",
"@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": {}
} }

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

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": {}
@ -448,12 +443,12 @@
}, },
"description": "State that {command} is not a valid /command." "description": "State that {command} is not a valid /command."
}, },
"compareEmojiMatch": "Comparar e asegurarse de que estas emoticonas concordan no outro dispositivo:", "compareEmojiMatch": "Compara estes emojis",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Compara e asegúrate de que os seguintes números concordan cos do outro dispositivo:", "compareNumbersMatch": "Compara estes números",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"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": {},
@ -2539,5 +2469,46 @@
} }
}, },
"reopenChat": "Reabrir conversa", "reopenChat": "Reabrir conversa",
"@reopenChat": {} "@reopenChat": {},
"noOtherDevicesFound": "Non se atopan outros dispositivos",
"@noOtherDevicesFound": {},
"noBackupWarning": "Aviso! Se non activas a copia de apoio do chat, perderás o acceso ás túas mensaxes cifradas. É totalmente recomendable activar a copia de apoio do chat antes de pechar a sesión.",
"@noBackupWarning": {},
"fileIsTooBigForServer": "O servidor informa de que o ficheiro é demasiado grande para envialo.",
"@fileIsTooBigForServer": {},
"fileHasBeenSavedAt": "Gardouse o ficheiro en {path}",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"jumpToLastReadMessage": "Ir á última mensaxe lida",
"@jumpToLastReadMessage": {},
"readUpToHere": "Lin ate aquí",
"@readUpToHere": {},
"openLinkInBrowser": "Abrir ligazón no navegador",
"@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",

File diff suppressed because it is too large Load Diff

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",
@ -786,12 +771,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Bandingkan dan pastikan angka cocok di perangkat lainnya:", "compareNumbersMatch": "Bandingkan angka",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareEmojiMatch": "Bandingkan dan pastikan emoji cocok di perangkat lainnya:", "compareEmojiMatch": "Bandingkan emoji",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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,12 +2463,51 @@
"@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...",
"@enterInviteLinkOrMatrixId": {}, "@enterInviteLinkOrMatrixId": {},
"reopenChat": "Buka obrolan lagi", "reopenChat": "Buka obrolan lagi",
"@reopenChat": {} "@reopenChat": {},
"noBackupWarning": "Peringatan! Tanpa mengaktifkan cadangan percakapan, kamu akan kehilangan akses ke pesan terenkripsimu. Disarankan untuk mengaktifkan cadangan percakapan terlebih dahulu sebelum keluar dari akun.",
"@noBackupWarning": {},
"noOtherDevicesFound": "Tidak ada perangkat lain yang ditemukan",
"@noOtherDevicesFound": {},
"fileIsTooBigForServer": "Server melaporkan bahwa file terlalu besar untuk dikirim.",
"@fileIsTooBigForServer": {},
"fileHasBeenSavedAt": "Berkas telah disimpan di {path}",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"jumpToLastReadMessage": "Pergi ke pesan terakhir dibaca",
"@jumpToLastReadMessage": {},
"readUpToHere": "Baca sampai sini",
"@readUpToHere": {},
"jump": "Lompat",
"@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",

View File

@ -11,7 +11,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"acceptedTheInvitation": "{username}が招待を承諾しました", "acceptedTheInvitation": "👍{username}が招待を承諾しました",
"@acceptedTheInvitation": { "@acceptedTheInvitation": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -23,7 +23,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"activatedEndToEndEncryption": "{username}がエンドツーエンド暗号化を有効にしました", "activatedEndToEndEncryption": "🔐{username}がエンドツーエンド暗号化を有効にしました",
"@activatedEndToEndEncryption": { "@activatedEndToEndEncryption": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -77,11 +77,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "アーカイブされた部屋",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "ゲストユーザーの参加を許可する", "areGuestsAllowedToJoin": "ゲストユーザーの参加を許可する",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -109,7 +104,7 @@
"username": {} "username": {}
} }
}, },
"badServerLoginTypesException": "ホームサーバーでサポートされているログインタイプ:\n{serverVersions}\nアプリでは{supportedVersions}しかサポートされていません", "badServerLoginTypesException": "ホームサーバーでサポートされているログインタイプ:\n{serverVersions}\nアプリがサポートしているログインタイプ:\n{supportedVersions}",
"@badServerLoginTypesException": { "@badServerLoginTypesException": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -312,7 +307,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"chatBackupDescription": "チャットのバックアップは秘密鍵によって保存されます。失くさないように気をつけてください。", "chatBackupDescription": "古いメッセージはリカバリーキーで保護されます。紛失しないようにご注意ください。",
"@chatBackupDescription": { "@chatBackupDescription": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -423,7 +418,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"createdTheChat": "{username}がチャットを作成しました", "createdTheChat": "💬 {username}がチャットを作成しました",
"@createdTheChat": { "@createdTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -435,11 +430,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "相互署名ON",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "現在アクティブです", "currentlyActive": "現在アクティブです",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -525,11 +515,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "発見する",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "表示名が変更されました", "displaynameHasBeenChanged": "表示名が変更されました",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -687,11 +672,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "金曜日",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "参加時点から閲覧可能", "fromJoining": "参加時点から閲覧可能",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -839,7 +819,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"invitedUser": "{username}が{targetName}を招待しました", "invitedUser": "📩 {username} {targetName} を招待しました",
"@invitedUser": { "@invitedUser": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -870,7 +850,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"joinedTheChat": "{username}がチャットに参加しました", "joinedTheChat": "👋 {username} がチャットに参加しました",
"@joinedTheChat": { "@joinedTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -882,12 +862,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "鍵はキャッシュされたいます", "kicked": "👞 {username} は {targetName} をキックしました",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username}は{targetName}をキックしました",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -895,7 +870,7 @@
"targetName": {} "targetName": {}
} }
}, },
"kickedAndBanned": "{username}は{targetName}をキックしBANしました", "kickedAndBanned": "🙅 {username} が {targetName} をキックしブロックしました",
"@kickedAndBanned": { "@kickedAndBanned": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1004,11 +979,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "月曜日",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "チャットのミュート", "muteChat": "チャットのミュート",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -1024,7 +994,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"newMessageInFluffyChat": "FluffyChatに新しいメッセージがあります", "newMessageInFluffyChat": "💬 FluffyChatに新しいメッセージがあります",
"@newMessageInFluffyChat": { "@newMessageInFluffyChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1059,7 +1029,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"noGoogleServicesWarning": "あなたのスマホにはグーグルサービスがないようですね。プライバシーを保護するための良い選択です!Push通知を受け取るにはmicroGを使うことを推奨しています: https://microg.org/", "noGoogleServicesWarning": "あなたのスマホにはGoogleサービスがないようですね。プライバシーを保護するための良い選択です!プッシュ通知を受け取るには https://microg.org/ または https://unifiedpush.org/ を使うことをお勧めします。",
"@noGoogleServicesWarning": { "@noGoogleServicesWarning": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1319,7 +1289,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"unbanFromChat": "追放を取り消し", "unbanFromChat": "チャットからのブロックを解除する",
"@unbanFromChat": { "@unbanFromChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1359,11 +1329,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "土曜日",
"@saturday": {
"type": "text",
"placeholders": {}
},
"search": "検索", "search": "検索",
"@search": { "@search": {
"type": "text", "type": "text",
@ -1437,35 +1402,35 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sentAFile": "{username}はファイルを送信しました", "sentAFile": "📁 {username}はファイルを送信しました",
"@sentAFile": { "@sentAFile": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAnAudio": "{username}は音声を送信しました", "sentAnAudio": "🎤 {username}は音声を送信しました",
"@sentAnAudio": { "@sentAnAudio": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAPicture": "{username}は画像を送信しました", "sentAPicture": "🖼️ {username}は画像を送信しました",
"@sentAPicture": { "@sentAPicture": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentASticker": "{username}はステッカーを送信しました", "sentASticker": "😊 {username}はステッカーを送信しました",
"@sentASticker": { "@sentASticker": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAVideo": "{username}は動画を送信しました", "sentAVideo": "🎥 {username}は動画を送信しました",
"@sentAVideo": { "@sentAVideo": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1568,11 +1533,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "日曜日",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "システム", "systemTheme": "システム",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1588,16 +1548,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",
@ -1634,11 +1584,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "火曜日",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "不在", "unavailable": "不在",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1684,7 +1629,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"unreadChats": "{unreadCount, plural, other{{unreadCount}の未読メッセージ}}", "unreadChats": "{unreadCount, plural, =1{1件の未読メッセージ} other{{unreadCount}の未読メッセージ}}",
"@unreadChats": { "@unreadChats": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1714,7 +1659,7 @@
"username": {} "username": {}
} }
}, },
"userLeftTheChat": "{username}は退室しました", "userLeftTheChat": "🚪 {username}はチャットから退室しました",
"@userLeftTheChat": { "@userLeftTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1809,11 +1754,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "水曜日",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "あなたにメールを送信しました", "weSentYouAnEmail": "あなたにメールを送信しました",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -1829,12 +1769,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"whyDoYouWantToReportThis": "なぜこれを通報したいのですか?", "whyDoYouWantToReportThis": "これを通報する理由",
"@whyDoYouWantToReportThis": { "@whyDoYouWantToReportThis": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wipeChatBackup": "新しい秘密鍵を作るためにチャットのバックアップを消去しますか?", "wipeChatBackup": "チャットのバックアップを消去して、新しいリカバリーキーを作りますか?",
"@wipeChatBackup": { "@wipeChatBackup": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1921,8 +1861,6 @@
"type": "text", "type": "text",
"placeholder": {} "placeholder": {}
}, },
"yourUserId": "あなたのユーザーID:",
"@yourUserId": {},
"yourChatBackupHasBeenSetUp": "チャットバックアップを設定ました。", "yourChatBackupHasBeenSetUp": "チャットバックアップを設定ました。",
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"sendOnEnter": "Enterで送信", "sendOnEnter": "Enterで送信",
@ -1945,5 +1883,508 @@
"description": "Usage hint for the command /clearcache" "description": "Usage hint for the command /clearcache"
}, },
"addToStory": "ストーリーに追加", "addToStory": "ストーリーに追加",
"@addToStory": {} "@addToStory": {},
"commandInvalid": "コマンドが無効",
"@commandInvalid": {
"type": "text"
},
"updateNow": "バックグラウンドでアップデートを開始",
"@updateNow": {},
"updateAvailable": "FluffyChatのアップデートが利用可能",
"@updateAvailable": {},
"commandHint_create": "空のグループチャットを作成\n暗号化を無効にするには、--no-encryption を使用",
"@commandHint_create": {
"type": "text",
"description": "Usage hint for the command /create"
},
"commandHint_discardsession": "セッションを破棄",
"@commandHint_discardsession": {
"type": "text",
"description": "Usage hint for the command /discardsession"
},
"confirmMatrixId": "アカウントを削除するには、Matrix IDを確認してください。",
"@confirmMatrixId": {},
"commandHint_markasgroup": "グループとしてマーク",
"@commandHint_markasgroup": {},
"commandHint_join": "指定した部屋に参加",
"@commandHint_join": {
"type": "text",
"description": "Usage hint for the command /join"
},
"commandHint_send": "テキストを送信",
"@commandHint_send": {
"type": "text",
"description": "Usage hint for the command /send"
},
"hydrate": "バックアップファイルから復元",
"@hydrate": {},
"commandHint_html": "HTML形式のテキストを送信",
"@commandHint_html": {
"type": "text",
"description": "Usage hint for the command /html"
},
"commandHint_invite": "指定したユーザーをこの部屋に招待",
"@commandHint_invite": {
"type": "text",
"description": "Usage hint for the command /invite"
},
"commandMissing": "{command} はコマンドではありません。",
"@commandMissing": {
"type": "text",
"placeholders": {
"command": {}
},
"description": "State that {command} is not a valid /command."
},
"oneClientLoggedOut": "クライアントの 1つがログアウトしました",
"@oneClientLoggedOut": {},
"addAccount": "アカウントを追加",
"@addAccount": {},
"editBundlesForAccount": "このアカウントのバンドルを編集",
"@editBundlesForAccount": {},
"unverified": "未検証",
"@unverified": {},
"sender": "送信者",
"@sender": {},
"unsubscribeStories": "ストーリーの購読を解除する",
"@unsubscribeStories": {},
"yourStory": "あなたのストーリー",
"@yourStory": {},
"matrixWidgets": "Matrixのウィジェット",
"@matrixWidgets": {},
"placeCall": "電話をかける",
"@placeCall": {},
"voiceCall": "音声通話",
"@voiceCall": {},
"unsupportedAndroidVersionLong": "この機能を利用するには、より新しいAndroidのバージョンが必要です。アップデートまたはLineage OSのサポートをご確認ください。",
"@unsupportedAndroidVersionLong": {},
"widgetVideo": "動画",
"@widgetVideo": {},
"widgetName": "名称",
"@widgetName": {},
"widgetCustom": "カスタム",
"@widgetCustom": {},
"widgetJitsi": "Jitsi Meet",
"@widgetJitsi": {},
"dehydrateWarning": "この操作は元に戻せません。バックアップファイルを安全に保存してください。",
"@dehydrateWarning": {},
"dehydrate": "セッションのエクスポートとデバイスの消去",
"@dehydrate": {},
"messageType": "メッセージの種類",
"@messageType": {},
"start": "開始",
"@start": {},
"publish": "公開",
"@publish": {},
"addDescription": "説明を追加",
"@addDescription": {},
"indexedDbErrorTitle": "プライベートモードに関する問題",
"@indexedDbErrorTitle": {},
"addWidget": "ウィジェットを追加",
"@addWidget": {},
"youBannedUser": "{user} を禁止しました",
"@youBannedUser": {
"placeholders": {
"user": {}
}
},
"youJoinedTheChat": "チャットに参加しました",
"@youJoinedTheChat": {},
"youHaveWithdrawnTheInvitationFor": "{user} への招待を取り下げました",
"@youHaveWithdrawnTheInvitationFor": {
"placeholders": {
"user": {}
}
},
"users": "ユーザー",
"@users": {},
"youRejectedTheInvitation": "招待を拒否しました",
"@youRejectedTheInvitation": {},
"screenSharingDetail": "FuffyChatで画面を共有しています",
"@screenSharingDetail": {},
"enterASpacepName": "スペース名を入力してください",
"@enterASpacepName": {},
"homeserver": "ホームサーバー",
"@homeserver": {},
"scanQrCode": "QRコードをスキャン",
"@scanQrCode": {},
"obtainingLocation": "位置情報を取得しています…",
"@obtainingLocation": {
"type": "text",
"placeholders": {}
},
"addToBundle": "バンドルに追加",
"@addToBundle": {},
"removeFromBundle": "このバンドルから削除",
"@removeFromBundle": {},
"bundleName": "バンドル名",
"@bundleName": {},
"noMatrixServer": "{server1} はMatrixのサーバーではありません。代わりに {server2} を使用しますか?",
"@noMatrixServer": {
"type": "text",
"placeholders": {
"server1": {},
"server2": {}
}
},
"openVideoCamera": "ビデオ用にカメラを開く",
"@openVideoCamera": {
"type": "text",
"placeholders": {}
},
"link": "リンク",
"@link": {},
"or": "または",
"@or": {
"type": "text",
"placeholders": {}
},
"register": "登録",
"@register": {
"type": "text",
"placeholders": {}
},
"removeYourAvatar": "アバターを削除する",
"@removeYourAvatar": {
"type": "text",
"placeholders": {}
},
"saveFile": "ファイルを保存",
"@saveFile": {
"type": "text",
"placeholders": {}
},
"recoveryKey": "リカバリーキー",
"@recoveryKey": {},
"showDirectChatsInSpaces": "関連するダイレクトチャットをスペースに表示する",
"@showDirectChatsInSpaces": {
"type": "text",
"placeholders": {}
},
"singlesignon": "シングルサインオン",
"@singlesignon": {
"type": "text",
"placeholders": {}
},
"spaceIsPublic": "スペースは公開されています",
"@spaceIsPublic": {
"type": "text",
"placeholders": {}
},
"spaceName": "スペース名",
"@spaceName": {
"type": "text",
"placeholders": {}
},
"startFirstChat": "最初のチャットを開始する",
"@startFirstChat": {},
"addToSpaceDescription": "このチャットを追加するスペースを選択してください。",
"@addToSpaceDescription": {},
"messageInfo": "メッセージの情報",
"@messageInfo": {},
"openGallery": "ギャラリーを開く",
"@openGallery": {},
"removeFromSpace": "スペースから削除",
"@removeFromSpace": {},
"pleaseEnterRecoveryKeyDescription": "古いメッセージを解除するには、以前のセッションで生成されたリカバリーキーを入力してください。リカバリーキーはパスワードではありません。",
"@pleaseEnterRecoveryKeyDescription": {},
"thisUserHasNotPostedAnythingYet": "このユーザーはまだストーリーに何も投稿していません",
"@thisUserHasNotPostedAnythingYet": {},
"replyHasBeenSent": "返信が送信されました",
"@replyHasBeenSent": {},
"videoWithSize": "ビデオ ({size})",
"@videoWithSize": {
"type": "text",
"placeholders": {
"size": {}
}
},
"storyFrom": "{date}からのストーリー:\n{body}",
"@storyFrom": {
"type": "text",
"placeholders": {
"date": {},
"body": {}
}
},
"whoCanSeeMyStoriesDesc": "あなたのストーリーでは、人々がお互いを見て連絡を取ることができることに注意してください。",
"@whoCanSeeMyStoriesDesc": {},
"iUnderstand": "わかりました",
"@iUnderstand": {},
"openChat": "チャットを開く",
"@openChat": {},
"experimentalVideoCalls": "実験的なビデオ通話",
"@experimentalVideoCalls": {},
"emailOrUsername": "メールアドレスまたはユーザー名",
"@emailOrUsername": {},
"switchToAccount": "アカウント {number} に切り替える",
"@switchToAccount": {
"type": "number",
"placeholders": {
"number": {}
}
},
"nextAccount": "次のアカウント",
"@nextAccount": {},
"youAcceptedTheInvitation": "👍 招待を承諾しました",
"@youAcceptedTheInvitation": {},
"errorAddingWidget": "ウィジェットの追加中にエラーが発生しました。",
"@errorAddingWidget": {},
"widgetNameError": "表示名を入力してください。",
"@widgetNameError": {},
"stories": "ストーリー",
"@stories": {},
"youUnbannedUser": "{user} の禁止を解除しました",
"@youUnbannedUser": {
"placeholders": {
"user": {}
}
},
"youInvitedBy": "📩 {user} から招待されました",
"@youInvitedBy": {
"placeholders": {
"user": {}
}
},
"youKicked": "👞 {user} をキックしました",
"@youKicked": {
"placeholders": {
"user": {}
}
},
"youKickedAndBanned": "🙅 {user} をキックしてブロックしました",
"@youKickedAndBanned": {
"placeholders": {
"user": {}
}
},
"storeInAppleKeyChain": "Apple KeyChainに保存",
"@storeInAppleKeyChain": {},
"storeInAndroidKeystore": "Android KeyStoreに保存する",
"@storeInAndroidKeystore": {},
"storeInSecureStorageDescription": "このデバイスの安全なストレージにリカバリーキーを保存。",
"@storeInSecureStorageDescription": {},
"unlockOldMessages": "古いメッセージのロックを解除する",
"@unlockOldMessages": {},
"callingAccount": "通話アカウント",
"@callingAccount": {},
"callingPermissions": "通話の権限",
"@callingPermissions": {},
"screenSharingTitle": "画面共有",
"@screenSharingTitle": {},
"foregroundServiceRunning": "この通知は、フォアグラウンド サービスの実行中に表示されます。",
"@foregroundServiceRunning": {},
"custom": "カスタム",
"@custom": {},
"countFiles": "{count}個のファイル",
"@countFiles": {
"placeholders": {
"count": {}
}
},
"storeSecurlyOnThisDevice": "このデバイスに安全に保管する",
"@storeSecurlyOnThisDevice": {},
"whyIsThisMessageEncrypted": "このメッセージが読めない理由",
"@whyIsThisMessageEncrypted": {},
"otherCallingPermissions": "マイク、カメラ、その他FluffyChatの権限",
"@otherCallingPermissions": {},
"appearOnTopDetails": "アプリをトップに表示できるようにするすでに通話アカウントとしてFluffychatを設定している場合は必要ありません",
"@appearOnTopDetails": {},
"loginWithOneClick": "ワンクリックでサインイン",
"@loginWithOneClick": {},
"dehydrateTorLong": "TOR ユーザーの場合、ウィンドウを閉じる前にセッションをエクスポートすることをお勧めします。",
"@dehydrateTorLong": {},
"hydrateTorLong": "前回、TOR でセッションをエクスポートしましたか?すぐにインポートしてチャットを続けましょう。",
"@hydrateTorLong": {},
"shareYourInviteLink": "招待リンクを共有する",
"@shareYourInviteLink": {},
"enableMultiAccounts": "(ベータ版) このデバイスで複数のアカウントを有効にする",
"@enableMultiAccounts": {},
"pleaseEnterRecoveryKey": "リカバリーキーを入力してください。",
"@pleaseEnterRecoveryKey": {},
"serverRequiresEmail": "このサーバーは、登録のためにメールアドレスを検証する必要があります。",
"@serverRequiresEmail": {},
"sendSticker": "ステッカーを送る",
"@sendSticker": {
"type": "text",
"placeholders": {}
},
"synchronizingPleaseWait": "同期中...お待ちください。",
"@synchronizingPleaseWait": {
"type": "text",
"placeholders": {}
},
"emojis": "絵文字",
"@emojis": {},
"storyPrivacyWarning": "あなたのストーリーでは、人々がお互いを見て連絡を取ることができることに注意してください。ストーリーは24時間表示されますが、すべてのデバイスとサーバーから削除されるという保証はありません。",
"@storyPrivacyWarning": {},
"markAsRead": "既読にする",
"@markAsRead": {},
"videoCallsBetaWarning": "ビデオ通話は、現在ベータ版であることにご注意ください。すべてのプラットフォームで期待通りに動作しない、あるいはまったく動作しない可能性があります。",
"@videoCallsBetaWarning": {},
"confirmEventUnpin": "イベントの固定を完全に解除してもよろしいですか?",
"@confirmEventUnpin": {},
"unsupportedAndroidVersion": "サポートされていないAndroidのバージョン",
"@unsupportedAndroidVersion": {},
"user": "ユーザー",
"@user": {},
"enterInviteLinkOrMatrixId": "招待リンクまたはMatrixのIDを入力してください...",
"@enterInviteLinkOrMatrixId": {},
"newGroup": "新しいグループ",
"@newGroup": {},
"noBackupWarning": "警告!チャットのバックアップを有効にしないと、暗号化されたメッセージにアクセスできなくなります。ログアウトする前に、まずチャットのバックアップを有効にすることを強くお勧めします。",
"@noBackupWarning": {},
"disableEncryptionWarning": "セキュリティ上の理由から、以前は暗号化が有効だったチャットで暗号化を無効にすることはできません。",
"@disableEncryptionWarning": {},
"youInvitedUser": "📩 {user} を招待しました",
"@youInvitedUser": {
"placeholders": {
"user": {}
}
},
"reactedWith": "{sender} が {reaction} で反応しました",
"@reactedWith": {
"type": "text",
"placeholders": {
"sender": {},
"reaction": {}
}
},
"createNewSpace": "新しいスペース",
"@createNewSpace": {
"type": "text",
"placeholders": {}
},
"widgetUrlError": "有効なURLではありません。",
"@widgetUrlError": {},
"reportUser": "ユーザーを報告",
"@reportUser": {},
"errorObtainingLocation": "位置情報の取得中にエラーが発生しました: {error}",
"@errorObtainingLocation": {
"type": "text",
"placeholders": {
"error": {}
}
},
"pinMessage": "部屋にピン留めする",
"@pinMessage": {},
"previousAccount": "前のアカウント",
"@previousAccount": {},
"editWidgets": "ウィジェットを編集",
"@editWidgets": {},
"pleaseChoose": "選択してください",
"@pleaseChoose": {
"type": "text",
"placeholders": {}
},
"oopsPushError": "おっと!残念ながら、プッシュ通知の設定中にエラーが発生しました。",
"@oopsPushError": {
"type": "text",
"placeholders": {}
},
"noOtherDevicesFound": "他のデバイスが見つかりません",
"@noOtherDevicesFound": {},
"recoveryKeyLost": "リカバリーキーを紛失した場合",
"@recoveryKeyLost": {},
"shareLocation": "位置情報の共有",
"@shareLocation": {
"type": "text",
"placeholders": {}
},
"time": "時間",
"@time": {},
"sendAsText": "テキストとして送信",
"@sendAsText": {
"type": "text"
},
"commandHint_googly": "ぎょろ目を送る",
"@commandHint_googly": {},
"commandHint_hug": "ハグを送る",
"@commandHint_hug": {},
"encryptThisChat": "このチャットを暗号化する",
"@encryptThisChat": {},
"noEmailWarning": "有効なメールアドレスを入力してください。入力しないと、パスワードをリセットすることができなくなります。不要な場合は、もう一度ボタンをタップして続けてください。",
"@noEmailWarning": {},
"commandHint_markasdm": "ダイレクトメッセージの部屋としてマークする",
"@commandHint_markasdm": {},
"commandHint_dm": "ダイレクトチャットを開始する\n暗号化を無効にするには、--no-encryptionを使用してください",
"@commandHint_dm": {
"type": "text",
"description": "Usage hint for the command /dm"
},
"commandHint_leave": "この部屋を退出",
"@commandHint_leave": {
"type": "text",
"description": "Usage hint for the command /leave"
},
"commandHint_myroomavatar": "この部屋の写真を設定する (mxc-uriで)",
"@commandHint_myroomavatar": {
"type": "text",
"description": "Usage hint for the command /myroomavatar"
},
"commandHint_myroomnick": "この部屋の表示名を設定する",
"@commandHint_myroomnick": {
"type": "text",
"description": "Usage hint for the command /myroomnick"
},
"commandHint_plain": "書式設定されていないテキストを送信する",
"@commandHint_plain": {
"type": "text",
"description": "Usage hint for the command /plain"
},
"commandHint_react": "リアクションとして返信を送信する",
"@commandHint_react": {
"type": "text",
"description": "Usage hint for the command /react"
},
"dehydrateTor": "TOR ユーザー: セッションをエクスポート",
"@dehydrateTor": {},
"hydrateTor": "TOR ユーザー: セッションのエクスポートをインポート",
"@hydrateTor": {},
"locationDisabledNotice": "位置情報サービスが無効になっています。位置情報を共有できるようにするには、位置情報サービスを有効にしてください。",
"@locationDisabledNotice": {
"type": "text",
"placeholders": {}
},
"locationPermissionDeniedNotice": "位置情報の権限が拒否されました。位置情報を共有できるように許可してください。",
"@locationPermissionDeniedNotice": {
"type": "text",
"placeholders": {}
},
"letsStart": "始めましょう",
"@letsStart": {},
"deviceKeys": "デバイスキー:",
"@deviceKeys": {},
"sorryThatsNotPossible": "申し訳ありません...それは不可能です",
"@sorryThatsNotPossible": {},
"endToEndEncryption": "エンドツーエンド暗号化",
"@endToEndEncryption": {},
"wasDirectChatDisplayName": "空のチャット (以前は {oldDisplayName})",
"@wasDirectChatDisplayName": {
"type": "text",
"placeholders": {
"oldDisplayName": {}
}
},
"doNotShowAgain": "今後表示しない",
"@doNotShowAgain": {},
"hideUnimportantStateEvents": "重要でない状態イベントを非表示にする",
"@hideUnimportantStateEvents": {},
"numChats": "{number} チャット",
"@numChats": {
"type": "number",
"placeholders": {
"number": {}
}
},
"allSpaces": "すべてのスペース",
"@allSpaces": {},
"enterRoom": "部屋に入る",
"@enterRoom": {},
"enterSpace": "スペースに入る",
"@enterSpace": {},
"newSpace": "新しいスペース",
"@newSpace": {},
"reopenChat": "チャットを再開する",
"@reopenChat": {}
} }

File diff suppressed because it is too large Load Diff

View File

@ -14,8 +14,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"yourUserId": "Tavo vartotojo ID:",
"@yourUserId": {},
"edit": "Redaguoti", "edit": "Redaguoti",
"@edit": { "@edit": {
"type": "text", "type": "text",
@ -26,11 +24,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Penktadienis",
"@friday": {
"type": "text",
"placeholders": {}
},
"about": "Apie", "about": "Apie",
"@about": { "@about": {
"type": "text", "type": "text",
@ -66,26 +59,11 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Pirmadienis",
"@monday": {
"type": "text",
"placeholders": {}
},
"skip": "Praleisti", "skip": "Praleisti",
"@skip": { "@skip": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Sekmadienis",
"@sunday": {
"type": "text",
"placeholders": {}
},
"tuesday": "Antradienis",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"share": "Bendrinti", "share": "Bendrinti",
"@share": { "@share": {
"type": "text", "type": "text",
@ -103,11 +81,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thursday": "Ketvirtadienis",
"@thursday": {
"type": "text",
"placeholders": {}
},
"sender": "Siuntėjas", "sender": "Siuntėjas",
"@sender": {}, "@sender": {},
"yes": "Taip", "yes": "Taip",
@ -270,8 +243,6 @@
}, },
"shareYourInviteLink": "Bendrinti savo pakvietimo nuorodą", "shareYourInviteLink": "Bendrinti savo pakvietimo nuorodą",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"typeInInviteLinkManually": "Įvesti pakvietimo nuorodą rankiniu būdu...",
"@typeInInviteLinkManually": {},
"none": "Nė vienas", "none": "Nė vienas",
"@none": { "@none": {
"type": "text", "type": "text",
@ -484,11 +455,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"saturday": "Šeštadienis",
"@saturday": {
"type": "text",
"placeholders": {}
},
"search": "Ieškoti", "search": "Ieškoti",
"@search": { "@search": {
"type": "text", "type": "text",
@ -875,11 +841,6 @@
"type": "text", "type": "text",
"description": "Usage hint for the command /me" "description": "Usage hint for the command /me"
}, },
"discover": "Rasti",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Rodomas vardas buvo pakeistas", "displaynameHasBeenChanged": "Rodomas vardas buvo pakeistas",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -1276,11 +1237,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Archyvuotas kambarys",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Ar svečiams leidžiama prisijungti", "areGuestsAllowedToJoin": "Ar svečiams leidžiama prisijungti",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -1303,12 +1259,12 @@
}, },
"chatHasBeenAddedToThisSpace": "Pokalbis buvo pridėtas prie šios erdvės", "chatHasBeenAddedToThisSpace": "Pokalbis buvo pridėtas prie šios erdvės",
"@chatHasBeenAddedToThisSpace": {}, "@chatHasBeenAddedToThisSpace": {},
"compareEmojiMatch": "Palyginkite ir įsitikinkite, kad šie jaustukai atitinka kito įrenginio jaustukus:", "compareEmojiMatch": "Palyginkite jaustukus",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Palyginkite ir įsitikinkite, kad šie skaičiai sutampa su kito įrenginio skaičiais:", "compareNumbersMatch": "Palyginkite skaičius",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1385,11 +1341,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Trečiadienis",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Išsiuntėme jums el. laišką", "weSentYouAnEmail": "Išsiuntėme jums el. laišką",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -1949,11 +1900,6 @@
"username": {} "username": {}
} }
}, },
"keysCached": "Raktai talpinami į atmintinę",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "👞 {username} išmetė {targetName}", "kicked": "👞 {username} išmetė {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
@ -1999,11 +1945,6 @@
"username2": {} "username2": {}
} }
}, },
"thisRoomHasBeenArchived": "Šis kambarys buvo suarchyvuotas.",
"@thisRoomHasBeenArchived": {
"type": "text",
"placeholders": {}
},
"toggleFavorite": "Perjungti parankinius", "toggleFavorite": "Perjungti parankinius",
"@toggleFavorite": { "@toggleFavorite": {
"type": "text", "type": "text",
@ -2220,11 +2161,6 @@
"user": {} "user": {}
} }
}, },
"crossSigningEnabled": "Kryžminis pasirašymas įjungtas",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"dateAndTimeOfDay": "{date}, {timeOfDay}", "dateAndTimeOfDay": "{date}, {timeOfDay}",
"@dateAndTimeOfDay": { "@dateAndTimeOfDay": {
"type": "text", "type": "text",
@ -2363,8 +2299,6 @@
"@dehydrateTorLong": {}, "@dehydrateTorLong": {},
"dehydrateWarning": "Šio veiksmo negalima atšaukti. Įsitikinkite, kad saugiai saugote atsarginę kopiją.", "dehydrateWarning": "Šio veiksmo negalima atšaukti. Įsitikinkite, kad saugiai saugote atsarginę kopiją.",
"@dehydrateWarning": {}, "@dehydrateWarning": {},
"dehydrateShare": "Tai jūsų privatus FluffyChat eksportas. Pasirūpinkite, kad jo neprarastumėte ir išsaugotumėte privatumą.",
"@dehydrateShare": {},
"hydrateTorLong": "Ar paskutinį kartą eksportavote savo sesiją naudodami TOR? Greitai ją importuokite ir tęskite pokalbį.", "hydrateTorLong": "Ar paskutinį kartą eksportavote savo sesiją naudodami TOR? Greitai ją importuokite ir tęskite pokalbį.",
"@hydrateTorLong": {}, "@hydrateTorLong": {},
"commandHint_markasgroup": "Pažymėti kaip grupę", "commandHint_markasgroup": "Pažymėti kaip grupę",
@ -2420,8 +2354,6 @@
"@indexedDbErrorLong": {}, "@indexedDbErrorLong": {},
"noEmailWarning": "Įveskite galiojantį el. pašto adresą. Priešingu atveju negalėsite iš naujo nustatyti slaptažodžio. Jei nenorite, dar kartą bakstelėkite mygtuką, kad galėtumėte tęsti.", "noEmailWarning": "Įveskite galiojantį el. pašto adresą. Priešingu atveju negalėsite iš naujo nustatyti slaptažodžio. Jei nenorite, dar kartą bakstelėkite mygtuką, kad galėtumėte tęsti.",
"@noEmailWarning": {}, "@noEmailWarning": {},
"enableAutoBackups": "Įjungti automatines atsargines kopijas",
"@enableAutoBackups": {},
"countFiles": "{count} failai", "countFiles": "{count} failai",
"@countFiles": { "@countFiles": {
"placeholders": { "placeholders": {

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

@ -1,7 +1,7 @@
{ {
"@@locale": "pl", "@@locale": "pl",
"@@last_modified": "2021-08-14 12:41:09.943634", "@@last_modified": "2021-08-14 12:41:09.943634",
"about": "O nas", "about": "O aplikacji",
"@about": { "@about": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -11,7 +11,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"acceptedTheInvitation": "{username} zaakceptował/-a zaproszenie", "acceptedTheInvitation": "👍 {username} zaakceptował/-a zaproszenie",
"@acceptedTheInvitation": { "@acceptedTheInvitation": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -23,7 +23,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"activatedEndToEndEncryption": "{username} aktywował/-a szyfrowanie end-to-end", "activatedEndToEndEncryption": "🔐 {username} aktywował/-a szyfrowanie od końca do końca",
"@activatedEndToEndEncryption": { "@activatedEndToEndEncryption": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -40,7 +40,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"admin": "Admin", "admin": "Administrator",
"@admin": { "@admin": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -67,22 +67,17 @@
"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",
"placeholders": {} "placeholders": {}
}, },
"areYouSure": "Jesteś pewny/-a?", "areYouSure": "Czy na pewno?",
"@areYouSure": { "@areYouSure": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"areYouSureYouWantToLogout": "Czy napewno chcesz się wylogować?", "areYouSureYouWantToLogout": "Czy na pewno chcesz się wylogować?",
"@areYouSureYouWantToLogout": { "@areYouSureYouWantToLogout": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -188,7 +183,7 @@
"username": {} "username": {}
} }
}, },
"changedTheDisplaynameTo": "{username} zmienił/-a wyświetlany nick na: {displayname}", "changedTheDisplaynameTo": "{username} zmienił/-a swój nick na: '{displayname}'",
"@changedTheDisplaynameTo": { "@changedTheDisplaynameTo": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -302,7 +297,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"chatBackupDescription": "Twoja kopia zapasowa Rozmów jest zabezpieczona kluczem bezpieczeństwa. Uważaj żeby go nie zgubić.", "chatBackupDescription": "Twoje stare wiadomości są zabezpieczone kluczem odzyskiwania. Uważaj żeby go nie zgubić.",
"@chatBackupDescription": { "@chatBackupDescription": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -416,12 +411,12 @@
}, },
"description": "State that {command} is not a valid /command." "description": "State that {command} is not a valid /command."
}, },
"compareEmojiMatch": "Porównaj i sprawdź czy na innym urządzeniu wyświetlają się te same emoji:", "compareEmojiMatch": "Porównaj emoji",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Porównaj i sprawdź czy na innym urządzeniu wyświetlają się te same cyfry:", "compareNumbersMatch": "Porównaj cyfry",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -485,7 +480,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"createdTheChat": "{username} stworzył/-a czat", "createdTheChat": "💬 {username} zaczął/-ęła rozmowę",
"@createdTheChat": { "@createdTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -523,7 +518,7 @@
"day": {} "day": {}
} }
}, },
"dateWithYear": "{day}-{month}-{year}", "dateWithYear": "{day}.{month}.{year}",
"@dateWithYear": { "@dateWithYear": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -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",
@ -836,7 +826,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"invitedUser": "{username} zaprosił/-a {targetName}", "invitedUser": "📩 {username} zaprosił/-a {targetName}",
"@invitedUser": { "@invitedUser": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -867,7 +857,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"joinedTheChat": "{username} dołączył/-a do czatu", "joinedTheChat": "👋 {username} dołączył/-a do czatu",
"@joinedTheChat": { "@joinedTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -879,12 +869,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Klucze są załadowane", "kicked": "👞 {username} wyrzucił/-a {targetName}",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} wyrzucił/-a {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -892,7 +877,7 @@
"targetName": {} "targetName": {}
} }
}, },
"kickedAndBanned": "{username} wyrzucił/-a i zbanował/-a {targetName}", "kickedAndBanned": "🙅 {username} wyrzucił/-a i zbanował/-a {targetName}",
"@kickedAndBanned": { "@kickedAndBanned": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -954,7 +939,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"login": "Zaloguj", "login": "Zaloguj się",
"@login": { "@login": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -966,7 +951,7 @@
"homeserver": {} "homeserver": {}
} }
}, },
"logout": "Wyloguj", "logout": "Wyloguj się",
"@logout": { "@logout": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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",
@ -1016,7 +996,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"newMessageInFluffyChat": "Nowa wiadomość w FluffyChat", "newMessageInFluffyChat": "💬 Nowa wiadomość w FluffyChat",
"@newMessageInFluffyChat": { "@newMessageInFluffyChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1128,12 +1108,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"pleaseEnterAMatrixIdentifier": "Wprowadź proszę identyfikator matrix.", "pleaseEnterAMatrixIdentifier": "Wprowadź identyfikator Matrix.",
"@pleaseEnterAMatrixIdentifier": { "@pleaseEnterAMatrixIdentifier": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"pleaseEnterYourPassword": "Wpisz swoje hasło", "pleaseEnterYourPassword": "Wprowadź swoje hasło",
"@pleaseEnterYourPassword": { "@pleaseEnterYourPassword": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1209,7 +1189,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"unbanFromChat": "Usuń blokadę", "unbanFromChat": "Odbanuj z czatu",
"@unbanFromChat": { "@unbanFromChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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",
@ -1277,35 +1252,35 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sentAFile": "{username} wysłał/-a plik", "sentAFile": "📁 {username} wysłał/-a plik",
"@sentAFile": { "@sentAFile": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAnAudio": "{username} wysłał/-a plik audio", "sentAnAudio": "🎤 {username} wysłał/-a plik audio",
"@sentAnAudio": { "@sentAnAudio": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAPicture": "{username} wysłał/-a obraz", "sentAPicture": "🖼️ {username} wysłał/-a zdjęcie",
"@sentAPicture": { "@sentAPicture": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentASticker": "{username} wysłał/-a naklejkę", "sentASticker": "😊 {username} wysłał/-a naklejkę",
"@sentASticker": { "@sentASticker": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAVideo": "{username} wysłał/-a wideo", "sentAVideo": "🎥 {username} wysłał/-a film",
"@sentAVideo": { "@sentAVideo": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1342,7 +1317,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sharedTheLocation": "{username} udostępnił/-a lokalizacje", "sharedTheLocation": "{username} udostępnił/-a swoją lokalizacje",
"@sharedTheLocation": { "@sharedTheLocation": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -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",
@ -1450,7 +1405,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"unreadChats": "{unreadCount, plural, other{{unreadCount} nieprzeczytanych czatów}}", "unreadChats": "{unreadCount, plural, =1{1 unread chat} other{{unreadCount} unread chats}}",
"@unreadChats": { "@unreadChats": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1480,14 +1435,14 @@
"username": {} "username": {}
} }
}, },
"userLeftTheChat": "{username} opuścił/-a czat", "userLeftTheChat": "🚪 {username} opuścił/-a czat",
"@userLeftTheChat": { "@userLeftTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"username": "Nick", "username": "Nazwa użytkownika",
"@username": { "@username": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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",
@ -1580,7 +1530,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"youHaveBeenBannedFromThisChat": "Zostałeś zbanowany na tym czacie", "youHaveBeenBannedFromThisChat": "Zostałeś/-aś zbanowany/-a z tego czatu",
"@youHaveBeenBannedFromThisChat": { "@youHaveBeenBannedFromThisChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1748,7 +1698,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"whatIsGoingOn": "Co u Ciebie słychać?", "whatIsGoingOn": "Co u ciebie słychać?",
"@whatIsGoingOn": {}, "@whatIsGoingOn": {},
"pleaseEnterValidEmail": "Proszę podaj poprawny adres email.", "pleaseEnterValidEmail": "Proszę podaj poprawny adres email.",
"@pleaseEnterValidEmail": {}, "@pleaseEnterValidEmail": {},
@ -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",
@ -1874,7 +1817,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"pleaseEnterYourPin": "Proszę podaj pin", "pleaseEnterYourPin": "Podaj swój PIN",
"@pleaseEnterYourPin": { "@pleaseEnterYourPin": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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",
@ -2030,5 +1971,517 @@
"@tooManyRequestsWarning": { "@tooManyRequestsWarning": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
} },
"commandHint_discardsession": "Odrzuć sesję",
"@commandHint_discardsession": {
"type": "text",
"description": "Usage hint for the command /discardsession"
},
"warning": "Uwaga!",
"@warning": {
"type": "text",
"placeholders": {}
},
"messageInfo": "Informacje o wiadomości",
"@messageInfo": {},
"time": "Czas",
"@time": {},
"messageType": "Rodzaj wiadomości",
"@messageType": {},
"whoCanSeeMyStoriesDesc": "Pamiętaj, że w Twojej relacji ludzie mogą się widzieć i kontaktować ze sobą.",
"@whoCanSeeMyStoriesDesc": {},
"shareYourInviteLink": "Udostępnij swój link zaproszenia",
"@shareYourInviteLink": {},
"separateChatTypes": "Oddzielenie czatów bezpośrednich i grup",
"@separateChatTypes": {
"type": "text",
"placeholders": {}
},
"waitingPartnerAcceptRequest": "Oczekiwanie na zaakceptowanie prośby przez drugą osobę…",
"@waitingPartnerAcceptRequest": {
"type": "text",
"placeholders": {}
},
"waitingPartnerEmoji": "Oczekiwanie na zaakceptowanie emoji przez drugą osobę…",
"@waitingPartnerEmoji": {
"type": "text",
"placeholders": {}
},
"pleaseChooseAPasscode": "Wybierz kod dostępu",
"@pleaseChooseAPasscode": {
"type": "text",
"placeholders": {}
},
"showDirectChatsInSpaces": "Pokaż powiązane czaty bezpośrednie w przestrzeniach",
"@showDirectChatsInSpaces": {
"type": "text",
"placeholders": {}
},
"unblockDevice": "Odblokuj urządzenie",
"@unblockDevice": {
"type": "text",
"placeholders": {}
},
"whyDoYouWantToReportThis": "Dlaczego chcesz to zgłosić?",
"@whyDoYouWantToReportThis": {
"type": "text",
"placeholders": {}
},
"removeFromSpace": "Usuń z przestrzeni",
"@removeFromSpace": {},
"replyHasBeenSent": "Wysłano odpowiedź",
"@replyHasBeenSent": {},
"iUnderstand": "Rozumiem",
"@iUnderstand": {},
"extremeOffensive": "Bardzo obraźliwe",
"@extremeOffensive": {
"type": "text",
"placeholders": {}
},
"errorObtainingLocation": "Błąd w ustalaniu lokalizacji: {error}",
"@errorObtainingLocation": {
"type": "text",
"placeholders": {
"error": {}
}
},
"howOffensiveIsThisContent": "Jak bardzo obraźliwe są te treści?",
"@howOffensiveIsThisContent": {
"type": "text",
"placeholders": {}
},
"inoffensive": "Nieobraźliwe",
"@inoffensive": {
"type": "text",
"placeholders": {}
},
"recoveryKey": "Klucz odzyskiwania",
"@recoveryKey": {},
"recoveryKeyLost": "Utracono klucz odzyskiwania?",
"@recoveryKeyLost": {},
"sentCallInformations": "{senderName} wysłał/-a informacje o połączeniu",
"@sentCallInformations": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"singlesignon": "Pojedyncze logowanie",
"@singlesignon": {
"type": "text",
"placeholders": {}
},
"startFirstChat": "Rozpocznij swój pierwszy czat",
"@startFirstChat": {},
"verifyStart": "Rozpocznij weryfikację",
"@verifyStart": {
"type": "text",
"placeholders": {}
},
"verifySuccess": "Pomyślnie zweryfikowano!",
"@verifySuccess": {
"type": "text",
"placeholders": {}
},
"verifyTitle": "Weryfikowanie innego konta",
"@verifyTitle": {
"type": "text",
"placeholders": {}
},
"waitingPartnerNumbers": "Oczekiwanie na zaakceptowanie numerów przez drugą osobę…",
"@waitingPartnerNumbers": {
"type": "text",
"placeholders": {}
},
"sender": "Nadawca",
"@sender": {},
"openGallery": "Otwórz galerię",
"@openGallery": {},
"start": "Start",
"@start": {},
"pleaseEnterRecoveryKeyDescription": "Aby odblokować wcześniejsze wiadomości, wprowadź swój klucz odzyskiwania, który został wygenerowany w poprzedniej sesji. Twój klucz odzyskiwania NIE jest Twoim hasłem.",
"@pleaseEnterRecoveryKeyDescription": {},
"videoWithSize": "Film ({size})",
"@videoWithSize": {
"type": "text",
"placeholders": {
"size": {}
}
},
"thisUserHasNotPostedAnythingYet": "Ten użytkownik jeszcze nic nie zamieścił na swojej relacji",
"@thisUserHasNotPostedAnythingYet": {},
"storyFrom": "Relacja z {date}: \n{body}",
"@storyFrom": {
"type": "text",
"placeholders": {
"date": {},
"body": {}
}
},
"addDescription": "Dodaj opis",
"@addDescription": {},
"unsubscribeStories": "Odsubskrybuj relacje",
"@unsubscribeStories": {},
"updateNow": "Rozpocznij aktualizację w tle",
"@updateNow": {},
"hydrateTorLong": "Czy ostatnio eksportowałeś/-aś swoją sesję na TOR? Szybko ją zaimportuj i kontynuuj rozmowy.",
"@hydrateTorLong": {},
"dehydrateTorLong": "W przypadku użytkowników sieci TOR zaleca się eksportowanie sesji przed zamknięciem okna.",
"@dehydrateTorLong": {},
"hydrate": "Przywracanie z pliku kopii zapasowej",
"@hydrate": {},
"noMatrixServer": "{server1} nie jest serwerem matriksa, czy chcesz zamiast niego użyć {server2}?",
"@noMatrixServer": {
"type": "text",
"placeholders": {
"server1": {},
"server2": {}
}
},
"hydrateTor": "Użytkownicy TOR-a: Importuj eksport sesji",
"@hydrateTor": {},
"numUsersTyping": "{count} użytkowników pisze…",
"@numUsersTyping": {
"type": "text",
"placeholders": {
"count": {}
}
},
"onlineKeyBackupEnabled": "Kopia zapasowa kluczy online jest włączona",
"@onlineKeyBackupEnabled": {
"type": "text",
"placeholders": {}
},
"pleaseEnterRecoveryKey": "Wprowadź swój klucz odzyskiwania:",
"@pleaseEnterRecoveryKey": {},
"submit": "Odeślij",
"@submit": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Wysłaliśmy Ci maila",
"@weSentYouAnEmail": {
"type": "text",
"placeholders": {}
},
"unverified": "Niezweryfikowane",
"@unverified": {},
"wipeChatBackup": "Wymazać kopię zapasową czatu, aby utworzyć nowy klucz odzyskiwania?",
"@wipeChatBackup": {
"type": "text",
"placeholders": {}
},
"whoCanPerformWhichAction": "Kto może wykonywać jakie czynności",
"@whoCanPerformWhichAction": {
"type": "text",
"placeholders": {}
},
"reportUser": "Zgłoś użytkownika",
"@reportUser": {},
"dismiss": "Odrzuć",
"@dismiss": {},
"storyPrivacyWarning": "Pamiętaj, że w Twojej relacji ludzie mogą się widzieć i kontaktować ze sobą. Twoje relacje będą widoczne przez 24 godziny, ale nie ma gwarancji, że zostaną usunięte ze wszystkich urządzeń i serwerów.",
"@storyPrivacyWarning": {},
"markAsRead": "Oznacz jako przeczytane",
"@markAsRead": {},
"passphraseOrKey": "fraza dostępu lub klucz odzyskiwania",
"@passphraseOrKey": {
"type": "text",
"placeholders": {}
},
"openChat": "Otwórz czat",
"@openChat": {},
"addToSpaceDescription": "Wybierz przestrzeń, do której ten czat ma być dodany.",
"@addToSpaceDescription": {},
"updateAvailable": "Aktualizacja FluffyChat jest dostępna",
"@updateAvailable": {},
"supposedMxid": "To powinno być {mxid}",
"@supposedMxid": {
"type": "text",
"placeholders": {
"mxid": {}
}
},
"commandHint_markasdm": "Oznacz jako pokój wiadomości bezpośrednich",
"@commandHint_markasdm": {},
"confirmMatrixId": "Potwierdź swój identyfikator Matrix w celu usunięcia konta.",
"@confirmMatrixId": {},
"commandHint_markasgroup": "Oznacz jako grupę",
"@commandHint_markasgroup": {},
"noEmotesFound": "Nie znaleziono żadnych emotek. 😕",
"@noEmotesFound": {
"type": "text",
"placeholders": {}
},
"dehydrate": "Eksportuj sesję i wymaż urządzenie",
"@dehydrate": {},
"dehydrateWarning": "Tego nie można cofnąć. Upewnij się, że plik kopii zapasowej jest bezpiecznie przechowywany.",
"@dehydrateWarning": {},
"dehydrateTor": "Użytkownicy TOR-a: Eksportuj sesję",
"@dehydrateTor": {},
"matrixWidgets": "Widżety Matrix",
"@matrixWidgets": {},
"unsupportedAndroidVersion": "Nieobsługiwana wersja systemu Android",
"@unsupportedAndroidVersion": {},
"widgetCustom": "Własny",
"@widgetCustom": {},
"widgetEtherpad": "Notatka",
"@widgetEtherpad": {},
"widgetJitsi": "Jitsi Meet",
"@widgetJitsi": {},
"pinMessage": "Przypnij do pokoju",
"@pinMessage": {},
"confirmEventUnpin": "Czy na pewno chcesz trwale odpiąć wydarzenie?",
"@confirmEventUnpin": {},
"youJoinedTheChat": "Dołączono do czatu",
"@youJoinedTheChat": {},
"noEmailWarning": "Wprowadź prawidłowy adres e-mail. W przeciwnym razie resetowanie hasła nie będzie możliwe. Jeśli nie chcesz, dotknij ponownie przycisku, aby kontynuować.",
"@noEmailWarning": {},
"user": "Użytkownik",
"@user": {},
"custom": "Własne",
"@custom": {},
"newGroup": "Nowa grupa",
"@newGroup": {},
"newSpace": "Nowa przestrzeń",
"@newSpace": {},
"enterInviteLinkOrMatrixId": "Wprowadź link zaproszenia lub identyfikator Matrix...",
"@enterInviteLinkOrMatrixId": {},
"fileIsTooBigForServer": "Serwer zgłasza, że plik jest zbyt duży, aby go wysłać.",
"@fileIsTooBigForServer": {},
"youBannedUser": "Zbanowałeś/-aś {user}",
"@youBannedUser": {
"placeholders": {
"user": {}
}
},
"users": "Użytkownicy",
"@users": {},
"countFiles": "{count} plików",
"@countFiles": {
"placeholders": {
"count": {}
}
},
"noOtherDevicesFound": "Nie znaleziono innych urządzeń",
"@noOtherDevicesFound": {},
"widgetUrlError": "Niepoprawny URL.",
"@widgetUrlError": {},
"widgetNameError": "Podaj nazwę wyświetlaną.",
"@widgetNameError": {},
"encryptThisChat": "Zaszyfruj ten czat",
"@encryptThisChat": {},
"endToEndEncryption": "Szyfrowanie od końca do końca",
"@endToEndEncryption": {},
"disableEncryptionWarning": "Ze względów bezpieczeństwa nie można wyłączyć szyfrowania w czacie, w którym zostało ono wcześniej włączone.",
"@disableEncryptionWarning": {},
"deviceKeys": "Klucze urządzenia:",
"@deviceKeys": {},
"emailOrUsername": "Adres e-mail lub nazwa użytkownika",
"@emailOrUsername": {},
"indexedDbErrorLong": "Przechowywanie wiadomości niestety nie jest domyślnie włączone w trybie prywatnym.\nOdwiedź\n - about:config\n - ustaw dom.indexedDB.privateBrowsing.enabled na true\nW przeciwnym razie nie jest możliwe uruchomienie FluffyChat.",
"@indexedDbErrorLong": {},
"saveKeyManuallyDescription": "Zapisz ten klucz ręcznie, uruchamiając systemowe okno dialogowe udostępniania lub schowek.",
"@saveKeyManuallyDescription": {},
"screenSharingTitle": "udostępnianie ekranu",
"@screenSharingTitle": {},
"appearOnTopDetails": "Umożliwia wyświetlanie aplikacji nad innymi (nie jest to konieczne, jeśli FluffyChat jest już ustawiony jako konto do dzwonienia)",
"@appearOnTopDetails": {},
"noKeyForThisMessage": "Może się to zdarzyć, jeśli wiadomość została wysłana przed zalogowaniem się na to konto na tym urządzeniu.\n\nMożliwe jest również, że nadawca zablokował Twoje urządzenie lub coś poszło nie tak z połączeniem internetowym.\n\nJesteś w stanie odczytać wiadomość na innej sesji? W takim razie możesz przenieść z niej wiadomość! Wejdź w Ustawienia > Urządzenia i upewnij się, że Twoje urządzenia zweryfikowały się wzajemnie. Gdy następnym razem otworzysz pokój i obie sesje będą włączone, klucze zostaną przekazane automatycznie.\n\nNie chcesz stracić kluczy podczas wylogowania lub przełączania urządzeń? Upewnij się, że w ustawieniach masz włączoną kopię zapasową czatu.",
"@noKeyForThisMessage": {},
"sorryThatsNotPossible": "Przepraszamy... to nie jest możliwe",
"@sorryThatsNotPossible": {},
"noBackupWarning": "Uwaga! Bez włączenia kopii zapasowej czatu, stracisz dostęp do swoich zaszyfrowanych wiadomości. Zaleca się włączenie kopii zapasowej czatu przed wylogowaniem.",
"@noBackupWarning": {},
"commandHint_googly": "Wyślij kręcące się oczka",
"@commandHint_googly": {},
"callingPermissions": "Uprawnienia połączeń",
"@callingPermissions": {},
"storeInAndroidKeystore": "Przechowaj w Android KeyStore",
"@storeInAndroidKeystore": {},
"commandHint_cuddle": "Wyślij przytulenie",
"@commandHint_cuddle": {},
"googlyEyesContent": "{senderName} wysyła ci kręcące się oczka",
"@googlyEyesContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"cuddleContent": "{senderName} przytula cię",
"@cuddleContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"hugContent": "{senderName} uściska cię",
"@hugContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"commandHint_hug": "Wyślij uścisk",
"@commandHint_hug": {},
"letsStart": "Zacznijmy",
"@letsStart": {},
"reactedWith": "{sender} zareagował/-a z {reaction}",
"@reactedWith": {
"type": "text",
"placeholders": {
"sender": {},
"reaction": {}
}
},
"emojis": "Emoji",
"@emojis": {},
"placeCall": "Zadzwoń",
"@placeCall": {},
"voiceCall": "Połączenie głosowe",
"@voiceCall": {},
"unsupportedAndroidVersionLong": "Ta funkcja wymaga nowszej wersji systemu Android. Sprawdź aktualizacje lub wsparcie Lineage OS.",
"@unsupportedAndroidVersionLong": {},
"videoCallsBetaWarning": "Należy pamiętać, że połączenia wideo są obecnie w fazie beta. Mogą nie działać zgodnie z oczekiwaniami lub nie działać w ogóle na wszystkich platformach.",
"@videoCallsBetaWarning": {},
"experimentalVideoCalls": "Eksperymentalne połączenia wideo",
"@experimentalVideoCalls": {},
"indexedDbErrorTitle": "Problemy związane z trybem prywatnym",
"@indexedDbErrorTitle": {},
"switchToAccount": "Przełącz na konto {number}",
"@switchToAccount": {
"type": "number",
"placeholders": {
"number": {}
}
},
"nextAccount": "Następne konto",
"@nextAccount": {},
"previousAccount": "Poprzednie konto",
"@previousAccount": {},
"editWidgets": "Edytuj widżety",
"@editWidgets": {},
"addWidget": "Dodaj widżet",
"@addWidget": {},
"widgetVideo": "Film",
"@widgetVideo": {},
"widgetName": "Nazwa",
"@widgetName": {},
"errorAddingWidget": "Błąd podczas dodawania widżetu.",
"@errorAddingWidget": {},
"youRejectedTheInvitation": "Odrzucono zaproszenie",
"@youRejectedTheInvitation": {},
"youAcceptedTheInvitation": "👍 Zaakceptowałeś/-aś zaproszenie",
"@youAcceptedTheInvitation": {},
"youHaveWithdrawnTheInvitationFor": "Wycofano zaproszenie dla {user}",
"@youHaveWithdrawnTheInvitationFor": {
"placeholders": {
"user": {}
}
},
"youInvitedBy": "📩 Zostałeś/-aś zaproszony/-a przez {user}",
"@youInvitedBy": {
"placeholders": {
"user": {}
}
},
"youInvitedUser": "📩 Zaprosiłeś/-aś {user}",
"@youInvitedUser": {
"placeholders": {
"user": {}
}
},
"youKicked": "👞 Wyrzuciłeś/-aś {user}",
"@youKicked": {
"placeholders": {
"user": {}
}
},
"youKickedAndBanned": "🙅 Wyrzuciłeś/-aś i zbanowałeś/-aś {user}",
"@youKickedAndBanned": {
"placeholders": {
"user": {}
}
},
"youUnbannedUser": "Odbanowałeś/-aś {user}",
"@youUnbannedUser": {
"placeholders": {
"user": {}
}
},
"stories": "Relacje",
"@stories": {},
"unlockOldMessages": "Odblokuj stare wiadomości",
"@unlockOldMessages": {},
"storeInSecureStorageDescription": "Przechowaj klucz odzyskiwania w bezpiecznym magazynie tego urządzenia.",
"@storeInSecureStorageDescription": {},
"storeInAppleKeyChain": "Przechowaj w pęku kluczy Apple",
"@storeInAppleKeyChain": {},
"storeSecurlyOnThisDevice": "Przechowaj bezpiecznie na tym urządzeniu",
"@storeSecurlyOnThisDevice": {},
"foregroundServiceRunning": "To powiadomienie pojawia się, gdy usługa w tle jest uruchomiona.",
"@foregroundServiceRunning": {},
"screenSharingDetail": "Udostępniasz swój ekran w FluffyChat",
"@screenSharingDetail": {},
"callingAccount": "Konto połączeń",
"@callingAccount": {},
"callingAccountDetails": "Pozwala FluffyChat używać natywnej aplikacji do wykonywania połączeń w Androidzie.",
"@callingAccountDetails": {},
"appearOnTop": "Wyświetlaj nad innymi",
"@appearOnTop": {},
"otherCallingPermissions": "Mikrofon, kamera i inne uprawnienia FluffyChat",
"@otherCallingPermissions": {},
"whyIsThisMessageEncrypted": "Dlaczego nie można odczytać tej wiadomości?",
"@whyIsThisMessageEncrypted": {},
"enterSpace": "Wejdź do przestrzeni",
"@enterSpace": {},
"enterRoom": "Wejdź do pokoju",
"@enterRoom": {},
"allSpaces": "Wszystkie przestrzenie",
"@allSpaces": {},
"numChats": "{number} czatów",
"@numChats": {
"type": "number",
"placeholders": {
"number": {}
}
},
"hideUnimportantStateEvents": "Ukryj nieistotne wydarzenia stanu",
"@hideUnimportantStateEvents": {},
"doNotShowAgain": "Nie pokazuj ponownie",
"@doNotShowAgain": {},
"wasDirectChatDisplayName": "Pusty czat (wcześniej {oldDisplayName})",
"@wasDirectChatDisplayName": {
"type": "text",
"placeholders": {
"oldDisplayName": {}
}
},
"newSpaceDescription": "Przestrzenie pozwalają na konsolidację czatów i budowanie prywatnych lub publicznych społeczności.",
"@newSpaceDescription": {},
"reopenChat": "Otwórz ponownie czat",
"@reopenChat": {},
"fileHasBeenSavedAt": "Plik został zapisany w ścieżce {path}",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"addToBundle": "Dodaj do pakietu",
"@addToBundle": {},
"bundleName": "Nazwa pakietu",
"@bundleName": {},
"editBundlesForAccount": "Edytuj paczki dla tego konta",
"@editBundlesForAccount": {},
"jumpToLastReadMessage": "Przejdź do ostatnio przeczytanej wiadomości",
"@jumpToLastReadMessage": {},
"readUpToHere": "Czytaj do tego miejsca",
"@readUpToHere": {},
"jump": "Przejdź",
"@jump": {},
"removeFromBundle": "Usuń z tej paczki",
"@removeFromBundle": {},
"openLinkInBrowser": "Otwórz link w przeglądarce",
"@openLinkInBrowser": {}
} }

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",

View File

@ -10,7 +10,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"acceptedTheInvitation": "{username} accepterade inbjudan", "acceptedTheInvitation": "👍 {username} accepterade inbjudan",
"@acceptedTheInvitation": { "@acceptedTheInvitation": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -22,7 +22,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"activatedEndToEndEncryption": "{username} aktiverade ändpunktskryptering", "activatedEndToEndEncryption": "🔐 {username} aktiverade ändpunktskryptering",
"@activatedEndToEndEncryption": { "@activatedEndToEndEncryption": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -71,11 +71,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"archivedRoom": "Arkiverat Rum",
"@archivedRoom": {
"type": "text",
"placeholders": {}
},
"areGuestsAllowedToJoin": "Får gästanvändare gå med", "areGuestsAllowedToJoin": "Får gästanvändare gå med",
"@areGuestsAllowedToJoin": { "@areGuestsAllowedToJoin": {
"type": "text", "type": "text",
@ -308,12 +303,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareEmojiMatch": "Jämför och se till att följande emoji matchar den andra enheten:", "compareEmojiMatch": "Vänligen jämför uttryckssymbolerna",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Jämför och se till att följande nummer matchar den andra enheten:", "compareNumbersMatch": "Vänligen jämför siffrorna",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -382,7 +377,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"createdTheChat": "{username} skapade chatten", "createdTheChat": "💬 {username} skapade chatten",
"@createdTheChat": { "@createdTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -394,11 +389,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"crossSigningEnabled": "Korssignering på",
"@crossSigningEnabled": {
"type": "text",
"placeholders": {}
},
"currentlyActive": "För närvarande aktiv", "currentlyActive": "För närvarande aktiv",
"@currentlyActive": { "@currentlyActive": {
"type": "text", "type": "text",
@ -484,11 +474,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"discover": "Utforska",
"@discover": {
"type": "text",
"placeholders": {}
},
"displaynameHasBeenChanged": "Visningsnamn har ändrats", "displaynameHasBeenChanged": "Visningsnamn har ändrats",
"@displaynameHasBeenChanged": { "@displaynameHasBeenChanged": {
"type": "text", "type": "text",
@ -631,11 +616,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"friday": "Fredag",
"@friday": {
"type": "text",
"placeholders": {}
},
"fromJoining": "Från att gå med", "fromJoining": "Från att gå med",
"@fromJoining": { "@fromJoining": {
"type": "text", "type": "text",
@ -778,7 +758,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"invitedUser": "{username} bjöd in {targetName}", "invitedUser": "📩 {username} bjöd in {targetName}",
"@invitedUser": { "@invitedUser": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -809,7 +789,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"joinedTheChat": "{username} anslöt till chatten", "joinedTheChat": "👋 {username} anslöt till chatten",
"@joinedTheChat": { "@joinedTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -821,12 +801,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"keysCached": "Nycklarna är cachade", "kicked": "👞 {username} sparkade ut {targetName}",
"@keysCached": {
"type": "text",
"placeholders": {}
},
"kicked": "{username} sparkade {targetName}",
"@kicked": { "@kicked": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -834,7 +809,7 @@
"targetName": {} "targetName": {}
} }
}, },
"kickedAndBanned": "{username} sparkade och bannade {targetName}", "kickedAndBanned": "🙅 {username} sparkade och bannade {targetName}",
"@kickedAndBanned": { "@kickedAndBanned": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -943,11 +918,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"monday": "Måndag",
"@monday": {
"type": "text",
"placeholders": {}
},
"muteChat": "Tysta chatt", "muteChat": "Tysta chatt",
"@muteChat": { "@muteChat": {
"type": "text", "type": "text",
@ -963,7 +933,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"newMessageInFluffyChat": "Nya meddelanden i FluffyChat", "newMessageInFluffyChat": "💬 Nya meddelanden i FluffyChat",
"@newMessageInFluffyChat": { "@newMessageInFluffyChat": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1060,7 +1030,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"oopsSomethingWentWrong": "Oops, någonting gick fel…", "oopsSomethingWentWrong": "Hoppsan, något gick fel…",
"@oopsSomethingWentWrong": { "@oopsSomethingWentWrong": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -1278,11 +1248,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",
@ -1356,35 +1321,35 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sentAFile": "{username} skickade en fil", "sentAFile": "📁 {username} skickade en fil",
"@sentAFile": { "@sentAFile": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAnAudio": "{username} skickade ett ljudklipp", "sentAnAudio": "🎤 {username} skickade ett ljudklipp",
"@sentAnAudio": { "@sentAnAudio": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAPicture": "{username} skickade ett ljudklipp", "sentAPicture": "🖼️ {username} skickade en bild",
"@sentAPicture": { "@sentAPicture": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentASticker": "{username} skickade en sticker", "sentASticker": "😊 {username} skickade ett klistermärke",
"@sentASticker": { "@sentASticker": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
"username": {} "username": {}
} }
}, },
"sentAVideo": "{username} skickade en video", "sentAVideo": "🎥 {username} skickade en video",
"@sentAVideo": { "@sentAVideo": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1477,11 +1442,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"sunday": "Söndag",
"@sunday": {
"type": "text",
"placeholders": {}
},
"systemTheme": "System", "systemTheme": "System",
"@systemTheme": { "@systemTheme": {
"type": "text", "type": "text",
@ -1497,16 +1457,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"thisRoomHasBeenArchived": "Detta rummet har blivit arkiverat.",
"@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",
@ -1538,11 +1488,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"tuesday": "Tisdag",
"@tuesday": {
"type": "text",
"placeholders": {}
},
"unavailable": "Upptagen", "unavailable": "Upptagen",
"@unavailable": { "@unavailable": {
"type": "text", "type": "text",
@ -1618,7 +1563,7 @@
"username": {} "username": {}
} }
}, },
"userLeftTheChat": "{username} lämnade chatten", "userLeftTheChat": "🚪 {username} lämnade chatten",
"@userLeftTheChat": { "@userLeftTheChat": {
"type": "text", "type": "text",
"placeholders": { "placeholders": {
@ -1708,11 +1653,6 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wednesday": "Onsdag",
"@wednesday": {
"type": "text",
"placeholders": {}
},
"weSentYouAnEmail": "Vi skickade dig ett e-postmeddelande", "weSentYouAnEmail": "Vi skickade dig ett e-postmeddelande",
"@weSentYouAnEmail": { "@weSentYouAnEmail": {
"type": "text", "type": "text",
@ -2079,7 +2019,7 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"wipeChatBackup": "Radera din chatt-backup för att skapa en ny säkerhetsnyckel?", "wipeChatBackup": "Radera din chatt-backup för att skapa en ny återställningsnyckel?",
"@wipeChatBackup": { "@wipeChatBackup": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -2096,7 +2036,7 @@
}, },
"shareYourInviteLink": "Dela din inbjudan", "shareYourInviteLink": "Dela din inbjudan",
"@shareYourInviteLink": {}, "@shareYourInviteLink": {},
"chatBackupDescription": "Din chatt backup är skyddad av en säkerhets nyckel. Se till att du inte förlorar den.", "chatBackupDescription": "Din chatt backup är skyddad av en säkerhetsnyckel. Se till att du inte förlorar den.",
"@chatBackupDescription": { "@chatBackupDescription": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -2211,8 +2151,6 @@
"@reportUser": {}, "@reportUser": {},
"openChat": "Öppna Chatt", "openChat": "Öppna Chatt",
"@openChat": {}, "@openChat": {},
"yourUserId": "Ditt användar-ID:",
"@yourUserId": {},
"sendOnEnter": "Skicka med Enter", "sendOnEnter": "Skicka med Enter",
"@sendOnEnter": {}, "@sendOnEnter": {},
"addToStory": "Addera till berättelse", "addToStory": "Addera till berättelse",
@ -2230,8 +2168,6 @@
"@yourChatBackupHasBeenSetUp": {}, "@yourChatBackupHasBeenSetUp": {},
"loginWithOneClick": "Logga in med ett klick", "loginWithOneClick": "Logga in med ett klick",
"@loginWithOneClick": {}, "@loginWithOneClick": {},
"typeInInviteLinkManually": "Skriv in länk med inbjudan manuellt...",
"@typeInInviteLinkManually": {},
"removeFromBundle": "Ta bort från paket", "removeFromBundle": "Ta bort från paket",
"@removeFromBundle": {}, "@removeFromBundle": {},
"enableMultiAccounts": "(BETA) Aktivera multi-konton på denna enhet", "enableMultiAccounts": "(BETA) Aktivera multi-konton på denna enhet",
@ -2244,7 +2180,7 @@
"@thisUserHasNotPostedAnythingYet": {}, "@thisUserHasNotPostedAnythingYet": {},
"storyPrivacyWarning": "Notera att användare kan se och kontakta varandra i din berättelse. Din berättelse är synlig i 24 timmar, men det finns ingen garanti för att berättelser raderas från alla enheter och servrar.", "storyPrivacyWarning": "Notera att användare kan se och kontakta varandra i din berättelse. Din berättelse är synlig i 24 timmar, men det finns ingen garanti för att berättelser raderas från alla enheter och servrar.",
"@storyPrivacyWarning": {}, "@storyPrivacyWarning": {},
"emojis": "Emojis", "emojis": "Uttryckssymboler",
"@emojis": {}, "@emojis": {},
"placeCall": "Ring", "placeCall": "Ring",
"@placeCall": {}, "@placeCall": {},
@ -2303,8 +2239,251 @@
"@errorAddingWidget": {}, "@errorAddingWidget": {},
"editWidgets": "Redigera widgetar", "editWidgets": "Redigera widgetar",
"@editWidgets": {}, "@editWidgets": {},
"widgetJitsi": "Jitsi Meet", "widgetJitsi": "Jitsi-möte",
"@widgetJitsi": {}, "@widgetJitsi": {},
"widgetNameError": "Vänligen ange ett visningsnamn.", "widgetNameError": "Vänligen ange ett visningsnamn.",
"@widgetNameError": {} "@widgetNameError": {},
"storeSecurlyOnThisDevice": "Lagra säkert på denna enhet",
"@storeSecurlyOnThisDevice": {},
"youJoinedTheChat": "Du gick med i chatten",
"@youJoinedTheChat": {},
"youAcceptedTheInvitation": "👍 Du accepterade inbjudan",
"@youAcceptedTheInvitation": {},
"youKicked": "👞 Du sparkade ut {user}",
"@youKicked": {
"placeholders": {
"user": {}
}
},
"hugContent": "{senderName} kramar dig",
"@hugContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"commandHint_markasgroup": "Märk som grupp",
"@commandHint_markasgroup": {},
"recoveryKeyLost": "Borttappad återställningsnyckel?",
"@recoveryKeyLost": {},
"indexedDbErrorTitle": "Problem med privat läge",
"@indexedDbErrorTitle": {},
"youHaveWithdrawnTheInvitationFor": "Du har återkallat inbjudan till {user}",
"@youHaveWithdrawnTheInvitationFor": {
"placeholders": {
"user": {}
}
},
"youUnbannedUser": "Du återkallade förbudet för {user}",
"@youUnbannedUser": {
"placeholders": {
"user": {}
}
},
"unlockOldMessages": "Lås upp äldre meddelanden",
"@unlockOldMessages": {},
"newSpace": "Nytt utrymme",
"@newSpace": {},
"googlyEyesContent": "{senderName} skickar dig googly ögon",
"@googlyEyesContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"dehydrate": "Exportera sessionen och rensa enheten",
"@dehydrate": {},
"dehydrateWarning": "Denna åtgärd kan inte ångras. Försäkra dig om att backupen är i säkert förvar.",
"@dehydrateWarning": {},
"dehydrateTor": "TOR-användare: Exportera session",
"@dehydrateTor": {},
"hydrateTor": "TOR-användare: Importera session från tidigare export",
"@hydrateTor": {},
"hydrateTorLong": "Exporterade du sessionen när du senast använde TOR? Importera den enkelt och fortsätt chatta.",
"@hydrateTorLong": {},
"recoveryKey": "Återställningsnyckel",
"@recoveryKey": {},
"separateChatTypes": "Separata direktchattar och grupper",
"@separateChatTypes": {
"type": "text",
"placeholders": {}
},
"showDirectChatsInSpaces": "Visa relaterade direktchattar i utrymmen",
"@showDirectChatsInSpaces": {
"type": "text",
"placeholders": {}
},
"startFirstChat": "Starta din första chatt",
"@startFirstChat": {},
"pleaseEnterRecoveryKeyDescription": "Ange din återställningsnyckel från en tidigare session för att låsa upp äldre meddelanden. Din återställningsnyckel är INTE ditt lösenord.",
"@pleaseEnterRecoveryKeyDescription": {},
"encryptThisChat": "Kryptera denna chatt",
"@encryptThisChat": {},
"enterInviteLinkOrMatrixId": "Ange länk för inbjudan eller Matrix-ID...",
"@enterInviteLinkOrMatrixId": {},
"dehydrateTorLong": "TOR-användare rekommenderas att exportera sessionen innan fönstret stängs.",
"@dehydrateTorLong": {},
"noBackupWarning": "Varning! Om du inte aktiverar säkerhetskopiering av chattar så tappar du åtkomst till krypterade meddelanden. Det är rekommenderat att du aktiverar säkerhetskopiering innan du loggar ut.",
"@noBackupWarning": {},
"noOtherDevicesFound": "Inga andra enheter hittades",
"@noOtherDevicesFound": {},
"endToEndEncryption": "Totalsträckskryptering",
"@endToEndEncryption": {},
"disableEncryptionWarning": "Av säkerhetsskäl kan du inte stänga av kryptering i en chatt där det tidigare aktiverats.",
"@disableEncryptionWarning": {},
"sorryThatsNotPossible": "Det där är inte möjligt",
"@sorryThatsNotPossible": {},
"confirmMatrixId": "Bekräfta ditt Matrix-ID för att radera ditt konto.",
"@confirmMatrixId": {},
"updateAvailable": "FluffyChat-uppdatering tillgänglig",
"@updateAvailable": {},
"updateNow": "Påbörja uppdatering i bakgrunden",
"@updateNow": {},
"supposedMxid": "Detta bör vara {mxid}",
"@supposedMxid": {
"type": "text",
"placeholders": {
"mxid": {}
}
},
"pleaseEnterRecoveryKey": "Ange din återställningsnyckel:",
"@pleaseEnterRecoveryKey": {},
"commandHint_markasdm": "Märk som rum för direktmeddelanden",
"@commandHint_markasdm": {},
"noEmailWarning": "Utan en giltig e-postadress kommer du inte kunna återställa ditt lösenord. Om du inte vill ange en e-postadress, tryck på knappen igen för att fortsätta.",
"@noEmailWarning": {},
"user": "Användare",
"@user": {},
"indexedDbErrorLong": "Meddelandelagring är tyvärr inte aktiverat i privat läge som standard.\nGå till\n - about:config\n - sätt dom.indexedDB.privateBrowsing.enabled till true\nAnnars går det inte att använda FluffyChat.",
"@indexedDbErrorLong": {},
"storeInSecureStorageDescription": "Lagra återställningsnyckeln på säker plats på denna enhet.",
"@storeInSecureStorageDescription": {},
"storeInAppleKeyChain": "Lagra i Apples nyckelkedja (KeyChain)",
"@storeInAppleKeyChain": {},
"foregroundServiceRunning": "Denna notifikation visas när förgrundstjänsten körs.",
"@foregroundServiceRunning": {},
"custom": "Anpassad",
"@custom": {},
"countFiles": "{count} filer",
"@countFiles": {
"placeholders": {
"count": {}
}
},
"screenSharingTitle": "skärmdelning",
"@screenSharingTitle": {},
"noKeyForThisMessage": "Detta kan hända om meddelandet skickades innan du loggade in på ditt konto i den här enheten.\n\nDet kan också vara så att avsändaren har blockerat din enhet eller att något gick fel med internetanslutningen.\n\nKan du läsa meddelandet i en annan session? I sådana fall kan du överföra meddelandet från den sessionen! Gå till Inställningar > Enhet och säkerställ att dina enheter har verifierat varandra. När du öppnar rummet nästa gång och båda sessionerna är i förgrunden, så kommer nycklarna att överföras automatiskt.\n\nVill du inte förlora nycklarna vid utloggning eller när du byter enhet? Säkerställ att du har aktiverat säkerhetskopiering för chatten i inställningarna.",
"@noKeyForThisMessage": {},
"fileIsTooBigForServer": "Servern informerar om att filen är för stor för att skickas.",
"@fileIsTooBigForServer": {},
"deviceKeys": "Enhetsnycklar:",
"@deviceKeys": {},
"enterSpace": "Gå till utrymme",
"@enterSpace": {},
"commandHint_googly": "Skicka några googly ögon",
"@commandHint_googly": {},
"commandHint_cuddle": "Skicka en omfamning",
"@commandHint_cuddle": {},
"commandHint_hug": "Skicka en kram",
"@commandHint_hug": {},
"users": "Användare",
"@users": {},
"cuddleContent": "{senderName} omfamnar dig",
"@cuddleContent": {
"type": "text",
"placeholders": {
"senderName": {}
}
},
"hydrate": "Återställ från säkerhetskopia",
"@hydrate": {},
"screenSharingDetail": "Du delar din skärm i FluffyChat",
"@screenSharingDetail": {},
"letsStart": "Lås oss börja",
"@letsStart": {},
"youRejectedTheInvitation": "Du avvisade inbjudan",
"@youRejectedTheInvitation": {},
"youBannedUser": "Du förbjöd {user}",
"@youBannedUser": {
"placeholders": {
"user": {}
}
},
"youInvitedBy": "📩 Du har blivit inbjuden av {user}",
"@youInvitedBy": {
"placeholders": {
"user": {}
}
},
"youInvitedUser": "📩 Du bjöd in {user}",
"@youInvitedUser": {
"placeholders": {
"user": {}
}
},
"youKickedAndBanned": "🙅 Du sparkade ut och förbjöd {user}",
"@youKickedAndBanned": {
"placeholders": {
"user": {}
}
},
"stories": "Berättelser",
"@stories": {},
"saveKeyManuallyDescription": "Spara nyckeln manuellt genom att aktivera dela-funktionen eller urklippshanteraren på enheten.",
"@saveKeyManuallyDescription": {},
"storeInAndroidKeystore": "Lagra i Androids nyckellagring (KeyStore)",
"@storeInAndroidKeystore": {},
"callingPermissions": "Samtalsbehörighet",
"@callingPermissions": {},
"callingAccount": "Samtalskonto",
"@callingAccount": {},
"callingAccountDetails": "Tillåt FluffyChat att använda Androids ring-app.",
"@callingAccountDetails": {},
"appearOnTop": "Visa ovanpå",
"@appearOnTop": {},
"appearOnTopDetails": "Tillåt att appen visas ovanpå (behövs inte om du redan har FluffyChat konfigurerat som ett samtalskonto)",
"@appearOnTopDetails": {},
"otherCallingPermissions": "Mikrofon, kamera och andra behörigheter för FluffyChat",
"@otherCallingPermissions": {},
"whyIsThisMessageEncrypted": "Varför kan inte detta meddelande läsas?",
"@whyIsThisMessageEncrypted": {},
"newGroup": "Ny grupp",
"@newGroup": {},
"enterRoom": "Gå till rummet",
"@enterRoom": {},
"allSpaces": "Alla utrymmen",
"@allSpaces": {},
"numChats": "{number} chattar",
"@numChats": {
"type": "number",
"placeholders": {
"number": {}
}
},
"hideUnimportantStateEvents": "Göm oviktiga tillståndshändelser",
"@hideUnimportantStateEvents": {},
"doNotShowAgain": "Visa inte igen",
"@doNotShowAgain": {},
"wasDirectChatDisplayName": "Tom chatt (var {oldDisplayName})",
"@wasDirectChatDisplayName": {
"type": "text",
"placeholders": {
"oldDisplayName": {}
}
},
"newSpaceDescription": "Utrymmen möjliggör konsolidering av chattar och att bygga privata eller offentliga gemenskaper.",
"@newSpaceDescription": {},
"reopenChat": "Återöppna chatt",
"@reopenChat": {},
"jumpToLastReadMessage": "Hoppa till det senast lästa meddelandet",
"@jumpToLastReadMessage": {},
"readUpToHere": "Läs upp till hit",
"@readUpToHere": {},
"fileHasBeenSavedAt": "Filen har sparats i {path}",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
}
} }

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

@ -0,0 +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",
@ -452,12 +447,12 @@
}, },
"description": "State that {command} is not a valid /command." "description": "State that {command} is not a valid /command."
}, },
"compareEmojiMatch": "Karşılaştırın ve aşağıdaki emojilerin diğer aygıttaki emojilerle eşleştiğinden emin olun:", "compareEmojiMatch": "Lütfen emojileri karşılaştırın",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Karşılaştırın ve aşağıdaki numaraların diğer aygıttaki numaralarla eşleştiğinden emin olun:", "compareNumbersMatch": "Lütfen sayıları karşılaştırın",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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.",
@ -2443,7 +2375,7 @@
"@commandHint_markasdm": {}, "@commandHint_markasdm": {},
"whyIsThisMessageEncrypted": "Bu mesaj neden okunamıyor?", "whyIsThisMessageEncrypted": "Bu mesaj neden okunamıyor?",
"@whyIsThisMessageEncrypted": {}, "@whyIsThisMessageEncrypted": {},
"noKeyForThisMessage": "Bu durum, mesaj siz bu aygıtta hesabınızda oturum açmadan önce gönderildiyse meydana gelebilir. \n \nGönderenin aygıtınızı engellemiş olması veya internet bağlantısında bir sorun olması da mümkündür. \n \nMesajı başka bir oturumda okuyabiliyor musunuz? O zaman mesajı oradan aktarabilirsiniz! Ayarlar > Aygıtlar bölümüne gidin ve aygıtlarınızın birbirini doğruladığından emin olun. Odayı bir sonraki sefer açtığınızda ve her iki oturum da ön planda olduğunda, anahtarlar otomatik olarak iletilecektir. \n \nOturumu kapatırken veya aygıt değiştirirken anahtarları kaybetmek istemiyor musunuz? Ayarlarda sohbet yedeklemesini etkinleştirdiğinizden emin olun.", "noKeyForThisMessage": "Bu durum, mesaj siz bu aygıtta hesabınızda oturum açmadan önce gönderildiyse meydana gelebilir.\n\nGönderenin aygıtınızı engellemiş olması veya internet bağlantısında bir sorun olması da mümkündür.\n\nMesajı başka bir oturumda okuyabiliyor musunuz? O zaman mesajı oradan aktarabilirsiniz! Ayarlar > Aygıtlar bölümüne gidin ve aygıtlarınızın birbirini doğruladığından emin olun. Odayı bir sonraki sefer açtığınızda ve her iki oturum da ön planda olduğunda, anahtarlar otomatik olarak iletilecektir.\n\nOturumu kapatırken veya aygıt değiştirirken anahtarları kaybetmek istemiyor musunuz? Ayarlarda sohbet yedeklemesini etkinleştirdiğinizden emin olun.",
"@noKeyForThisMessage": {}, "@noKeyForThisMessage": {},
"screenSharingTitle": "ekran paylaşımı", "screenSharingTitle": "ekran paylaşımı",
"@screenSharingTitle": {}, "@screenSharingTitle": {},
@ -2532,12 +2464,51 @@
"@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...",
"@enterInviteLinkOrMatrixId": {}, "@enterInviteLinkOrMatrixId": {},
"reopenChat": "Sohbeti yeniden aç", "reopenChat": "Sohbeti yeniden aç",
"@reopenChat": {} "@reopenChat": {},
"noBackupWarning": "Uyarı! Sohbet yedeklemesini etkinleştirmezseniz, şifrelenen mesajlarınıza erişiminizi kaybedersiniz. Oturumu kapatmadan önce sohbet yedeklemesini etkinleştirmeniz önemle tavsiye edilir.",
"@noBackupWarning": {},
"noOtherDevicesFound": "Başka aygıt bulunamadı",
"@noOtherDevicesFound": {},
"fileIsTooBigForServer": "Sunucu, dosyanın gönderilemeyecek kadar büyük olduğunu bildiriyor.",
"@fileIsTooBigForServer": {},
"fileHasBeenSavedAt": "Dosya {path} konumuna kaydedildi",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"jumpToLastReadMessage": "Son okunan mesaja atla",
"@jumpToLastReadMessage": {},
"readUpToHere": "Buraya kadar oku",
"@readUpToHere": {},
"jump": "Atla",
"@jump": {},
"openLinkInBrowser": "Bağlantıyı tarayıcıda aç",
"@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",
@ -271,12 +266,12 @@
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareEmojiMatch": "Порівняйте і переконайтесь, що показані емодзі збігаються емодзі на іншому пристрої:", "compareEmojiMatch": "Порівняйте емодзі",
"@compareEmojiMatch": { "@compareEmojiMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
}, },
"compareNumbersMatch": "Порівняйте і переконайтесь, що вказані числа збігаються з числами на іншому пристрої:", "compareNumbersMatch": "Порівняйте цифри",
"@compareNumbersMatch": { "@compareNumbersMatch": {
"type": "text", "type": "text",
"placeholders": {} "placeholders": {}
@ -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,12 +2464,51 @@
"@sorryThatsNotPossible": {}, "@sorryThatsNotPossible": {},
"deviceKeys": "Ключі пристрою:", "deviceKeys": "Ключі пристрою:",
"@deviceKeys": {}, "@deviceKeys": {},
"noSearchResult": "Немає відповідних результатів пошуку.",
"@noSearchResult": {},
"letsStart": "Розпочнімо", "letsStart": "Розпочнімо",
"@letsStart": {}, "@letsStart": {},
"enterInviteLinkOrMatrixId": "Введіть запрошувальне посилання або Matrix ID...", "enterInviteLinkOrMatrixId": "Введіть запрошувальне посилання або Matrix ID...",
"@enterInviteLinkOrMatrixId": {}, "@enterInviteLinkOrMatrixId": {},
"reopenChat": "Відновити бесіду", "reopenChat": "Відновити бесіду",
"@reopenChat": {} "@reopenChat": {},
"noOtherDevicesFound": "Інших пристроїв не знайдено",
"@noOtherDevicesFound": {},
"noBackupWarning": "Увага! Якщо ви не ввімкнете резервне копіювання бесіди, ви втратите доступ до своїх зашифрованих повідомлень. Наполегливо радимо ввімкнути резервне копіювання бесіди перед виходом.",
"@noBackupWarning": {},
"fileIsTooBigForServer": "Сервер повідомляє, що файл завеликий для надсилання.",
"@fileIsTooBigForServer": {},
"fileHasBeenSavedAt": "Файл збережено в {path}",
"@fileHasBeenSavedAt": {
"type": "text",
"placeholders": {
"path": {}
}
},
"jumpToLastReadMessage": "Перейти до останнього прочитаного повідомлення",
"@jumpToLastReadMessage": {},
"readUpToHere": "Читати тут",
"@readUpToHere": {},
"jump": "Перейти",
"@jump": {},
"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",

File diff suppressed because it is too large Load Diff

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

@ -7,11 +7,9 @@ are also published on it.
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click it**. Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click it**.
{::nomarkdown} <a href="fdroidrepos://fluffychat.im/repo/stable/repo/?fingerprint=5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07" >
<a href="fdroidrepos://fluffychat.im/repo/stable/repo/?fingerprint=8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB" >
<img src="qr-stable.svg" width="300" height="300"/> <img src="qr-stable.svg" width="300" height="300"/>
</a> </a>
{:/}
### If the QR-Code doesn't work: ### If the QR-Code doesn't work:
@ -24,11 +22,11 @@ If this still isn't working follow the next steps:
2. Go to the `Settings` Tab in the Bottom bar 2. Go to the `Settings` Tab in the Bottom bar
3. Click the `Repositories` Action 3. Click the `Repositories` Action
4. Click on the plus sign at the top. 4. Click on the plus sign at the top.
5. Fill in `https://fluffychat.im/repo/stable/repo/` into the top field and `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB` in the bottom field. 5. Fill in `https://fluffychat.im/repo/stable/repo/` into the top field and `5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07` in the bottom field.
## What is the fingerprint? ## What is the fingerprint?
The fingerprint of the Repository is: `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3EF56566E748CDE8BC65C1FB` The fingerprint of the Repository is: `5EDB5C4395B2F2D9BA682F6A1D275170CCE5365A6FA27D2220EA8D52A6D95F07`
# Nightly Repository # Nightly Repository
@ -36,11 +34,9 @@ The fingerprint of the Repository is: `8E2637AEF6697CC6DD486AF044A6EE45B1A742AE3
Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click** it. Easiest way to add the Repository is to either **scan the QR-Code** or if you are on your phone **directly click** it.
{::nomarkdown}
<a href="fdroidrepos://fluffychat.im/repo/nightly/repo/?fingerprint=21A469657300576478B623DF99D8EB889A80BCD939ACA60A4074741BEAEC397D" > <a href="fdroidrepos://fluffychat.im/repo/nightly/repo/?fingerprint=21A469657300576478B623DF99D8EB889A80BCD939ACA60A4074741BEAEC397D" >
<img src="qr-nightly.svg" width="300" height="300"/> <img src="qr-nightly.svg" width="300" height="300"/>
</a> </a>
{:/}
### If the QR-Code doesn't work: ### If the QR-Code doesn't work:

View File

@ -40,7 +40,7 @@
class="w-36 pr-2 mb-2 inline hover:scale-105 transition-transform"></a> class="w-36 pr-2 mb-2 inline hover:scale-105 transition-transform"></a>
<a href="https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"><img src="google-play-badge.png" <a href="https://play.google.com/store/apps/details?id=chat.fluffy.fluffychat"><img src="google-play-badge.png"
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"> class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline">
</a><a href="https://f-droid.org/de/packages/chat.fluffy.fluffychat/"><img src="fdroid_button.png" </a><a href="https://f-droid.org/packages/chat.fluffy.fluffychat/"><img src="fdroid_button.png"
class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline"> class="w-36 pr-2 mb-2 hover:scale-105 transition-transform inline">
</a> </a>
<a href="https://fluffychat.im/web"> <a href="https://fluffychat.im/web">
@ -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;">

File diff suppressed because one or more lines are too long

Before

Width:  |  Height:  |  Size: 84 KiB

After

Width:  |  Height:  |  Size: 38 KiB

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.

Binary file not shown.

View File

@ -144,13 +144,15 @@ void main() {
await tester.waitFor( await tester.waitFor(
find.descendant( find.descendant(
of: find.byType(InvitationSelectionView), of: find.byType(InvitationSelectionView),
matching: find.byType(TextField)), matching: find.byType(TextField),
),
); );
await tester.enterText( await tester.enterText(
find.descendant( find.descendant(
of: find.byType(InvitationSelectionView), of: find.byType(InvitationSelectionView),
matching: find.byType(TextField)), matching: find.byType(TextField),
),
Users.user2.name, Users.user2.name,
); );
@ -160,14 +162,17 @@ void main() {
await Future.delayed(const Duration(milliseconds: 1000)); await Future.delayed(const Duration(milliseconds: 1000));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.tap(find await tester.tap(
.descendant( find
.descendant(
of: find.descendant( of: find.descendant(
of: find.byType(InvitationSelectionView), of: find.byType(InvitationSelectionView),
matching: find.byType(ListTile), matching: find.byType(ListTile),
), ),
matching: find.text(Users.user2.name)) matching: find.text(Users.user2.name),
.last); )
.last,
);
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.waitFor(find.maybeUppercaseText('Yes')); await tester.waitFor(find.maybeUppercaseText('Yes'));

View File

@ -2,7 +2,6 @@ import 'dart:developer';
import 'package:fluffychat/pages/chat_list/chat_list_body.dart'; import 'package:fluffychat/pages/chat_list/chat_list_body.dart';
import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart'; import 'package:fluffychat/pages/homeserver_picker/homeserver_picker.dart';
import 'package:fluffychat/pages/settings_account/settings_account_view.dart';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart'; import 'package:flutter_test/flutter_test.dart';
@ -120,17 +119,6 @@ extension DefaultFlowExtensions on WidgetTester {
), ),
); );
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.tap(find.text('Account'));
await tester.pumpAndSettle();
await tester.scrollUntilVisible(
find.text('Logout'),
500,
scrollable: find.descendant(
of: find.byType(SettingsAccountView),
matching: find.byType(Scrollable),
),
);
await tester.pumpAndSettle();
await tester.tap(find.text('Logout')); await tester.tap(find.text('Logout'));
await tester.pumpAndSettle(); await tester.pumpAndSettle();
await tester.tap(find.maybeUppercaseText('Yes')); await tester.tap(find.maybeUppercaseText('Yes'));
@ -156,7 +144,8 @@ extension DefaultFlowExtensions on WidgetTester {
do { do {
if (DateTime.now().isAfter(end)) { if (DateTime.now().isAfter(end)) {
throw Exception( throw Exception(
'Timed out waiting for HomeserverPicker or ChatListViewBody'); 'Timed out waiting for HomeserverPicker or ChatListViewBody',
);
} }
await pumpAndSettle(); await pumpAndSettle();

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

@ -1,5 +1,5 @@
app_identifier("im.fluffychat.app") # The bundle identifier of your app app_identifier("im.fluffychat.app") # The bundle identifier of your app
apple_id("christian.pauly@wtal.de") # Your Apple email address apple_id("christian-kussowski@posteo.de") # Your Apple email address
itc_team_id("122628977") # App Store Connect Team ID itc_team_id("122628977") # App Store Connect Team ID
team_id("4NXF6Z997G") # Developer Portal Team ID team_id("4NXF6Z997G") # Developer Portal Team ID

View File

@ -16,7 +16,7 @@ abstract class AppConfig {
static const double messageFontSize = 15.75; static const double messageFontSize = 15.75;
static const bool allowOtherHomeservers = true; static const bool allowOtherHomeservers = true;
static const bool enableRegistration = true; static const bool enableRegistration = true;
static const Color primaryColor = Color.fromARGB(255, 135, 103, 172); static const Color primaryColor = Color(0xFF5625BA);
static const Color primaryColorLight = Color(0xFFCCBDEA); static const Color primaryColorLight = Color(0xFFCCBDEA);
static const Color secondaryColor = Color(0xFF41a2bc); static const Color secondaryColor = Color(0xFF41a2bc);
static String _privacyUrl = static String _privacyUrl =
@ -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';
@ -70,8 +75,9 @@ abstract class AppConfig {
colorSchemeSeed = Color(json['chat_color']); colorSchemeSeed = Color(json['chat_color']);
} catch (e) { } catch (e) {
Logs().w( Logs().w(
'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"', 'Invalid color in config.json! Please make sure to define the color in this format: "0xffdd0000"',
e); e,
);
} }
} }
if (json['application_name'] is String) { if (json['application_name'] is String) {

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';
@ -19,7 +18,6 @@ import 'package:fluffychat/pages/new_private_chat/new_private_chat.dart';
import 'package:fluffychat/pages/new_space/new_space.dart'; import 'package:fluffychat/pages/new_space/new_space.dart';
import 'package:fluffychat/pages/settings/settings.dart'; import 'package:fluffychat/pages/settings/settings.dart';
import 'package:fluffychat/pages/settings_3pid/settings_3pid.dart'; import 'package:fluffychat/pages/settings_3pid/settings_3pid.dart';
import 'package:fluffychat/pages/settings_account/settings_account.dart';
import 'package:fluffychat/pages/settings_chat/settings_chat.dart'; import 'package:fluffychat/pages/settings_chat/settings_chat.dart';
import 'package:fluffychat/pages/settings_emotes/settings_emotes.dart'; import 'package:fluffychat/pages/settings_emotes/settings_emotes.dart';
import 'package:fluffychat/pages/settings_ignore_list/settings_ignore_list.dart'; import 'package:fluffychat/pages/settings_ignore_list/settings_ignore_list.dart';
@ -28,7 +26,6 @@ import 'package:fluffychat/pages/settings_notifications/settings_notifications.d
import 'package:fluffychat/pages/settings_security/settings_security.dart'; import 'package:fluffychat/pages/settings_security/settings_security.dart';
import 'package:fluffychat/pages/settings_stories/settings_stories.dart'; import 'package:fluffychat/pages/settings_stories/settings_stories.dart';
import 'package:fluffychat/pages/settings_style/settings_style.dart'; import 'package:fluffychat/pages/settings_style/settings_style.dart';
import 'package:fluffychat/pages/sign_up/signup.dart';
import 'package:fluffychat/pages/story/story_page.dart'; import 'package:fluffychat/pages/story/story_page.dart';
import 'package:fluffychat/widgets/layouts/empty_page.dart'; import 'package:fluffychat/widgets/layouts/empty_page.dart';
import 'package:fluffychat/widgets/layouts/loading_view.dart'; import 'package:fluffychat/widgets/layouts/loading_view.dart';
@ -71,21 +68,25 @@ class AppRoutes {
widget: const ChatDetails(), widget: const ChatDetails(),
stackedRoutes: _chatDetailsRoutes, stackedRoutes: _chatDetailsRoutes,
), ),
VWidget(path: ':roomid', widget: const Chat(), stackedRoutes: [ VWidget(
VWidget( path: ':roomid',
path: 'encryption', widget: const ChatPage(),
widget: const ChatEncryptionSettings(), stackedRoutes: [
), VWidget(
VWidget( path: 'encryption',
path: 'invite', widget: const ChatEncryptionSettings(),
widget: const InvitationSelection(), ),
), VWidget(
VWidget( path: 'invite',
path: 'details', widget: const InvitationSelection(),
widget: const ChatDetails(), ),
stackedRoutes: _chatDetailsRoutes, VWidget(
), path: 'details',
]), widget: const ChatDetails(),
stackedRoutes: _chatDetailsRoutes,
),
],
),
VWidget( VWidget(
path: '/settings', path: '/settings',
widget: const Settings(), widget: const Settings(),
@ -97,7 +98,7 @@ class AppRoutes {
stackedRoutes: [ stackedRoutes: [
VWidget( VWidget(
path: ':roomid', path: ':roomid',
widget: const Chat(), widget: const ChatPage(),
buildTransition: _dynamicTransition, buildTransition: _dynamicTransition,
), ),
], ],
@ -171,14 +172,14 @@ class AppRoutes {
VNester( VNester(
path: ':roomid', path: ':roomid',
widgetBuilder: (child) => SideViewLayout( widgetBuilder: (child) => SideViewLayout(
mainView: const Chat(), mainView: const ChatPage(),
sideView: child, sideView: child,
), ),
buildTransition: _fadeTransition, buildTransition: _fadeTransition,
nestedRoutes: [ nestedRoutes: [
VWidget( VWidget(
path: '', path: '',
widget: const Chat(), widget: const ChatPage(),
buildTransition: _fadeTransition, buildTransition: _fadeTransition,
), ),
VWidget( VWidget(
@ -242,7 +243,7 @@ class AppRoutes {
), ),
VWidget( VWidget(
path: ':roomid', path: ':roomid',
widget: const Chat(), widget: const ChatPage(),
buildTransition: _dynamicTransition, buildTransition: _dynamicTransition,
), ),
], ],
@ -263,22 +264,6 @@ class AppRoutes {
widget: const Login(), widget: const Login(),
buildTransition: _fadeTransition, buildTransition: _fadeTransition,
), ),
VWidget(
path: 'connect',
widget: const ConnectPage(),
buildTransition: _fadeTransition,
stackedRoutes: [
VWidget(
path: 'login',
widget: const Login(),
buildTransition: _fadeTransition,
),
VWidget(
path: 'signup',
widget: const SignupPage(),
buildTransition: _fadeTransition,
),
]),
VWidget( VWidget(
path: 'logs', path: 'logs',
widget: const LogViewer(), widget: const LogViewer(),
@ -345,37 +330,14 @@ class AppRoutes {
], ],
), ),
VWidget( VWidget(
path: 'account', path: 'addaccount',
widget: const SettingsAccount(), widget: const HomeserverPicker(),
buildTransition: _dynamicTransition, buildTransition: _fadeTransition,
stackedRoutes: [ stackedRoutes: [
VWidget( VWidget(
path: 'add', path: 'login',
widget: const HomeserverPicker(), widget: const Login(),
buildTransition: _fadeTransition, buildTransition: _fadeTransition,
stackedRoutes: [
VWidget(
path: 'login',
widget: const Login(),
buildTransition: _fadeTransition,
),
VWidget(
path: 'connect',
widget: const ConnectPage(),
buildTransition: _fadeTransition,
stackedRoutes: [
VWidget(
path: 'login',
widget: const Login(),
buildTransition: _fadeTransition,
),
VWidget(
path: 'signup',
widget: const SignupPage(),
buildTransition: _fadeTransition,
),
]),
],
), ),
], ],
), ),

View File

@ -9,7 +9,10 @@ import 'app_config.dart';
abstract class FluffyThemes { abstract class FluffyThemes {
static const double columnWidth = 360.0; static const double columnWidth = 360.0;
static bool isColumnModeByWidth(double width) => width > columnWidth * 2 + 64; static const double navRailWidth = 64.0;
static bool isColumnModeByWidth(double width) =>
width > columnWidth * 2 + navRailWidth;
static bool isColumnMode(BuildContext context) => static bool isColumnMode(BuildContext context) =>
isColumnModeByWidth(MediaQuery.of(context).size.width); isColumnModeByWidth(MediaQuery.of(context).size.width);
@ -38,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;
@ -47,7 +66,7 @@ abstract class FluffyThemes {
useMaterial3: true, useMaterial3: true,
brightness: brightness, brightness: brightness,
colorSchemeSeed: seed ?? AppConfig.colorSchemeSeed, colorSchemeSeed: seed ?? AppConfig.colorSchemeSeed,
textTheme: PlatformInfos.isDesktop textTheme: PlatformInfos.isDesktop || PlatformInfos.isWeb
? brightness == Brightness.light ? brightness == Brightness.light
? Typography.material2018().black.merge(fallbackTextTheme) ? Typography.material2018().black.merge(fallbackTextTheme)
: Typography.material2018().white.merge(fallbackTextTheme) : Typography.material2018().white.merge(fallbackTextTheme)
@ -94,10 +113,18 @@ abstract class FluffyThemes {
), ),
), ),
), ),
dialogTheme: DialogTheme(
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2),
),
),
elevatedButtonTheme: ElevatedButtonThemeData( elevatedButtonTheme: ElevatedButtonThemeData(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
padding: const EdgeInsets.all(16), padding: const EdgeInsets.all(16),
textStyle: const TextStyle(fontSize: 16), textStyle: const TextStyle(fontSize: 16),
shape: RoundedRectangleBorder(
borderRadius: BorderRadius.circular(AppConfig.borderRadius),
),
), ),
), ),
); );

View File

@ -3,7 +3,8 @@ import 'dart:math';
import 'package:flutter/material.dart'; import 'package:flutter/material.dart';
import 'package:file_picker_cross/file_picker_cross.dart'; import 'package:collection/collection.dart';
import 'package:file_picker/file_picker.dart';
import 'package:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
import 'package:matrix/matrix.dart'; import 'package:matrix/matrix.dart';
@ -68,14 +69,15 @@ class AddStoryController extends State<AddStoryPage> {
} }
void importMedia() async { void importMedia() async {
final picked = await FilePickerCross.importFromStorage( final picked = await FilePicker.platform.pickFiles(
type: FileTypeCross.image, type: FileType.image,
withData: true,
); );
final fileName = picked.fileName; final file = picked?.files.firstOrNull;
if (fileName == null) return; if (file == null) return;
final matrixFile = MatrixImageFile( final matrixFile = MatrixImageFile(
bytes: picked.toUint8List(), bytes: file.bytes!,
name: fileName, name: file.name,
); );
setState(() { setState(() {
image = matrixFile; image = matrixFile;
@ -88,14 +90,15 @@ class AddStoryController extends State<AddStoryPage> {
); );
if (picked == null) return; if (picked == null) return;
final matrixFile = await showFutureLoadingDialog( final matrixFile = await showFutureLoadingDialog(
context: context, context: context,
future: () async { future: () async {
final bytes = await picked.readAsBytes(); final bytes = await picked.readAsBytes();
return MatrixImageFile( return MatrixImageFile(
bytes: bytes, bytes: bytes,
name: picked.name, name: picked.name,
); );
}); },
);
setState(() { setState(() {
image = matrixFile.result; image = matrixFile.result;

View File

@ -92,34 +92,39 @@ class InviteStoryPageState extends State<InviteStoryPage> {
const Divider(height: 1), const Divider(height: 1),
Expanded( Expanded(
child: FutureBuilder<List<User>>( child: FutureBuilder<List<User>>(
future: loadContacts, future: loadContacts,
builder: (context, snapshot) { builder: (context, snapshot) {
final contacts = snapshot.data; final contacts = snapshot.data;
if (contacts == null) { if (contacts == null) {
final error = snapshot.error; final error = snapshot.error;
if (error != null) { if (error != null) {
return Center( return Center(
child: Text(error.toLocalizedString(context))); child: Text(error.toLocalizedString(context)),
} );
return const Center(
child: CircularProgressIndicator.adaptive());
} }
_undecided = contacts.map((u) => u.id).toSet(); return const Center(
return ListView.builder( child: CircularProgressIndicator.adaptive(),
itemCount: contacts.length,
itemBuilder: (context, i) => SwitchListTile.adaptive(
value: _invite.contains(contacts[i].id),
onChanged: (b) => setState(() => b
? _invite.add(contacts[i].id)
: _invite.remove(contacts[i].id)),
secondary: Avatar(
mxContent: contacts[i].avatarUrl,
name: contacts[i].calcDisplayname(),
),
title: Text(contacts[i].calcDisplayname()),
),
); );
}), }
_undecided = contacts.map((u) => u.id).toSet();
return ListView.builder(
itemCount: contacts.length,
itemBuilder: (context, i) => SwitchListTile.adaptive(
value: _invite.contains(contacts[i].id),
onChanged: (b) => setState(
() => b
? _invite.add(contacts[i].id)
: _invite.remove(contacts[i].id),
),
secondary: Avatar(
mxContent: contacts[i].avatarUrl,
name: contacts[i].calcDisplayname(),
),
title: Text(contacts[i].calcDisplayname()),
),
);
},
),
), ),
], ],
), ),

View File

@ -36,19 +36,22 @@ class ArchiveView extends StatelessWidget {
builder: (BuildContext context) { builder: (BuildContext context) {
if (snapshot.hasError) { if (snapshot.hasError) {
return Center( return Center(
child: Text( child: Text(
L10n.of(context)!.oopsSomethingWentWrong, L10n.of(context)!.oopsSomethingWentWrong,
textAlign: TextAlign.center, textAlign: TextAlign.center,
)); ),
);
} }
if (!snapshot.hasData) { if (!snapshot.hasData) {
return const Center( return const Center(
child: CircularProgressIndicator.adaptive(strokeWidth: 2)); child: CircularProgressIndicator.adaptive(strokeWidth: 2),
);
} else { } else {
archive = snapshot.data; archive = snapshot.data;
if (archive == null || archive!.isEmpty) { if (archive == null || archive!.isEmpty) {
return const Center( return const Center(
child: Icon(Icons.archive_outlined, size: 80)); child: Icon(Icons.archive_outlined, size: 80),
);
} }
return ListView.builder( return ListView.builder(
itemCount: archive!.length, itemCount: archive!.length,

View File

@ -125,9 +125,12 @@ class BootstrapDialogState extends State<BootstrapDialog> {
children: [ children: [
ListTile( ListTile(
contentPadding: const EdgeInsets.symmetric(horizontal: 8.0), contentPadding: const EdgeInsets.symmetric(horizontal: 8.0),
trailing: Icon( trailing: CircleAvatar(
Icons.info_outlined, backgroundColor: Colors.transparent,
color: Theme.of(context).colorScheme.primary, child: Icon(
Icons.info_outlined,
color: Theme.of(context).colorScheme.primary,
),
), ),
subtitle: Text(L10n.of(context)!.chatBackupDescription), subtitle: Text(L10n.of(context)!.chatBackupDescription),
), ),
@ -136,11 +139,15 @@ class BootstrapDialogState extends State<BootstrapDialog> {
thickness: 1, thickness: 1,
), ),
TextField( TextField(
minLines: 4, minLines: 2,
maxLines: 4, maxLines: 4,
readOnly: true, readOnly: true,
style: const TextStyle(fontFamily: 'monospace'), style: const TextStyle(fontFamily: 'RobotoMono'),
controller: TextEditingController(text: key), controller: TextEditingController(text: key),
decoration: const InputDecoration(
contentPadding: EdgeInsets.all(16),
suffixIcon: Icon(Icons.key_outlined),
),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
if (_supportsSecureStorage) if (_supportsSecureStorage)
@ -234,12 +241,13 @@ class BootstrapDialogState extends State<BootstrapDialog> {
icon: const Icon(Icons.close), icon: const Icon(Icons.close),
onPressed: Navigator.of(context).pop, onPressed: Navigator.of(context).pop,
), ),
title: Text(L10n.of(context)!.unlockOldMessages), title: Text(L10n.of(context)!.chatBackup),
), ),
body: Center( body: Center(
child: ConstrainedBox( child: ConstrainedBox(
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: FluffyThemes.columnWidth * 1.5), maxWidth: FluffyThemes.columnWidth * 1.5,
),
child: ListView( child: ListView(
padding: const EdgeInsets.all(16.0), padding: const EdgeInsets.all(16.0),
children: [ children: [
@ -251,11 +259,12 @@ class BootstrapDialogState extends State<BootstrapDialog> {
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
), ),
subtitle: Text( subtitle: Text(
L10n.of(context)!.pleaseEnterRecoveryKeyDescription), L10n.of(context)!.pleaseEnterRecoveryKeyDescription,
),
), ),
const Divider(height: 32), const Divider(height: 32),
TextField( TextField(
minLines: 2, minLines: 1,
maxLines: 2, maxLines: 2,
autocorrect: false, autocorrect: false,
readOnly: _recoveryKeyInputLoading, readOnly: _recoveryKeyInputLoading,
@ -263,68 +272,72 @@ class BootstrapDialogState extends State<BootstrapDialog> {
? null ? null
: [AutofillHints.password], : [AutofillHints.password],
controller: _recoveryKeyTextEditingController, controller: _recoveryKeyTextEditingController,
style: const TextStyle(fontFamily: 'monospace'), style: const TextStyle(fontFamily: 'RobotoMono'),
decoration: InputDecoration( decoration: InputDecoration(
hintText: 'Abc123 Def456', contentPadding: const EdgeInsets.all(16),
labelStyle: TextStyle( hintStyle: TextStyle(
fontFamily: Theme.of(context) fontFamily:
.textTheme Theme.of(context).textTheme.bodyLarge?.fontFamily,
.bodyLarge ),
?.fontFamily), hintText: L10n.of(context)!.recoveryKey,
labelText: L10n.of(context)!.recoveryKey,
errorText: _recoveryKeyInputError, errorText: _recoveryKeyInputError,
), ),
), ),
const SizedBox(height: 16), const SizedBox(height: 16),
ElevatedButton.icon( ElevatedButton.icon(
style: ElevatedButton.styleFrom( style: ElevatedButton.styleFrom(
foregroundColor: foregroundColor:
Theme.of(context).colorScheme.onPrimary, Theme.of(context).colorScheme.onPrimary,
backgroundColor: Theme.of(context).primaryColor, backgroundColor: Theme.of(context).primaryColor,
),
icon: _recoveryKeyInputLoading
? const CircularProgressIndicator.adaptive()
: const Icon(Icons.lock_open_outlined),
label: Text(L10n.of(context)!.unlockOldMessages),
onPressed: _recoveryKeyInputLoading
? null
: () async {
setState(() {
_recoveryKeyInputError = null;
_recoveryKeyInputLoading = true;
});
try {
final key =
_recoveryKeyTextEditingController.text;
await bootstrap.newSsssKey!.unlock(
keyOrPassphrase: key,
);
Logs().d('SSSS unlocked');
await bootstrap
.client.encryption!.crossSigning
.selfSign(
keyOrPassphrase: key,
);
Logs().d('Successful elfsigned');
await bootstrap.openExistingSsss();
} catch (e, s) {
Logs().w('Unable to unlock SSSS', e, s);
setState(() => _recoveryKeyInputError =
L10n.of(context)!.oopsSomethingWentWrong);
} finally {
setState(
() => _recoveryKeyInputLoading = false);
}
}),
const SizedBox(height: 16),
Row(children: [
const Expanded(child: Divider()),
Padding(
padding: const EdgeInsets.all(12.0),
child: Text(L10n.of(context)!.or),
), ),
const Expanded(child: Divider()), icon: _recoveryKeyInputLoading
]), ? const CircularProgressIndicator.adaptive()
: const Icon(Icons.lock_open_outlined),
label: Text(L10n.of(context)!.unlockOldMessages),
onPressed: _recoveryKeyInputLoading
? null
: () async {
setState(() {
_recoveryKeyInputError = null;
_recoveryKeyInputLoading = true;
});
try {
final key =
_recoveryKeyTextEditingController.text;
await bootstrap.newSsssKey!.unlock(
keyOrPassphrase: key,
);
Logs().d('SSSS unlocked');
await bootstrap.client.encryption!.crossSigning
.selfSign(
keyOrPassphrase: key,
);
Logs().d('Successful elfsigned');
await bootstrap.openExistingSsss();
} catch (e, s) {
Logs().w('Unable to unlock SSSS', e, s);
setState(
() => _recoveryKeyInputError =
L10n.of(context)!.oopsSomethingWentWrong,
);
} finally {
setState(
() => _recoveryKeyInputLoading = false,
);
}
},
),
const SizedBox(height: 16),
Row(
children: [
const Expanded(child: Divider()),
Padding(
padding: const EdgeInsets.all(12.0),
child: Text(L10n.of(context)!.or),
),
const Expanded(child: Divider()),
],
),
const SizedBox(height: 16), const SizedBox(height: 16),
ElevatedButton.icon( ElevatedButton.icon(
icon: const Icon(Icons.cast_connected_outlined), icon: const Icon(Icons.cast_connected_outlined),
@ -401,11 +414,13 @@ class BootstrapDialogState extends State<BootstrapDialog> {
case BootstrapState.error: case BootstrapState.error:
titleText = L10n.of(context)!.oopsSomethingWentWrong; titleText = L10n.of(context)!.oopsSomethingWentWrong;
body = const Icon(Icons.error_outline, color: Colors.red, size: 40); body = const Icon(Icons.error_outline, color: Colors.red, size: 40);
buttons.add(AdaptiveFlatButton( buttons.add(
label: L10n.of(context)!.close, AdaptiveFlatButton(
onPressed: () => label: L10n.of(context)!.close,
Navigator.of(context, rootNavigator: false).pop<bool>(false), onPressed: () =>
)); Navigator.of(context, rootNavigator: false).pop<bool>(false),
),
);
break; break;
case BootstrapState.done: case BootstrapState.done:
titleText = L10n.of(context)!.everythingReady; titleText = L10n.of(context)!.everythingReady;
@ -416,11 +431,13 @@ class BootstrapDialogState extends State<BootstrapDialog> {
Text(L10n.of(context)!.yourChatBackupHasBeenSetUp), Text(L10n.of(context)!.yourChatBackupHasBeenSetUp),
], ],
); );
buttons.add(AdaptiveFlatButton( buttons.add(
label: L10n.of(context)!.close, AdaptiveFlatButton(
onPressed: () => label: L10n.of(context)!.close,
Navigator.of(context, rootNavigator: false).pop<bool>(false), onPressed: () =>
)); Navigator.of(context, rootNavigator: false).pop<bool>(false),
),
);
break; break;
} }
} }

View File

@ -75,7 +75,8 @@ class AddWidgetTileState extends State<AddWidgetTile> {
Navigator.of(context).pop(); Navigator.of(context).pop();
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(L10n.of(context)!.errorAddingWidget))); SnackBar(content: Text(L10n.of(context)!.errorAddingWidget)),
);
} }
} }

View File

@ -26,12 +26,15 @@ class AddWidgetTileView extends StatelessWidget {
'm.jitsi': Text(L10n.of(context)!.widgetJitsi), 'm.jitsi': Text(L10n.of(context)!.widgetJitsi),
'm.video': Text(L10n.of(context)!.widgetVideo), 'm.video': Text(L10n.of(context)!.widgetVideo),
'm.custom': Text(L10n.of(context)!.widgetCustom), 'm.custom': Text(L10n.of(context)!.widgetCustom),
}.map((key, value) => MapEntry( }.map(
(key, value) => MapEntry(
key, key,
Padding( Padding(
padding: const EdgeInsets.symmetric(horizontal: 4.0), padding: const EdgeInsets.symmetric(horizontal: 4.0),
child: value, child: value,
))), ),
),
),
onValueChanged: controller.setWidgetType, onValueChanged: controller.setWidgetType,
), ),
Padding( Padding(

View File

@ -9,7 +9,7 @@ import 'package:adaptive_dialog/adaptive_dialog.dart';
import 'package:desktop_drop/desktop_drop.dart'; import 'package:desktop_drop/desktop_drop.dart';
import 'package:device_info_plus/device_info_plus.dart'; import 'package:device_info_plus/device_info_plus.dart';
import 'package:emoji_picker_flutter/emoji_picker_flutter.dart'; import 'package:emoji_picker_flutter/emoji_picker_flutter.dart';
import 'package:file_picker_cross/file_picker_cross.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:future_loading_dialog/future_loading_dialog.dart'; import 'package:future_loading_dialog/future_loading_dialog.dart';
import 'package:image_picker/image_picker.dart'; import 'package:image_picker/image_picker.dart';
@ -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';
@ -35,25 +36,56 @@ import 'send_file_dialog.dart';
import 'send_location_dialog.dart'; import 'send_location_dialog.dart';
import 'sticker_picker_dialog.dart'; import 'sticker_picker_dialog.dart';
class Chat extends StatefulWidget { class ChatPage extends StatelessWidget {
final Widget? sideView; final Widget? sideView;
const Chat({Key? key, this.sideView}) : super(key: key); const ChatPage({Key? key, this.sideView}) : super(key: key);
@override
Widget build(BuildContext context) {
final roomId = context.vRouter.pathParameters['roomid'];
final room =
roomId == null ? null : Matrix.of(context).client.getRoomById(roomId);
if (room == null) {
return Scaffold(
appBar: AppBar(title: Text(L10n.of(context)!.oopsSomethingWentWrong)),
body: Center(
child: Padding(
padding: const EdgeInsets.all(16),
child:
Text(L10n.of(context)!.youAreNoLongerParticipatingInThisChat),
),
),
);
}
return ChatPageWithRoom(sideView: sideView, room: room);
}
}
class ChatPageWithRoom extends StatefulWidget {
final Widget? sideView;
final Room room;
const ChatPageWithRoom({
Key? key,
required this.sideView,
required this.room,
}) : super(key: key);
@override @override
ChatController createState() => ChatController(); ChatController createState() => ChatController();
} }
class ChatController extends State<Chat> { class ChatController extends State<ChatPageWithRoom> {
Room? room; Room get room => sendingClient.getRoomById(roomId) ?? widget.room;
Client? sendingClient; late Client sendingClient;
Timeline? timeline; Timeline? timeline;
MatrixState? matrix; String? readMarkerEventId;
String? get roomId => context.vRouter.pathParameters['roomid']; String get roomId => widget.room.id;
final AutoScrollController scrollController = AutoScrollController(); final AutoScrollController scrollController = AutoScrollController();
@ -82,10 +114,12 @@ class ChatController extends State<Chat> {
final matrixFiles = <MatrixFile>[]; final matrixFiles = <MatrixFile>[];
for (var i = 0; i < bytesList.result!.length; i++) { for (var i = 0; i < bytesList.result!.length; i++) {
matrixFiles.add(MatrixFile( matrixFiles.add(
bytes: bytesList.result![i], MatrixFile(
name: details.files[i].name, bytes: bytesList.result![i],
).detectFileType); name: details.files[i].name,
).detectFileType,
);
} }
await showDialog( await showDialog(
@ -93,7 +127,7 @@ class ChatController extends State<Chat> {
useRootNavigator: false, useRootNavigator: false,
builder: (c) => SendFileDialog( builder: (c) => SendFileDialog(
files: matrixFiles, files: matrixFiles,
room: room!, room: room,
), ),
); );
} }
@ -118,7 +152,10 @@ class ChatController extends State<Chat> {
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;
@ -128,40 +165,33 @@ class ChatController extends State<Chat> {
String pendingText = ''; String pendingText = '';
bool get canLoadMore =>
timeline!.events.isEmpty ||
timeline!.events.last.type != EventTypes.RoomCreate;
bool showEmojiPicker = false; bool showEmojiPicker = false;
void recreateChat() async { void recreateChat() async {
final room = this.room; final room = this.room;
final userId = room?.directChatMatrixID; final userId = room.directChatMatrixID;
if (room == null || userId == null) { if (userId == null) {
throw Exception( throw Exception(
'Try to recreate a room with is not a DM room. This should not be possible from the UI!'); 'Try to recreate a room with is not a DM room. This should not be possible from the UI!',
);
} }
final success = await showFutureLoadingDialog( final success = await showFutureLoadingDialog(
context: context, context: context,
future: () async { future: () async {
final client = room.client; final client = room.client;
final waitForSync = client.onSync.stream final waitForSync = client.onSync.stream
.firstWhere((s) => s.rooms?.leave?.containsKey(room.id) ?? false); .firstWhere((s) => s.rooms?.leave?.containsKey(room.id) ?? false);
await room.leave(); await room.leave();
await waitForSync; await waitForSync;
return await client.startDirectChat(userId); return await client.startDirectChat(userId);
}); },
);
final roomId = success.result; final roomId = success.result;
if (roomId == null) return; if (roomId == null) return;
VRouter.of(context).toSegments(['rooms', roomId]); VRouter.of(context).toSegments(['rooms', roomId]);
} }
void leaveChat() async { void leaveChat() async {
final room = this.room;
if (room == null) {
throw Exception(
'Leave room button clicked while room is null. This should not be possible from the UI!');
}
final success = await showFutureLoadingDialog( final success = await showFutureLoadingDialog(
context: context, context: context,
future: room.leave, future: room.leave,
@ -173,19 +203,40 @@ class ChatController extends State<Chat> {
EmojiPickerType emojiPickerType = EmojiPickerType.keyboard; EmojiPickerType emojiPickerType = EmojiPickerType.keyboard;
void requestHistory() async { void requestHistory() async {
if (canLoadMore) { if (!timeline!.canRequestHistory) return;
try { Logs().v('Requesting history...');
await timeline!.requestHistory(historyCount: _loadHistoryCount); try {
} catch (err) { await timeline!.requestHistory(historyCount: _loadHistoryCount);
ScaffoldMessenger.of(context).showSnackBar( } catch (err) {
SnackBar( ScaffoldMessenger.of(context).showSnackBar(
content: Text( SnackBar(
(err).toLocalizedString(context), content: Text(
), (err).toLocalizedString(context),
), ),
); ),
rethrow; );
} rethrow;
}
}
void requestFuture() async {
final timeline = this.timeline;
if (timeline == null) return;
if (!timeline.canRequestFuture) return;
Logs().v('Requesting future...');
try {
final mostRecentEventId = timeline.events.first.eventId;
await timeline.requestFuture(historyCount: _loadHistoryCount);
setReadMarker(eventId: mostRecentEventId);
} catch (err) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(
(err).toLocalizedString(context),
),
),
);
rethrow;
} }
} }
@ -195,18 +246,11 @@ class ChatController extends State<Chat> {
} }
setReadMarker(); setReadMarker();
if (!scrollController.hasClients) return; if (!scrollController.hasClients) return;
if (scrollController.position.pixels == if (timeline?.allowNewEvent == false ||
scrollController.position.maxScrollExtent && scrollController.position.pixels > 0 && _scrolledUp == false) {
timeline!.events.isNotEmpty && setState(() => _scrolledUp = true);
timeline!.events[timeline!.events.length - 1].type != } else if (scrollController.position.pixels == 0 && _scrolledUp == true) {
EventTypes.RoomCreate) { setState(() => _scrolledUp = false);
requestHistory();
}
if (scrollController.position.pixels > 0 && showScrollDownButton == false) {
setState(() => showScrollDownButton = true);
} else if (scrollController.position.pixels == 0 &&
showScrollDownButton == true) {
setState(() => showScrollDownButton = false);
} }
} }
@ -225,6 +269,12 @@ class ChatController extends State<Chat> {
inputFocus.addListener(_inputFocusListener); inputFocus.addListener(_inputFocusListener);
_loadDraft(); _loadDraft();
super.initState(); super.initState();
sendingClient = Matrix.of(context).client;
readMarkerEventId = room.fullyRead;
loadTimelineFuture =
_getTimeline(eventContextId: readMarkerEventId).onError(
ErrorReporter(context, 'Unable to load timeline').onErrorCallback,
);
} }
void updateView() { void updateView() {
@ -232,48 +282,84 @@ class ChatController extends State<Chat> {
setState(() {}); setState(() {});
} }
Future<bool> getTimeline() async { Future<void>? loadTimelineFuture;
if (timeline == null) {
await Matrix.of(context).client.roomsLoading;
await Matrix.of(context).client.accountDataLoading;
timeline = await room!.getTimeline(onUpdate: updateView);
if (timeline!.events.isNotEmpty) {
if (room!.markedUnread) room!.markUnread(false);
setReadMarker();
}
// when the scroll controller is attached we want to scroll to an event id, if specified Future<void> _getTimeline({
// and update the scroll controller...which will trigger a request history, if the String? eventContextId,
// "load more" button is visible on the screen Duration timeout = const Duration(seconds: 7),
SchedulerBinding.instance.addPostFrameCallback((_) async { }) async {
if (mounted) { await Matrix.of(context).client.roomsLoading;
final event = VRouter.of(context).queryParameters['event']; await Matrix.of(context).client.accountDataLoading;
if (event != null) { if (eventContextId != null &&
scrollToEventId(event); (!eventContextId.isValidMatrixId || eventContextId.sigil != '\$')) {
} eventContextId = null;
_updateScrollController(); }
} try {
}); timeline = await room
.getTimeline(
onUpdate: updateView,
eventContextId: eventContextId,
)
.timeout(timeout);
} catch (e, s) {
Logs().w('Unable to load timeline on event ID $eventContextId', e, s);
if (!mounted) return;
timeline = await room.getTimeline(onUpdate: updateView);
if (!mounted) return;
if (e is TimeoutException || e is IOException) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text(L10n.of(context)!.jumpToLastReadMessage),
action: SnackBarAction(
label: L10n.of(context)!.jump,
onPressed: () => scrollToEventId(eventContextId!),
),
),
);
}
} }
timeline!.requestKeys(onlineKeyBackupOnly: false); timeline!.requestKeys(onlineKeyBackupOnly: false);
return true; if (timeline!.events.isNotEmpty) {
if (room.markedUnread) room.markUnread(false);
setReadMarker();
}
// when the scroll controller is attached we want to scroll to an event id, if specified
// and update the scroll controller...which will trigger a request history, if the
// "load more" button is visible on the screen
SchedulerBinding.instance.addPostFrameCallback((_) async {
if (mounted) {
final event = VRouter.of(context).queryParameters['event'];
if (event != null) {
scrollToEventId(event);
}
}
});
return;
} }
Future<void>? _setReadMarkerFuture; Future<void>? _setReadMarkerFuture;
void setReadMarker([_]) { void setReadMarker({String? eventId}) {
if (_setReadMarkerFuture == null && if (_setReadMarkerFuture != null) return;
(room!.hasNewMessages || room!.notificationCount > 0) && if (eventId == null &&
timeline != null && !room.hasNewMessages &&
timeline!.events.isNotEmpty && room.notificationCount == 0) {
Matrix.of(context).webHasFocus) { return;
Logs().v('Set read marker...');
// ignore: unawaited_futures
_setReadMarkerFuture = timeline!.setReadMarker().then((_) {
_setReadMarkerFuture = null;
});
room!.client.updateIosBadge();
} }
if (!Matrix.of(context).webHasFocus) return;
final timeline = this.timeline;
if (timeline == null || timeline.events.isEmpty) return;
eventId ??= timeline.events.first.eventId;
Logs().v('Set read marker...', eventId);
// ignore: unawaited_futures
_setReadMarkerFuture = timeline.setReadMarker(eventId: eventId).then((_) {
_setReadMarkerFuture = null;
});
room.client.updateIosBadge();
} }
@override @override
@ -286,15 +372,24 @@ class ChatController extends State<Chat> {
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();
typingCoolDown = null; typingCoolDown = null;
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);
} }
@ -312,7 +407,7 @@ class ChatController extends State<Chat> {
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,
@ -327,10 +422,12 @@ class ChatController extends State<Chat> {
} }
// ignore: unawaited_futures // ignore: unawaited_futures
room!.sendTextEvent(sendController.text, room.sendTextEvent(
inReplyTo: replyEvent, sendController.text,
editEventId: editEvent?.eventId, inReplyTo: replyEvent,
parseCommands: parseCommands); editEventId: editEvent?.eventId,
parseCommands: parseCommands,
);
sendController.value = TextEditingValue( sendController.value = TextEditingValue(
text: pendingText, text: pendingText,
selection: const TextSelection.collapsed(offset: 0), selection: const TextSelection.collapsed(offset: 0),
@ -345,42 +442,49 @@ class ChatController extends State<Chat> {
} }
void sendFileAction() async { void sendFileAction() async {
final result = await FilePickerCross.importMultipleFromStorage( final result = await FilePicker.platform.pickFiles(
type: FileTypeCross.any, allowMultiple: true,
withData: true,
); );
if (result.isEmpty) return; if (result == null || result.files.isEmpty) return;
await showDialog( await showDialog(
context: context, context: context,
useRootNavigator: false, useRootNavigator: false,
builder: (c) => SendFileDialog( builder: (c) => SendFileDialog(
files: result files: result.files
.map((xfile) => MatrixFile( .map(
bytes: xfile.toUint8List(), (xfile) => MatrixFile(
name: xfile.fileName!, bytes: xfile.bytes!,
).detectFileType) name: xfile.name,
).detectFileType,
)
.toList(), .toList(),
room: room!, room: room,
), ),
); );
} }
void sendImageAction() async { void sendImageAction() async {
final result = await FilePickerCross.importMultipleFromStorage( final result = await FilePicker.platform.pickFiles(
type: FileTypeCross.image, type: FileType.image,
withData: true,
allowMultiple: true,
); );
if (result.isEmpty) return; if (result == null || result.files.isEmpty) return;
await showDialog( await showDialog(
context: context, context: context,
useRootNavigator: false, useRootNavigator: false,
builder: (c) => SendFileDialog( builder: (c) => SendFileDialog(
files: result files: result.files
.map((xfile) => MatrixFile( .map(
bytes: xfile.toUint8List(), (xfile) => MatrixFile(
name: xfile.fileName!, bytes: xfile.bytes!,
).detectFileType) name: xfile.name,
).detectFileType,
)
.toList(), .toList(),
room: room!, room: room,
), ),
); );
} }
@ -401,7 +505,7 @@ class ChatController extends State<Chat> {
name: file.path, name: file.path,
) )
], ],
room: room!, room: room,
), ),
); );
} }
@ -422,7 +526,7 @@ class ChatController extends State<Chat> {
name: file.path, name: file.path,
) )
], ],
room: room!, room: room,
), ),
); );
} }
@ -430,7 +534,7 @@ class ChatController extends State<Chat> {
void sendStickerAction() async { void sendStickerAction() async {
final sticker = await showAdaptiveBottomSheet<ImagePackImageContent>( final sticker = await showAdaptiveBottomSheet<ImagePackImageContent>(
context: context, context: context,
builder: (c) => StickerPickerDialog(room: room!), builder: (c) => StickerPickerDialog(room: room),
); );
if (sticker == null) return; if (sticker == null) return;
final eventContent = <String, dynamic>{ final eventContent = <String, dynamic>{
@ -439,13 +543,14 @@ class ChatController extends State<Chat> {
'url': sticker.url.toString(), 'url': sticker.url.toString(),
}; };
// send the sticker // send the sticker
await room!.sendEvent( await room.sendEvent(
eventContent, eventContent,
type: EventTypes.Sticker, type: EventTypes.Sticker,
); );
} }
void voiceMessageAction() async { void voiceMessageAction() async {
final scaffoldMessenger = ScaffoldMessenger.of(context);
if (PlatformInfos.isAndroid) { if (PlatformInfos.isAndroid) {
final info = await DeviceInfoPlugin().androidInfo; final info = await DeviceInfoPlugin().androidInfo;
if (info.version.sdkInt < 19) { if (info.version.sdkInt < 19) {
@ -472,7 +577,7 @@ class ChatController extends State<Chat> {
bytes: audioFile.readAsBytesSync(), bytes: audioFile.readAsBytesSync(),
name: audioFile.path, name: audioFile.path,
); );
await room!.sendFileEvent( await room.sendFileEvent(
file, file,
inReplyTo: replyEvent, inReplyTo: replyEvent,
extraContent: { extraContent: {
@ -486,7 +591,16 @@ class ChatController extends State<Chat> {
'waveform': result.waveform, 'waveform': result.waveform,
}, },
}, },
); ).catchError((e) {
scaffoldMessenger.showSnackBar(
SnackBar(
content: Text(
(e as Object).toLocalizedString(context),
),
),
);
return null;
});
setState(() { setState(() {
replyEvent = null; replyEvent = null;
}); });
@ -513,7 +627,7 @@ class ChatController extends State<Chat> {
await showDialog( await showDialog(
context: context, context: context,
useRootNavigator: false, useRootNavigator: false,
builder: (c) => SendLocationDialog(room: room!), builder: (c) => SendLocationDialog(room: room),
); );
} }
@ -527,8 +641,9 @@ class ChatController extends State<Chat> {
for (final event in selectedEvents) { for (final event in selectedEvents) {
if (copyString.isNotEmpty) copyString += '\n\n'; if (copyString.isNotEmpty) copyString += '\n\n';
copyString += event.getDisplayEvent(timeline!).calcLocalizedBodyFallback( copyString += event.getDisplayEvent(timeline!).calcLocalizedBodyFallback(
MatrixLocals(L10n.of(context)!), MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: true); withSenderNamePrefix: true,
);
} }
return copyString; return copyString;
} }
@ -544,33 +659,35 @@ class ChatController extends State<Chat> {
void reportEventAction() async { void reportEventAction() async {
final event = selectedEvents.single; final event = selectedEvents.single;
final score = await showConfirmationDialog<int>( final score = await showConfirmationDialog<int>(
context: context, context: context,
title: L10n.of(context)!.reportMessage, title: L10n.of(context)!.reportMessage,
message: L10n.of(context)!.howOffensiveIsThisContent, message: L10n.of(context)!.howOffensiveIsThisContent,
cancelLabel: L10n.of(context)!.cancel, cancelLabel: L10n.of(context)!.cancel,
okLabel: L10n.of(context)!.ok, okLabel: L10n.of(context)!.ok,
actions: [ actions: [
AlertDialogAction( AlertDialogAction(
key: -100, key: -100,
label: L10n.of(context)!.extremeOffensive, label: L10n.of(context)!.extremeOffensive,
), ),
AlertDialogAction( AlertDialogAction(
key: -50, key: -50,
label: L10n.of(context)!.offensive, label: L10n.of(context)!.offensive,
), ),
AlertDialogAction( AlertDialogAction(
key: 0, key: 0,
label: L10n.of(context)!.inoffensive, label: L10n.of(context)!.inoffensive,
), ),
]); ],
);
if (score == null) return; if (score == null) return;
final reason = await showTextInputDialog( final reason = await showTextInputDialog(
useRootNavigator: false, useRootNavigator: false,
context: context, context: context,
title: L10n.of(context)!.whyDoYouWantToReportThis, title: L10n.of(context)!.whyDoYouWantToReportThis,
okLabel: L10n.of(context)!.ok, okLabel: L10n.of(context)!.ok,
cancelLabel: L10n.of(context)!.cancel, cancelLabel: L10n.of(context)!.cancel,
textFields: [DialogTextField(hintText: L10n.of(context)!.reason)]); textFields: [DialogTextField(hintText: L10n.of(context)!.reason)],
);
if (reason == null || reason.single.isEmpty) return; if (reason == null || reason.single.isEmpty) return;
final result = await showFutureLoadingDialog( final result = await showFutureLoadingDialog(
context: context, context: context,
@ -587,7 +704,8 @@ class ChatController extends State<Chat> {
selectedEvents.clear(); selectedEvents.clear();
}); });
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(L10n.of(context)!.contentHasBeenReported))); SnackBar(content: Text(L10n.of(context)!.contentHasBeenReported)),
);
} }
void redactEventsAction() async { void redactEventsAction() async {
@ -602,25 +720,27 @@ class ChatController extends State<Chat> {
if (!confirmed) return; if (!confirmed) return;
for (final event in selectedEvents) { for (final event in selectedEvents) {
await showFutureLoadingDialog( await showFutureLoadingDialog(
context: context, context: context,
future: () async { future: () async {
if (event.status.isSent) { if (event.status.isSent) {
if (event.canRedact) { if (event.canRedact) {
await event.redactEvent(); await event.redactEvent();
} else {
final client = currentRoomBundle.firstWhere(
(cl) => selectedEvents.first.senderId == cl!.userID,
orElse: () => null);
if (client == null) {
return;
}
final room = client.getRoomById(roomId!)!;
await Event.fromJson(event.toJson(), room).redactEvent();
}
} else { } else {
await event.remove(); final client = currentRoomBundle.firstWhere(
(cl) => selectedEvents.first.senderId == cl!.userID,
orElse: () => null,
);
if (client == null) {
return;
}
final room = client.getRoomById(roomId)!;
await Event.fromJson(event.toJson(), room).redactEvent();
} }
}); } else {
await event.remove();
}
},
);
} }
setState(() { setState(() {
showEmojiPicker = false; showEmojiPicker = false;
@ -629,14 +749,14 @@ class ChatController extends State<Chat> {
} }
List<Client?> get currentRoomBundle { List<Client?> get currentRoomBundle {
final clients = matrix!.currentBundle!; final clients = Matrix.of(context).currentBundle!;
clients.removeWhere((c) => c!.getRoomById(roomId!) == null); clients.removeWhere((c) => c!.getRoomById(roomId) == null);
return clients; return clients;
} }
bool get canRedactSelectedEvents { bool get canRedactSelectedEvents {
if (isArchived) return false; if (isArchived) return false;
final clients = matrix!.currentBundle; final clients = Matrix.of(context).currentBundle;
for (final event in selectedEvents) { for (final event in selectedEvents) {
if (event.canRedact == false && if (event.canRedact == false &&
!(clients!.any((cl) => event.senderId == cl!.userID))) return false; !(clients!.any((cl) => event.senderId == cl!.userID))) return false;
@ -691,48 +811,23 @@ class ChatController extends State<Chat> {
} }
void scrollToEventId(String eventId) async { void scrollToEventId(String eventId) async {
var eventIndex = timeline!.events.indexWhere((e) => e.eventId == eventId); final eventIndex = timeline!.events.indexWhere((e) => e.eventId == eventId);
if (eventIndex == -1) { if (eventIndex == -1) {
// event id not found...maybe we can fetch it? setState(() {
// the try...finally is here to start and close the loading dialog reliably timeline = null;
await showFutureLoadingDialog( _scrolledUp = false;
context: context, loadTimelineFuture = _getTimeline(
future: () async { eventContextId: eventId,
// okay, we first have to fetch if the event is in the room timeout: const Duration(seconds: 30),
try { ).onError(
final event = await timeline!.getEventById(eventId); ErrorReporter(context, 'Unable to load timeline after scroll to ID')
if (event == null) { .onErrorCallback,
// event is null...meaning something is off );
return; });
} await loadTimelineFuture;
} catch (err) { WidgetsBinding.instance.addPostFrameCallback((timeStamp) {
if (err is MatrixException && err.errcode == 'M_NOT_FOUND') { scrollToEventId(eventId);
// event wasn't found, as the server gave a 404 or something });
return;
}
rethrow;
}
// okay, we know that the event *is* in the room
while (eventIndex == -1) {
if (!canLoadMore) {
// we can't load any more events but still haven't found ours yet...better stop here
return;
}
try {
await timeline!.requestHistory(historyCount: _loadHistoryCount);
} catch (err) {
if (err is TimeoutException) {
// loading the history timed out...so let's do nothing
return;
}
rethrow;
}
eventIndex =
timeline!.events.indexWhere((e) => e.eventId == eventId);
}
});
}
if (!mounted) {
return; return;
} }
await scrollController.scrollToIndex( await scrollController.scrollToIndex(
@ -742,7 +837,21 @@ class ChatController extends State<Chat> {
_updateScrollController(); _updateScrollController();
} }
void scrollDown() => scrollController.jumpTo(0); void scrollDown() async {
if (!timeline!.allowNewEvent) {
setState(() {
timeline = null;
_scrolledUp = false;
loadTimelineFuture = _getTimeline().onError(
ErrorReporter(context, 'Unable to load timeline after scroll down')
.onErrorCallback,
);
});
await loadTimelineFuture;
setReadMarker(eventId: timeline!.events.first.eventId);
}
scrollController.jumpTo(0);
}
void onEmojiSelected(_, Emoji? emoji) { void onEmojiSelected(_, Emoji? emoji) {
switch (emojiPickerType) { switch (emojiPickerType) {
@ -760,15 +869,18 @@ class ChatController extends State<Chat> {
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);
} }
void forgetRoom() async { void forgetRoom() async {
final result = await showFutureLoadingDialog( final result = await showFutureLoadingDialog(
context: context, context: context,
future: room!.forget, future: room.forget,
); );
if (result.error != null) return; if (result.error != null) return;
VRouter.of(context).to('/archive'); VRouter.of(context).to('/archive');
@ -801,7 +913,8 @@ class ChatController extends State<Chat> {
sendController sendController
..text = sendController.text.characters.skipLast(1).toString() ..text = sendController.text.characters.skipLast(1).toString()
..selection = TextSelection.fromPosition( ..selection = TextSelection.fromPosition(
TextPosition(offset: sendController.text.length)); TextPosition(offset: sendController.text.length),
);
break; break;
} }
} }
@ -816,7 +929,7 @@ class ChatController extends State<Chat> {
final events = List<Event>.from(selectedEvents); final events = List<Event>.from(selectedEvents);
setState(() => selectedEvents.clear()); setState(() => selectedEvents.clear());
for (final event in events) { for (final event in events) {
await room!.sendReaction( await room.sendReaction(
event.eventId, event.eventId,
emoji!, emoji!,
); );
@ -836,8 +949,9 @@ class ChatController extends State<Chat> {
void editSelectedEventAction() { void editSelectedEventAction() {
final client = currentRoomBundle.firstWhere( final client = currentRoomBundle.firstWhere(
(cl) => selectedEvents.first.senderId == cl!.userID, (cl) => selectedEvents.first.senderId == cl!.userID,
orElse: () => null); orElse: () => null,
);
if (client == null) { if (client == null) {
return; return;
} }
@ -845,10 +959,12 @@ class ChatController extends State<Chat> {
setState(() { setState(() {
pendingText = sendController.text; pendingText = sendController.text;
editEvent = selectedEvents.first; editEvent = selectedEvents.first;
inputText = sendController.text = editEvent! inputText = sendController.text =
.getDisplayEvent(timeline!) editEvent!.getDisplayEvent(timeline!).calcLocalizedBodyFallback(
.calcLocalizedBodyFallback(MatrixLocals(L10n.of(context)!), MatrixLocals(L10n.of(context)!),
withSenderNamePrefix: false, hideReply: true); withSenderNamePrefix: false,
hideReply: true,
);
selectedEvents.clear(); selectedEvents.clear();
}); });
inputFocus.requestFocus(); inputFocus.requestFocus();
@ -860,7 +976,7 @@ class ChatController extends State<Chat> {
useRootNavigator: false, useRootNavigator: false,
context: context, context: context,
title: L10n.of(context)!.goToTheNewRoom, title: L10n.of(context)!.goToTheNewRoom,
message: room! message: room
.getState(EventTypes.RoomTombstone)! .getState(EventTypes.RoomTombstone)!
.parsedTombstoneContent .parsedTombstoneContent
.body, .body,
@ -871,14 +987,16 @@ class ChatController extends State<Chat> {
} }
final result = await showFutureLoadingDialog( final result = await showFutureLoadingDialog(
context: context, context: context,
future: () => room!.client.joinRoom(room! future: () => room.client.joinRoom(
.getState(EventTypes.RoomTombstone)! room
.parsedTombstoneContent .getState(EventTypes.RoomTombstone)!
.replacementRoom), .parsedTombstoneContent
.replacementRoom,
),
); );
await showFutureLoadingDialog( await showFutureLoadingDialog(
context: context, context: context,
future: room!.leave, future: room.leave,
); );
if (result.error == null) { if (result.error == null) {
VRouter.of(context).toSegments(['rooms', result.result!]); VRouter.of(context).toSegments(['rooms', result.result!]);
@ -955,18 +1073,16 @@ class ChatController extends State<Chat> {
cancelLabel: L10n.of(context)!.cancel, cancelLabel: L10n.of(context)!.cancel,
); );
if (response == OkCancelResult.ok) { if (response == OkCancelResult.ok) {
final events = room!.pinnedEventIds final events = room.pinnedEventIds
..removeWhere((oldEvent) => oldEvent == eventId); ..removeWhere((oldEvent) => oldEvent == eventId);
showFutureLoadingDialog( showFutureLoadingDialog(
context: context, context: context,
future: () => room!.setPinnedEvents(events), future: () => room.setPinnedEvents(events),
); );
} }
} }
void pinEvent() { void pinEvent() {
final room = this.room;
if (room == null) return;
final pinnedEventIds = room.pinnedEventIds; final pinnedEventIds = room.pinnedEventIds;
final selectedEventIds = selectedEvents.map((e) => e.eventId).toSet(); final selectedEventIds = selectedEvents.map((e) => e.eventId).toSet();
final unpin = selectedEventIds.length == 1 && final unpin = selectedEventIds.length == 1 &&
@ -992,7 +1108,7 @@ class ChatController extends State<Chat> {
await prefs.setString('draft_$roomId', text); await prefs.setString('draft_$roomId', text);
}); });
setReadMarker(); setReadMarker();
if (text.endsWith(' ') && matrix!.hasComplexBundles) { if (text.endsWith(' ') && Matrix.of(context).hasComplexBundles) {
final clients = currentRoomBundle; final clients = currentRoomBundle;
for (final client in clients) { for (final client in clients) {
final prefix = client!.sendPrefix; final prefix = client!.sendPrefix;
@ -1011,7 +1127,7 @@ class ChatController extends State<Chat> {
typingCoolDown = Timer(const Duration(seconds: 2), () { typingCoolDown = Timer(const Duration(seconds: 2), () {
typingCoolDown = null; typingCoolDown = null;
currentlyTyping = false; currentlyTyping = false;
room!.setTyping(false); room.setTyping(false);
}); });
typingTimeout ??= Timer(const Duration(seconds: 30), () { typingTimeout ??= Timer(const Duration(seconds: 30), () {
typingTimeout = null; typingTimeout = null;
@ -1019,14 +1135,13 @@ class ChatController extends State<Chat> {
}); });
if (!currentlyTyping) { if (!currentlyTyping) {
currentlyTyping = true; currentlyTyping = true;
room! room.setTyping(true, timeout: const Duration(seconds: 30).inMilliseconds);
.setTyping(true, timeout: const Duration(seconds: 30).inMilliseconds);
} }
setState(() => inputText = text); setState(() => inputText = text);
} }
bool get isArchived => bool get isArchived =>
{Membership.leave, Membership.ban}.contains(room?.membership); {Membership.leave, Membership.ban}.contains(room.membership);
void showEventInfo([Event? event]) => void showEventInfo([Event? event]) =>
(event ?? selectedEvents.single).showInfoDialog(context); (event ?? selectedEvents.single).showInfoDialog(context);
@ -1067,13 +1182,14 @@ class ChatController extends State<Chat> {
if (callType == null) return; if (callType == null) return;
final success = await showFutureLoadingDialog( final success = await showFutureLoadingDialog(
context: context, context: context,
future: () => future: () =>
Matrix.of(context).voipPlugin!.voip.requestTurnServerCredentials()); Matrix.of(context).voipPlugin!.voip.requestTurnServerCredentials(),
);
if (success.result != null) { if (success.result != null) {
final voipPlugin = Matrix.of(context).voipPlugin; final voipPlugin = Matrix.of(context).voipPlugin;
try { try {
await voipPlugin!.voip.inviteToCall(room!.id, callType); await voipPlugin!.voip.inviteToCall(room.id, callType);
} catch (e) { } catch (e) {
ScaffoldMessenger.of(context).showSnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text(e.toLocalizedString(context))), SnackBar(content: Text(e.toLocalizedString(context))),

View File

@ -16,9 +16,6 @@ class ChatAppBarTitle extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
final room = controller.room; final room = controller.room;
if (room == null) {
return Container();
}
if (controller.selectedEvents.isNotEmpty) { if (controller.selectedEvents.isNotEmpty) {
return Text(controller.selectedEvents.length.toString()); return Text(controller.selectedEvents.length.toString());
} }

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';
@ -48,6 +47,26 @@ class ChatEventList extends StatelessWidget {
(BuildContext context, int i) { (BuildContext context, int i) {
// Footer to display typing indicator and read receipts: // Footer to display typing indicator and read receipts:
if (i == 0) { if (i == 0) {
if (controller.timeline!.isRequestingFuture) {
return const Center(
child: CircularProgressIndicator.adaptive(strokeWidth: 2),
);
}
if (controller.timeline!.canRequestFuture) {
return Builder(
builder: (context) {
WidgetsBinding.instance.addPostFrameCallback(
(_) => controller.requestFuture(),
);
return Center(
child: IconButton(
onPressed: controller.requestFuture,
icon: const Icon(Icons.refresh_outlined),
),
);
},
);
}
return Column( return Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -64,18 +83,22 @@ class ChatEventList extends StatelessWidget {
child: CircularProgressIndicator.adaptive(strokeWidth: 2), child: CircularProgressIndicator.adaptive(strokeWidth: 2),
); );
} }
if (controller.canLoadMore) { 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 Container(); return const SizedBox.shrink();
} }
// The message at this index: // The message at this index:
@ -86,19 +109,20 @@ class ChatEventList extends StatelessWidget {
index: i - 1, index: i - 1,
controller: controller.scrollController, controller: controller.scrollController,
child: event.isVisibleInGui child: event.isVisibleInGui
? Message(event, ? Message(
event,
onSwipe: (direction) => onSwipe: (direction) =>
controller.replyAction(replyTo: event), controller.replyAction(replyTo: event),
onInfoTab: controller.showEventInfo, onInfoTab: controller.showEventInfo,
onAvatarTab: (Event event) => showAdaptiveBottomSheet( onAvatarTab: (Event event) => showAdaptiveBottomSheet(
context: context, context: context,
builder: (c) => UserBottomSheet( builder: (c) => UserBottomSheet(
user: event.senderFromMemoryOrFallback, user: event.senderFromMemoryOrFallback,
outerContext: context, outerContext: context,
onMention: () => controller.sendController.text += onMention: () => controller.sendController.text +=
'${event.senderFromMemoryOrFallback.mention} ', '${event.senderFromMemoryOrFallback.mention} ',
), ),
), ),
onSelect: controller.onSelectMessage, onSelect: controller.onSelectMessage,
scrollToEventId: (String eventId) => scrollToEventId: (String eventId) =>
controller.scrollToEventId(eventId), controller.scrollToEventId(eventId),
@ -106,10 +130,14 @@ class ChatEventList extends StatelessWidget {
selected: controller.selectedEvents selected: controller.selectedEvents
.any((e) => e.eventId == event.eventId), .any((e) => e.eventId == event.eventId),
timeline: controller.timeline!, timeline: controller.timeline!,
displayReadMarker:
controller.readMarkerEventId == event.eventId &&
controller.timeline?.allowNewEvent == false,
nextEvent: i < controller.timeline!.events.length nextEvent: i < controller.timeline!.events.length
? controller.timeline!.events[i] ? controller.timeline!.events[i]
: null) : null,
: Container(), )
: const SizedBox.shrink(),
); );
}, },
childCount: controller.timeline!.events.length + 2, childCount: controller.timeline!.events.length + 2,

View File

@ -23,7 +23,7 @@ class ChatInputRow extends StatelessWidget {
Widget build(BuildContext context) { Widget build(BuildContext context) {
if (controller.showEmojiPicker && if (controller.showEmojiPicker &&
controller.emojiPickerType == EmojiPickerType.reaction) { controller.emojiPickerType == EmojiPickerType.reaction) {
return Container(); return const SizedBox.shrink();
} }
return Row( return Row(
crossAxisAlignment: CrossAxisAlignment.end, crossAxisAlignment: CrossAxisAlignment.end,
@ -72,7 +72,7 @@ class ChatInputRow extends StatelessWidget {
), ),
), ),
) )
: Container(), : const SizedBox.shrink(),
] ]
: <Widget>[ : <Widget>[
KeyBoardShortcuts( KeyBoardShortcuts(
@ -146,7 +146,7 @@ class ChatInputRow extends StatelessWidget {
contentPadding: const EdgeInsets.all(0), contentPadding: const EdgeInsets.all(0),
), ),
), ),
if (controller.room! if (controller.room
.getImagePacks(ImagePackUsage.sticker) .getImagePacks(ImagePackUsage.sticker)
.isNotEmpty) .isNotEmpty)
PopupMenuItem<String>( PopupMenuItem<String>(
@ -215,9 +215,9 @@ class ChatInputRow extends StatelessWidget {
), ),
), ),
), ),
if (controller.matrix!.isMultiAccount && if (Matrix.of(context).isMultiAccount &&
controller.matrix!.hasComplexBundles && Matrix.of(context).hasComplexBundles &&
controller.matrix!.currentBundle!.length > 1) Matrix.of(context).currentBundle!.length > 1)
Container( Container(
height: 56, height: 56,
alignment: Alignment.center, alignment: Alignment.center,
@ -227,7 +227,7 @@ class ChatInputRow extends StatelessWidget {
child: Padding( child: Padding(
padding: const EdgeInsets.symmetric(vertical: 4.0), padding: const EdgeInsets.symmetric(vertical: 4.0),
child: InputBar( child: InputBar(
room: controller.room!, room: controller.room,
minLines: 1, minLines: 1,
maxLines: 8, maxLines: 8,
autofocus: !PlatformInfos.isMobile, autofocus: !PlatformInfos.isMobile,
@ -279,8 +279,9 @@ class _ChatAccountPicker extends StatelessWidget {
const _ChatAccountPicker(this.controller, {Key? key}) : super(key: key); const _ChatAccountPicker(this.controller, {Key? key}) : super(key: key);
void _popupMenuButtonSelected(String mxid) { void _popupMenuButtonSelected(String mxid, BuildContext context) {
final client = controller.matrix!.currentBundle! final client = Matrix.of(context)
.currentBundle!
.firstWhere((cl) => cl!.userID == mxid, orElse: () => null); .firstWhere((cl) => cl!.userID == mxid, orElse: () => null);
if (client == null) { if (client == null) {
Logs().w('Attempted to switch to a non-existing client $mxid'); Logs().w('Attempted to switch to a non-existing client $mxid');
@ -291,37 +292,37 @@ class _ChatAccountPicker extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
controller.matrix ??= Matrix.of(context);
final clients = controller.currentRoomBundle; final clients = controller.currentRoomBundle;
return Padding( return Padding(
padding: const EdgeInsets.all(8.0), padding: const EdgeInsets.all(8.0),
child: FutureBuilder<Profile>( child: FutureBuilder<Profile>(
future: controller.sendingClient!.fetchOwnProfile(), future: controller.sendingClient.fetchOwnProfile(),
builder: (context, snapshot) => PopupMenuButton<String>( builder: (context, snapshot) => PopupMenuButton<String>(
onSelected: _popupMenuButtonSelected, onSelected: (mxid) => _popupMenuButtonSelected(mxid, context),
itemBuilder: (BuildContext context) => clients itemBuilder: (BuildContext context) => clients
.map((client) => PopupMenuItem<String>( .map(
value: client!.userID, (client) => PopupMenuItem<String>(
child: FutureBuilder<Profile>( value: client!.userID,
future: client.fetchOwnProfile(), child: FutureBuilder<Profile>(
builder: (context, snapshot) => ListTile( future: client.fetchOwnProfile(),
leading: Avatar( builder: (context, snapshot) => ListTile(
mxContent: snapshot.data?.avatarUrl, leading: Avatar(
name: snapshot.data?.displayName ?? mxContent: snapshot.data?.avatarUrl,
client.userID!.localpart, name: snapshot.data?.displayName ??
size: 20, client.userID!.localpart,
), size: 20,
title:
Text(snapshot.data?.displayName ?? client.userID!),
contentPadding: const EdgeInsets.all(0),
), ),
title: Text(snapshot.data?.displayName ?? client.userID!),
contentPadding: const EdgeInsets.all(0),
), ),
)) ),
),
)
.toList(), .toList(),
child: Avatar( child: Avatar(
mxContent: snapshot.data?.avatarUrl, mxContent: snapshot.data?.avatarUrl,
name: snapshot.data?.displayName ?? name: snapshot.data?.displayName ??
controller.matrix!.client.userID!.localpart, Matrix.of(context).client.userID!.localpart,
size: 20, size: 20,
), ),
), ),

View File

@ -49,11 +49,12 @@ class ChatView extends StatelessWidget {
if (controller.canSaveSelectedEvent) if (controller.canSaveSelectedEvent)
// Use builder context to correctly position the share dialog on iPad // Use builder context to correctly position the share dialog on iPad
Builder( Builder(
builder: (context) => IconButton( builder: (context) => IconButton(
icon: Icon(Icons.adaptive.share), icon: Icon(Icons.adaptive.share),
tooltip: L10n.of(context)!.share, tooltip: L10n.of(context)!.share,
onPressed: () => controller.saveSelectedEvent(context), onPressed: () => controller.saveSelectedEvent(context),
)), ),
),
if (controller.canRedactSelectedEvents) if (controller.canRedactSelectedEvents)
IconButton( IconButton(
icon: const Icon(Icons.delete_outlined), icon: const Icon(Icons.delete_outlined),
@ -124,41 +125,27 @@ class ChatView extends StatelessWidget {
} else { } else {
return [ return [
if (Matrix.of(context).voipPlugin != null && if (Matrix.of(context).voipPlugin != null &&
controller.room!.isDirectChat) controller.room.isDirectChat)
IconButton( IconButton(
onPressed: controller.onPhoneButtonTap, onPressed: controller.onPhoneButtonTap,
icon: const Icon(Icons.call_outlined), icon: const Icon(Icons.call_outlined),
tooltip: L10n.of(context)!.placeCall, tooltip: L10n.of(context)!.placeCall,
), ),
EncryptionButton(controller.room!), EncryptionButton(controller.room),
ChatSettingsPopupMenu(controller.room!, !controller.room!.isDirectChat), ChatSettingsPopupMenu(controller.room, !controller.room.isDirectChat),
]; ];
} }
} }
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
controller.matrix ??= Matrix.of(context); if (controller.room.membership == Membership.invite) {
final client = controller.matrix!.client; showFutureLoadingDialog(
controller.sendingClient ??= client; context: context,
controller.room = controller.sendingClient!.getRoomById(controller.roomId!); future: () => controller.room.join(),
if (controller.room == null) {
return Scaffold(
appBar: AppBar(
title: Text(L10n.of(context)!.oopsSomethingWentWrong),
),
body: Center(
child: Text(L10n.of(context)!.youAreNoLongerParticipatingInThisChat),
),
); );
} }
if (controller.room!.membership == Membership.invite) {
showFutureLoadingDialog(
context: context, future: () => controller.room!.join());
}
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 {
@ -171,13 +158,13 @@ class ChatView extends StatelessWidget {
} }
}, },
child: GestureDetector( child: GestureDetector(
onTapDown: controller.setReadMarker, onTapDown: (_) => controller.setReadMarker(),
behavior: HitTestBehavior.opaque, behavior: HitTestBehavior.opaque,
child: StreamBuilder( child: StreamBuilder(
stream: controller.room!.onUpdate.stream stream: controller.room.onUpdate.stream
.rateLimit(const Duration(seconds: 1)), .rateLimit(const Duration(seconds: 1)),
builder: (context, snapshot) => FutureBuilder<bool>( builder: (context, snapshot) => FutureBuilder(
future: controller.getTimeline(), future: controller.loadTimelineFuture,
builder: (BuildContext context, snapshot) { builder: (BuildContext context, snapshot) {
return Scaffold( return Scaffold(
appBar: AppBar( appBar: AppBar(
@ -195,7 +182,7 @@ class ChatView extends StatelessWidget {
color: Theme.of(context).colorScheme.primary, color: Theme.of(context).colorScheme.primary,
) )
: UnreadRoomsBadge( : UnreadRoomsBadge(
filter: (r) => r.id != controller.roomId!, filter: (r) => r.id != controller.roomId,
badgePosition: BadgePosition.topEnd(end: 8, top: 4), badgePosition: BadgePosition.topEnd(end: 8, top: 4),
child: const Center(child: BackButton()), child: const Center(child: BackButton()),
), ),
@ -209,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),
), ),
@ -231,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),
],
), ),
), ),
), ),
@ -249,24 +232,27 @@ class ChatView extends StatelessWidget {
PinnedEvents(controller), PinnedEvents(controller),
Expanded( Expanded(
child: GestureDetector( child: GestureDetector(
onTap: controller.clearSingleSelectedEvent, onTap: controller.clearSingleSelectedEvent,
child: Builder( child: Builder(
builder: (context) { builder: (context) {
if (controller.timeline == null) { if (controller.timeline == null) {
return const Center( return const Center(
child: CircularProgressIndicator child:
.adaptive(strokeWidth: 2), CircularProgressIndicator.adaptive(
); strokeWidth: 2,
} ),
return ChatEventList(
controller: controller,
); );
}, }
)),
return ChatEventList(
controller: controller,
);
},
),
),
), ),
if (controller.room!.canSendDefaultMessages && if (controller.room.canSendDefaultMessages &&
controller.room!.membership == Membership.join) controller.room.membership == Membership.join)
Container( Container(
margin: EdgeInsets.only( margin: EdgeInsets.only(
bottom: bottomSheetPadding, bottom: bottomSheetPadding,
@ -274,7 +260,8 @@ class ChatView extends StatelessWidget {
right: bottomSheetPadding, right: bottomSheetPadding,
), ),
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: FluffyThemes.columnWidth * 2.5), maxWidth: FluffyThemes.columnWidth * 2.5,
),
alignment: Alignment.center, alignment: Alignment.center,
child: Material( child: Material(
borderRadius: const BorderRadius.only( borderRadius: const BorderRadius.only(
@ -290,7 +277,7 @@ class ChatView extends StatelessWidget {
Brightness.light Brightness.light
? Colors.white ? Colors.white
: Colors.black, : Colors.black,
child: controller.room?.isAbandonedDMRoom == child: controller.room.isAbandonedDMRoom ==
true true
? Row( ? Row(
mainAxisAlignment: mainAxisAlignment:
@ -319,12 +306,13 @@ class ChatView extends StatelessWidget {
const EdgeInsets.all(16), const EdgeInsets.all(16),
), ),
icon: const Icon( icon: const Icon(
Icons.chat_outlined, Icons.forum_outlined,
), ),
onPressed: onPressed:
controller.recreateChat, controller.recreateChat,
label: Text( label: Text(
L10n.of(context)!.reopenChat), L10n.of(context)!.reopenChat,
),
), ),
], ],
) )

View File

@ -15,15 +15,18 @@ class EditWidgetsDialog extends StatelessWidget {
return SimpleDialog( return SimpleDialog(
title: Text(L10n.of(context)!.editWidgets), title: Text(L10n.of(context)!.editWidgets),
children: [ children: [
...room.widgets.map((e) => ListTile( ...room.widgets.map(
title: Text(e.name ?? e.type), (e) => ListTile(
leading: IconButton( title: Text(e.name ?? e.type),
onPressed: () { leading: IconButton(
room.deleteWidget(e.id!); onPressed: () {
Navigator.of(context).pop(); room.deleteWidget(e.id!);
}, Navigator.of(context).pop();
icon: const Icon(Icons.delete)), },
)), icon: const Icon(Icons.delete),
),
),
),
AddWidgetTile(room: room), AddWidgetTile(room: room),
], ],
); );

View File

@ -13,34 +13,36 @@ class EncryptionButton extends StatelessWidget {
@override @override
Widget build(BuildContext context) { Widget build(BuildContext context) {
return StreamBuilder<SyncUpdate>( return StreamBuilder<SyncUpdate>(
stream: Matrix.of(context) stream: Matrix.of(context)
.client .client
.onSync .onSync
.stream .stream
.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
builder: (BuildContext context, snapshot) => IconButton( ? room.calcEncryptionHealthState()
tooltip: room.encrypted : Future.value(EncryptionHealthState.allVerified),
? L10n.of(context)!.encrypted builder: (BuildContext context, snapshot) => IconButton(
: L10n.of(context)!.encryptionNotEnabled, tooltip: room.encrypted
icon: Icon( ? L10n.of(context)!.encrypted
room.encrypted : L10n.of(context)!.encryptionNotEnabled,
? Icons.lock_outlined icon: Icon(
: Icons.lock_open_outlined, room.encrypted ? Icons.lock_outlined : Icons.lock_open_outlined,
size: 20, size: 20,
color: room.joinRules != JoinRules.public && color: room.joinRules != JoinRules.public && !room.encrypted
!room.encrypted ? Colors.red
? Colors.red : room.joinRules != JoinRules.public &&
: room.joinRules != JoinRules.public && snapshot.data ==
snapshot.data == EncryptionHealthState.unverifiedDevices
EncryptionHealthState.unverifiedDevices ? Colors.orange
? Colors.orange : null,
: null), ),
onPressed: () => VRouter.of(context) onPressed: () => VRouter.of(context)
.toSegments(['rooms', room.id, 'encryption']), .toSegments(['rooms', room.id, 'encryption']),
)); ),
}); );
},
);
} }
} }

View File

@ -54,7 +54,8 @@ class EventInfoDialog extends StatelessWidget {
), ),
title: Text(L10n.of(context)!.sender), title: Text(L10n.of(context)!.sender),
subtitle: Text( subtitle: Text(
'${event.senderFromMemoryOrFallback.calcDisplayname()} [${event.senderId}]'), '${event.senderFromMemoryOrFallback.calcDisplayname()} [${event.senderId}]',
),
), ),
ListTile( ListTile(
title: Text(L10n.of(context)!.time), title: Text(L10n.of(context)!.time),

View File

@ -1,14 +1,15 @@
import 'dart:async'; import 'dart:async';
import 'dart:io'; import 'dart:io';
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';
@ -31,7 +32,7 @@ enum AudioPlayerStatus { notDownloaded, downloading, downloaded }
class AudioPlayerState extends State<AudioPlayerWidget> { class AudioPlayerState extends State<AudioPlayerWidget> {
AudioPlayerStatus status = AudioPlayerStatus.notDownloaded; AudioPlayerStatus status = AudioPlayerStatus.notDownloaded;
final AudioPlayer audioPlayer = AudioPlayer(); AudioPlayer? audioPlayer;
StreamSubscription? onAudioPositionChanged; StreamSubscription? onAudioPositionChanged;
StreamSubscription? onDurationChanged; StreamSubscription? onDurationChanged;
@ -42,12 +43,13 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
int currentPosition = 0; int currentPosition = 0;
double maxPosition = 0; double maxPosition = 0;
MatrixFile? matrixFile;
File? audioFile; File? audioFile;
@override @override
void dispose() { void dispose() {
if (audioPlayer.playerState.playing) { if (audioPlayer?.playerState.playing == true) {
audioPlayer.stop(); audioPlayer?.stop();
} }
onAudioPositionChanged?.cancel(); onAudioPositionChanged?.cancel();
onDurationChanged?.cancel(); onDurationChanged?.cancel();
@ -62,14 +64,20 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
setState(() => status = AudioPlayerStatus.downloading); setState(() => status = AudioPlayerStatus.downloading);
try { try {
final matrixFile = await widget.event.downloadAndDecryptAttachment(); final matrixFile = await widget.event.downloadAndDecryptAttachment();
final tempDir = await getTemporaryDirectory(); File? file;
final fileName = Uri.encodeComponent(
widget.event.attachmentOrThumbnailMxcUrl()!.pathSegments.last); if (!kIsWeb) {
final file = File('${tempDir.path}/${fileName}_${matrixFile.name}'); final tempDir = await getTemporaryDirectory();
await file.writeAsBytes(matrixFile.bytes); final fileName = Uri.encodeComponent(
widget.event.attachmentOrThumbnailMxcUrl()!.pathSegments.last,
);
file = File('${tempDir.path}/${fileName}_${matrixFile.name}');
await file.writeAsBytes(matrixFile.bytes);
}
setState(() { setState(() {
audioFile = file; audioFile = file;
this.matrixFile = matrixFile;
status = AudioPlayerStatus.downloaded; status = AudioPlayerStatus.downloaded;
}); });
_playAction(); _playAction();
@ -84,6 +92,7 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
} }
void _playAction() async { void _playAction() async {
final audioPlayer = this.audioPlayer ??= AudioPlayer();
if (AudioPlayerWidget.currentId != widget.event.eventId) { if (AudioPlayerWidget.currentId != widget.event.eventId) {
if (AudioPlayerWidget.currentId != null) { if (AudioPlayerWidget.currentId != null) {
if (audioPlayer.playerState.playing) { if (audioPlayer.playerState.playing) {
@ -117,15 +126,16 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
}); });
onPlayerStateChanged ??= onPlayerStateChanged ??=
audioPlayer.playingStream.listen((_) => setState(() {})); audioPlayer.playingStream.listen((_) => setState(() {}));
audioPlayer.setFilePath(audioFile!.path); final audioFile = this.audioFile;
audioPlayer.play().catchError((e, s) { if (audioFile != null) {
ScaffoldMessenger.of(context).showSnackBar( audioPlayer.setFilePath(audioFile.path);
SnackBar( } else {
content: Text(L10n.of(context)!.oopsSomethingWentWrong), await audioPlayer.setAudioSource(MatrixFileAudioSource(matrixFile!));
), }
); audioPlayer.play().onError(
Logs().w('Error while playing audio', e, s); ErrorReporter(context, 'Unable to play audio message')
}); .onErrorCallback,
);
} }
static const double buttonSize = 36; static const double buttonSize = 36;
@ -188,7 +198,7 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
color: widget.color.withAlpha(64), color: widget.color.withAlpha(64),
borderRadius: BorderRadius.circular(64), borderRadius: BorderRadius.circular(64),
child: Icon( child: Icon(
audioPlayer.playerState.playing audioPlayer?.playerState.playing == true
? Icons.pause_outlined ? Icons.pause_outlined
: Icons.play_arrow_outlined, : Icons.play_arrow_outlined,
color: widget.color, color: widget.color,
@ -211,23 +221,27 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
for (var i = 0; i < AudioPlayerWidget.wavesCount; i++) for (var i = 0; i < AudioPlayerWidget.wavesCount; i++)
Expanded( Expanded(
child: InkWell( child: InkWell(
onTap: () => audioPlayer.seek(Duration( onTap: () => audioPlayer?.seek(
Duration(
milliseconds: milliseconds:
(maxPosition / AudioPlayerWidget.wavesCount) (maxPosition / AudioPlayerWidget.wavesCount)
.round() * .round() *
i)), i,
),
),
child: Container( child: Container(
height: 32, height: 32,
alignment: Alignment.center, alignment: Alignment.center,
child: Opacity( child: Opacity(
opacity: currentPosition > i ? 1 : 0.5, opacity: currentPosition > i ? 1 : 0.5,
child: Container( child: Container(
margin: const EdgeInsets.symmetric(horizontal: 1), margin: const EdgeInsets.symmetric(horizontal: 1),
decoration: BoxDecoration( decoration: BoxDecoration(
color: widget.color, color: widget.color,
borderRadius: BorderRadius.circular(64), borderRadius: BorderRadius.circular(64),
), ),
height: 32 * (waveform[i] / 1024)), height: 32 * (waveform[i] / 1024),
),
), ),
), ),
), ),
@ -251,3 +265,22 @@ class AudioPlayerState extends State<AudioPlayerWidget> {
); );
} }
} }
/// To use a MatrixFile as an AudioSource for the just_audio package
class MatrixFileAudioSource extends StreamAudioSource {
final MatrixFile file;
MatrixFileAudioSource(this.file);
@override
Future<StreamAudioResponse> request([int? start, int? end]) async {
start ??= 0;
end ??= file.bytes.length;
return StreamAudioResponse(
sourceLength: file.bytes.length,
contentLength: end - start,
offset: start,
stream: Stream.value(file.bytes.sublist(start, end)),
contentType: file.mimeType,
);
}
}

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,32 +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 '../../../pages/image_viewer/image_viewer.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
@ -38,113 +35,470 @@ class HtmlMessage extends StatelessWidget {
// miss-matching tags, and this way we actually correctly identify what we want to strip and, well, // miss-matching tags, and this way we actually correctly identify what we want to strip and, well,
// strip it. // strip it.
final renderHtml = html.replaceAll( final renderHtml = html.replaceAll(
RegExp('<mx-reply>.*</mx-reply>', RegExp(
caseSensitive: false, multiLine: false, dotAll: true), '<mx-reply>.*</mx-reply>',
''); caseSensitive: false,
multiLine: false,
dotAll: true,
),
'',
);
final fontSize = AppConfig.messageFontSize * AppConfig.fontSizeFactor;
final linkifiedRenderHtml = linkify(
renderHtml,
options: const LinkifyOptions(humanize: false),
)
.map(
(element) {
if (element is! UrlElement ||
element.text.contains('<') ||
element.text.contains('>') ||
element.text.contains('"')) {
return element.text;
}
return '<a href="${element.url}">${element.text}</a>';
},
)
.join('')
.replaceAll('\n', '');
final linkColor = textColor.withAlpha(150);
// there is no need to pre-validate the html, as we validate it while rendering // there is no need to pre-validate the html, as we validate it while rendering
final matrix = Matrix.of(context);
final themeData = Theme.of(context);
return Html( return Html(
data: renderHtml, data: linkifiedRenderHtml,
defaultTextStyle: defaultTextStyle, style: {
emoteSize: emoteSize, '*': Style(
linkStyle: linkStyle ?? color: textColor,
themeData.textTheme.bodyMedium!.copyWith( margin: Margins.all(0),
color: themeData.colorScheme.secondary, fontSize: FontSize(fontSize),
decoration: TextDecoration.underline, ),
'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,
),
), ),
shrinkToFit: true, padding: HtmlPaddings.only(left: 6, bottom: 0),
maxLines: maxLines, ),
onLinkTap: (url) => UrlLauncher(context, url).launchUrl(), 'hr': Style(
onPillTap: (url) => UrlLauncher(context, url).launchUrl(), border: Border.all(color: textColor, width: 0.5),
getMxcUrl: (String mxc, double? width, double? height, ),
{bool? animated = false}) { 'table': Style(
final ratio = MediaQuery.of(context).devicePixelRatio; border: Border.all(color: textColor, width: 0.5),
return Uri.parse(mxc) ),
.getThumbnail( 'tr': Style(
matrix.client, border: Border.all(color: textColor, width: 0.5),
width: (width ?? 800) * ratio, ),
height: (height ?? 800) * ratio, 'td': Style(
method: ThumbnailMethod.scale, border: Border.all(color: textColor, width: 0.5),
animated: AppConfig.autoplayImages ? animated : false, padding: HtmlPaddings.all(2),
) ),
.toString(); 'th': Style(
border: Border.all(color: textColor, width: 0.5),
),
}, },
onImageTap: (String mxc) => showDialog( extensions: [
context: Matrix.of(context).navigatorContext, RoomPillExtension(context, room),
useRootNavigator: false, CodeExtension(fontSize: fontSize),
builder: (_) => ImageViewer(Event( MatrixMathExtension(
type: EventTypes.Message, style: TextStyle(fontSize: fontSize, color: textColor),
content: <String, dynamic>{ ),
'body': mxc, const TableHtmlExtension(),
'url': mxc, SpoilerExtension(textColor: textColor),
'msgtype': MessageTypes.Image, const ImageExtension(),
}, FontColorExtension(),
senderId: room.client.userID!, ],
originServerTs: DateTime.now(), onLinkTap: (url, _, __) => UrlLauncher(context, url).launchUrl(),
eventId: 'fake_event', onlyRenderTheseTags: const {
room: room))), ...allowedHtmlTags,
setCodeLanguage: (String key, String value) async { // Needed to make it work properly
await matrix.store.setItem('${SettingKeys.codeLanguage}.$key', value); 'body',
}, 'html',
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 {};
}
if (identifier.sigil == '!') {
// we have a room ID pill
final r = room.client.getRoomById(identifier);
if (r == null) {
return {};
}
return {
'displayname':
r.getLocalizedDisplayname(MatrixLocals(L10n.of(context)!)),
'avatar_url': r.getState('m.room.avatar')?.content['url'],
};
}
return {};
}, },
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,5 +1,6 @@
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:swipe_to_action/swipe_to_action.dart'; import 'package:swipe_to_action/swipe_to_action.dart';
@ -18,6 +19,7 @@ import 'verification_request_content.dart';
class Message extends StatelessWidget { class Message extends StatelessWidget {
final Event event; final Event event;
final Event? nextEvent; final Event? nextEvent;
final bool displayReadMarker;
final void Function(Event)? onSelect; final void Function(Event)? onSelect;
final void Function(Event)? onAvatarTab; final void Function(Event)? onAvatarTab;
final void Function(Event)? onInfoTab; final void Function(Event)? onInfoTab;
@ -27,18 +29,20 @@ class Message extends StatelessWidget {
final bool selected; final bool selected;
final Timeline timeline; final Timeline timeline;
const Message(this.event, const Message(
{this.nextEvent, this.event, {
this.longPressSelect = false, this.nextEvent,
this.onSelect, this.displayReadMarker = false,
this.onInfoTab, this.longPressSelect = false,
this.onAvatarTab, this.onSelect,
this.scrollToEventId, this.onInfoTab,
required this.onSwipe, this.onAvatarTab,
this.selected = false, this.scrollToEventId,
required this.timeline, required this.onSwipe,
Key? key}) this.selected = false,
: super(key: key); required this.timeline,
Key? key,
}) : super(key: key);
/// Indicates wheither the user may use a mouse instead /// Indicates wheither the user may use a mouse instead
/// of touchscreen. /// of touchscreen.
@ -53,7 +57,7 @@ class Message extends StatelessWidget {
EventTypes.CallInvite EventTypes.CallInvite
}.contains(event.type)) { }.contains(event.type)) {
if (event.type.startsWith('m.call.')) { if (event.type.startsWith('m.call.')) {
return Container(); return const SizedBox.shrink();
} }
return StateMessage(event); return StateMessage(event);
} }
@ -126,13 +130,15 @@ class Message extends StatelessWidget {
height: 16 * AppConfig.bubbleSizeFactor, height: 16 * AppConfig.bubbleSizeFactor,
child: event.status == EventStatus.sending child: event.status == EventStatus.sending
? const CircularProgressIndicator.adaptive( ? const CircularProgressIndicator.adaptive(
strokeWidth: 2) strokeWidth: 2,
)
: event.status == EventStatus.error : event.status == EventStatus.error
? const Icon(Icons.error, color: Colors.red) ? const Icon(Icons.error, color: Colors.red)
: null, : null,
), ),
), ),
)) ),
)
: FutureBuilder<User?>( : FutureBuilder<User?>(
future: event.fetchSenderUser(), future: event.fetchSenderUser(),
builder: (context, snapshot) { builder: (context, snapshot) {
@ -142,7 +148,8 @@ class Message extends StatelessWidget {
name: user.calcDisplayname(), name: user.calcDisplayname(),
onTap: () => onAvatarTab!(event), onTap: () => onAvatarTab!(event),
); );
}), },
),
Expanded( Expanded(
child: Column( child: Column(
crossAxisAlignment: CrossAxisAlignment.start, crossAxisAlignment: CrossAxisAlignment.start,
@ -171,7 +178,8 @@ class Message extends StatelessWidget {
: displayname.lightColorText), : displayname.lightColorText),
), ),
); );
}), },
),
), ),
Container( Container(
alignment: alignment, alignment: alignment,
@ -198,7 +206,8 @@ class Message extends StatelessWidget {
? EdgeInsets.zero ? EdgeInsets.zero
: EdgeInsets.all(16 * AppConfig.bubbleSizeFactor), : EdgeInsets.all(16 * AppConfig.bubbleSizeFactor),
constraints: const BoxConstraints( constraints: const BoxConstraints(
maxWidth: FluffyThemes.columnWidth * 1.5), maxWidth: FluffyThemes.columnWidth * 1.5,
),
child: Stack( child: Stack(
children: <Widget>[ children: <Widget>[
Column( Column(
@ -233,11 +242,14 @@ class Message extends StatelessWidget {
child: AbsorbPointer( child: AbsorbPointer(
child: Container( child: Container(
margin: EdgeInsets.symmetric( margin: EdgeInsets.symmetric(
vertical: 4.0 * vertical:
AppConfig.bubbleSizeFactor), 4.0 * AppConfig.bubbleSizeFactor,
child: ReplyContent(replyEvent, ),
ownMessage: ownMessage, child: ReplyContent(
timeline: timeline), replyEvent,
ownMessage: ownMessage,
timeline: timeline,
),
), ),
), ),
); );
@ -249,10 +261,13 @@ class Message extends StatelessWidget {
onInfoTab: onInfoTab, onInfoTab: onInfoTab,
), ),
if (event.hasAggregatedEvents( if (event.hasAggregatedEvents(
timeline, RelationshipTypes.edit)) timeline,
RelationshipTypes.edit,
))
Padding( Padding(
padding: EdgeInsets.only( padding: EdgeInsets.only(
top: 4.0 * AppConfig.bubbleSizeFactor), top: 4.0 * AppConfig.bubbleSizeFactor,
),
child: Row( child: Row(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
children: [ children: [
@ -291,7 +306,8 @@ class Message extends StatelessWidget {
Widget container; Widget container;
if (event.hasAggregatedEvents(timeline, RelationshipTypes.reaction) || if (event.hasAggregatedEvents(timeline, RelationshipTypes.reaction) ||
displayTime || displayTime ||
selected) { selected ||
displayReadMarker) {
container = Column( container = Column(
mainAxisSize: MainAxisSize.min, mainAxisSize: MainAxisSize.min,
crossAxisAlignment: crossAxisAlignment:
@ -301,26 +317,29 @@ class Message extends StatelessWidget {
Padding( Padding(
padding: displayTime padding: displayTime
? EdgeInsets.symmetric( ? EdgeInsets.symmetric(
vertical: 8.0 * AppConfig.bubbleSizeFactor) vertical: 8.0 * AppConfig.bubbleSizeFactor,
)
: EdgeInsets.zero, : EdgeInsets.zero,
child: Center( child: Center(
child: Material( child: Material(
color: displayTime color: displayTime
? Theme.of(context).colorScheme.background ? Theme.of(context).colorScheme.background
: Theme.of(context) : Theme.of(context)
.colorScheme .colorScheme
.background .background
.withOpacity(0.33), .withOpacity(0.33),
borderRadius: BorderRadius.circular(AppConfig.borderRadius / 2), borderRadius:
clipBehavior: Clip.antiAlias, BorderRadius.circular(AppConfig.borderRadius / 2),
child: Padding( clipBehavior: Clip.antiAlias,
padding: const EdgeInsets.all(6.0), child: Padding(
child: Text( padding: const EdgeInsets.all(6.0),
event.originServerTs.localizedTime(context), child: Text(
style: TextStyle(fontSize: 14 * AppConfig.fontSizeFactor), event.originServerTs.localizedTime(context),
style: TextStyle(fontSize: 14 * AppConfig.fontSizeFactor),
),
), ),
), ),
)), ),
), ),
row, row,
if (event.hasAggregatedEvents(timeline, RelationshipTypes.reaction)) if (event.hasAggregatedEvents(timeline, RelationshipTypes.reaction))
@ -332,6 +351,35 @@ class Message extends StatelessWidget {
), ),
child: MessageReactions(event, timeline), child: MessageReactions(event, timeline),
), ),
if (displayReadMarker)
Row(
children: [
Expanded(
child: Divider(color: Theme.of(context).colorScheme.primary),
),
Container(
decoration: BoxDecoration(
border: Border.all(
color: Theme.of(context).colorScheme.primary,
),
color: Theme.of(context).colorScheme.primaryContainer,
borderRadius: BorderRadius.circular(4),
),
margin: const EdgeInsets.all(8.0),
padding: const EdgeInsets.symmetric(
horizontal: 8,
),
child: Text(
L10n.of(context)!.readUpToHere,
style:
TextStyle(color: Theme.of(context).colorScheme.primary),
),
),
Expanded(
child: Divider(color: Theme.of(context).colorScheme.primary),
),
],
),
], ],
); );
} else { } else {

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';
@ -27,21 +27,27 @@ class MessageContent extends StatelessWidget {
final Color textColor; final Color textColor;
final void Function(Event)? onInfoTab; final void Function(Event)? onInfoTab;
const MessageContent(this.event, const MessageContent(
{this.onInfoTab, Key? key, required this.textColor}) this.event, {
: super(key: key); this.onInfoTab,
Key? key,
required this.textColor,
}) : super(key: key);
void _verifyOrRequestKey(BuildContext context) async { void _verifyOrRequestKey(BuildContext context) async {
final l10n = L10n.of(context)!; final l10n = L10n.of(context)!;
if (event.content['can_request_session'] != true) { if (event.content['can_request_session'] != true) {
ScaffoldMessenger.of(context).showSnackBar(SnackBar( ScaffoldMessenger.of(context).showSnackBar(
SnackBar(
content: Text( content: Text(
event.type == EventTypes.Encrypted event.type == EventTypes.Encrypted
? l10n.needPantalaimonWarning ? l10n.needPantalaimonWarning
: event.calcLocalizedBodyFallback( : event.calcLocalizedBodyFallback(
MatrixLocals(l10n), MatrixLocals(l10n),
), ),
))); ),
),
);
return; return;
} }
final client = Matrix.of(context).client; final client = Matrix.of(context).client;
@ -113,11 +119,12 @@ class MessageContent extends StatelessWidget {
case CuteEventContent.eventType: case CuteEventContent.eventType:
return CuteContent(event); return CuteContent(event);
case MessageTypes.Audio: case MessageTypes.Audio:
if (PlatformInfos.isMobile || PlatformInfos.isMacOS if (PlatformInfos.isMobile ||
// || latformInfos.isLinux PlatformInfos.isMacOS ||
// disabled until PlatformInfos.isWeb
// https://github.com/bleonard252/just_audio_mpv/issues/3 is // Disabled until https://github.com/bleonard252/just_audio_mpv/issues/3
// fixed // is fixed
// || PlatformInfos.isLinux
) { ) {
return AudioPlayerWidget( return AudioPlayerWidget(
event, event,
@ -143,22 +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,
),
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
@ -211,72 +206,84 @@ class MessageContent extends StatelessWidget {
default: default:
if (event.redacted) { if (event.redacted) {
return FutureBuilder<User?>( return FutureBuilder<User?>(
future: event.redactedBecause?.fetchSenderUser(), future: event.redactedBecause?.fetchSenderUser(),
builder: (context, snapshot) { builder: (context, snapshot) {
return _ButtonContent( return _ButtonContent(
label: L10n.of(context)!.redactedAnEvent(snapshot.data label: L10n.of(context)!.redactedAnEvent(
?.calcDisplayname() ?? snapshot.data?.calcDisplayname() ??
event.senderFromMemoryOrFallback.calcDisplayname()), event.senderFromMemoryOrFallback.calcDisplayname(),
icon: const Icon(Icons.delete_outlined), ),
textColor: buttonTextColor, icon: const Icon(Icons.delete_outlined),
onPressed: () => onInfoTab!(event), textColor: buttonTextColor,
); onPressed: () => onInfoTab!(event),
}); );
},
);
} }
final bigEmotes = event.onlyEmotes && final bigEmotes = event.onlyEmotes &&
event.numberEmotes > 0 && event.numberEmotes > 0 &&
event.numberEmotes <= 10; event.numberEmotes <= 10;
return FutureBuilder<String>( return FutureBuilder<String>(
future: event.calcLocalizedBody(MatrixLocals(L10n.of(context)!), future: event.calcLocalizedBody(
hideReply: true), MatrixLocals(L10n.of(context)!),
builder: (context, snapshot) { hideReply: true,
return LinkText( ),
text: snapshot.data ?? builder: (context, snapshot) {
event.calcLocalizedBodyFallback( return Linkify(
MatrixLocals(L10n.of(context)!), text: snapshot.data ??
hideReply: true), event.calcLocalizedBodyFallback(
textStyle: TextStyle( MatrixLocals(L10n.of(context)!),
color: textColor, hideReply: true,
fontSize: bigEmotes ? fontSize * 3 : fontSize, ),
decoration: style: TextStyle(
event.redacted ? TextDecoration.lineThrough : null, color: textColor,
), fontSize: bigEmotes ? fontSize * 3 : fontSize,
linkStyle: TextStyle( decoration:
color: textColor.withAlpha(150), event.redacted ? TextDecoration.lineThrough : null,
fontSize: bigEmotes ? fontSize * 3 : fontSize, ),
decoration: TextDecoration.underline, options: const LinkifyOptions(humanize: false),
), linkStyle: TextStyle(
onLinkTap: (url) => UrlLauncher(context, url).launchUrl(), color: textColor.withAlpha(150),
); fontSize: bigEmotes ? fontSize * 3 : fontSize,
}); decoration: TextDecoration.underline,
decorationColor: textColor.withAlpha(150),
),
onOpen: (url) => UrlLauncher(context, url.url).launchUrl(),
);
},
);
} }
case EventTypes.CallInvite: case EventTypes.CallInvite:
return FutureBuilder<User?>( return FutureBuilder<User?>(
future: event.fetchSenderUser(), future: event.fetchSenderUser(),
builder: (context, snapshot) { builder: (context, snapshot) {
return _ButtonContent( return _ButtonContent(
label: L10n.of(context)!.startedACall( label: L10n.of(context)!.startedACall(
snapshot.data?.calcDisplayname() ?? snapshot.data?.calcDisplayname() ??
event.senderFromMemoryOrFallback.calcDisplayname()), event.senderFromMemoryOrFallback.calcDisplayname(),
icon: const Icon(Icons.phone_outlined), ),
textColor: buttonTextColor, icon: const Icon(Icons.phone_outlined),
onPressed: () => onInfoTab!(event), textColor: buttonTextColor,
); onPressed: () => onInfoTab!(event),
}); );
},
);
default: default:
return FutureBuilder<User?>( return FutureBuilder<User?>(
future: event.fetchSenderUser(), future: event.fetchSenderUser(),
builder: (context, snapshot) { builder: (context, snapshot) {
return _ButtonContent( return _ButtonContent(
label: L10n.of(context)!.userSentUnknownEvent( label: L10n.of(context)!.userSentUnknownEvent(
snapshot.data?.calcDisplayname() ?? snapshot.data?.calcDisplayname() ??
event.senderFromMemoryOrFallback.calcDisplayname(), event.senderFromMemoryOrFallback.calcDisplayname(),
event.type), event.type,
icon: const Icon(Icons.info_outlined), ),
textColor: buttonTextColor, icon: const Icon(Icons.info_outlined),
onPressed: () => onInfoTab!(event), textColor: buttonTextColor,
); onPressed: () => onInfoTab!(event),
}); );
},
);
} }
} }
} }

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,
), ),
), )
], ],
), ),
), ),

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