Compare commits

...

106 Commits

Author SHA1 Message Date
Evgeny Poberezkin 4947cf2c0c Merge branch 'master' into av/android-lint 2023-08-10 19:15:56 +01:00
Evgeny Poberezkin 18041ae471 mobile: translations (#2884)
* Translated using Weblate (Dutch)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/nl/

* Translated using Weblate (Arabic)

Currently translated at 62.7% (831 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Arabic)

Currently translated at 62.7% (831 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Arabic)

Currently translated at 71.9% (953 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/es/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/nl/

* Translated using Weblate (Korean)

Currently translated at 71.2% (943 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ko/

* Translated using Weblate (German)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (German)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/de/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/es/

* Translated using Weblate (Czech)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/cs/

* Translated using Weblate (Czech)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/cs/

* Translated using Weblate (Arabic)

Currently translated at 77.3% (1024 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Arabic)

Currently translated at 82.1% (1088 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Hebrew)

Currently translated at 100.0% (1324 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/he/

* Translated using Weblate (Hebrew)

Currently translated at 43.4% (528 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/he/

* Translated using Weblate (Turkish)

Currently translated at 53.4% (708 of 1324 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (German)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (French)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Arabic)

Currently translated at 86.7% (1150 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Italian)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Turkish)

Currently translated at 1.3% (17 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/tr/

* Translated using Weblate (Turkish)

Currently translated at 53.4% (708 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (Arabic)

Currently translated at 87.2% (1156 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Thai)

Currently translated at 94.7% (1152 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/th/

* Translated using Weblate (Thai)

Currently translated at 95.7% (1269 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/th/

* Translated using Weblate (German)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (French)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/

* Translated using Weblate (French)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fr/

* Translated using Weblate (Italian)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/

* Translated using Weblate (Japanese)

Currently translated at 99.6% (1321 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ja/

* Translated using Weblate (Czech)

Currently translated at 100.0% (1325 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/cs/

* Translated using Weblate (Arabic)

Currently translated at 99.8% (1323 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Arabic)

Currently translated at 3.7% (46 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/ar/

* Translated using Weblate (Thai)

Currently translated at 94.7% (1152 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/th/

* Translated using Weblate (Thai)

Currently translated at 95.7% (1269 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/th/

* Translated using Weblate (Bulgarian)

Currently translated at 43.9% (582 of 1325 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Italian)

Currently translated at 100.0% (1326 of 1326 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Bulgarian)

Currently translated at 45.7% (607 of 1326 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Bulgarian)

Currently translated at 46.9% (623 of 1326 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Bulgarian)

Currently translated at 47.5% (631 of 1326 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Bulgarian)

Currently translated at 53.2% (706 of 1326 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Bulgarian)

Currently translated at 59.3% (787 of 1326 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Polish)

Currently translated at 100.0% (1328 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pl/

* Translated using Weblate (Bulgarian)

Currently translated at 76.3% (1014 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Turkish)

Currently translated at 5.3% (65 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/tr/

* Translated using Weblate (Turkish)

Currently translated at 7.4% (90 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/tr/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (1328 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/

* Translated using Weblate (Italian)

Currently translated at 100.0% (1328 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Turkish)

Currently translated at 58.2% (773 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (Turkish)

Currently translated at 58.2% (774 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (Turkish)

Currently translated at 7.5% (92 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/tr/

* Translated using Weblate (Turkish)

Currently translated at 63.9% (849 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1328 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Finnish)

Currently translated at 94.2% (1252 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fi/

* Translated using Weblate (Finnish)

Currently translated at 19.9% (242 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/fi/

* Translated using Weblate (Turkish)

Currently translated at 68.5% (910 of 1328 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (Polish)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pl/

* Translated using Weblate (German)

Currently translated at 99.5% (1350 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (French)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/

* Translated using Weblate (Italian)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Turkish)

Currently translated at 70.2% (953 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (German)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (Bulgarian)

Currently translated at 85.9% (1165 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Bulgarian)

Currently translated at 90.2% (1224 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Arabic)

Currently translated at 99.7% (1353 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Thai)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/th/

* Translated using Weblate (Thai)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/th/

* Translated using Weblate (Bulgarian)

Currently translated at 1.0% (13 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/bg/

* Translated using Weblate (Bulgarian)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (Turkish)

Currently translated at 70.3% (954 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (1356 of 1356 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/

* Translated using Weblate (Dutch)

Currently translated at 100.0% (1216 of 1216 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/nl/

* Translated using Weblate (Italian)

Currently translated at 100.0% (1358 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/

* Translated using Weblate (Arabic)

Currently translated at 99.7% (1355 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/

* Translated using Weblate (Polish)

Currently translated at 100.0% (1358 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/pl/

* Translated using Weblate (Spanish)

Currently translated at 100.0% (1358 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/es/

* Translated using Weblate (German)

Currently translated at 100.0% (1358 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/de/

* Translated using Weblate (French)

Currently translated at 100.0% (1358 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fr/

* Translated using Weblate (Turkish)

Currently translated at 77.2% (1049 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/

* Translated using Weblate (Dutch)

Currently translated at 99.9% (1357 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/

* Translated using Weblate (Lithuanian)

Currently translated at 45.4% (617 of 1358 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/lt/

* export localizations

* update text

* fix German translations

* revert change in French

* remove "read" receipts translations in Japanese

* remove "read" receipts from Japanese

* revert French translations

* import/export localizations

---------

Co-authored-by: John m <jvanmanen@gmail.com>
Co-authored-by: Mosaab Emam <mosaab.emam123@gmail.com>
Co-authored-by: jonnysemon <jonnysemon@users.noreply.hosted.weblate.org>
Co-authored-by: khalidbelk <khalid.belkassmi-el-hafi@epitech.eu>
Co-authored-by: No name <CertainBot@users.noreply.hosted.weblate.org>
Co-authored-by: fxxk3rrth4ng <baech00@kakao.com>
Co-authored-by: mlanp <github@lang.xyz>
Co-authored-by: zenobit <zen@osowoso.xyz>
Co-authored-by: ItaiShek <itaishek@gmail.com>
Co-authored-by: p1ns <dnzkckali@gmail.com>
Co-authored-by: random r <epsilin@yopmail.com>
Co-authored-by: Titapa (PunPun) Chaiyakiturajai <titapapunne@gmail.com>
Co-authored-by: Pixelcode <pixelcode@dismail.de>
Co-authored-by: Ophiushi <41908476+ishi-sama@users.noreply.github.com>
Co-authored-by: Y. Sakamoto <ysakamoto@tutanota.com>
Co-authored-by: elgratea <weblate@fastmail.com>
Co-authored-by: B.O.S.S <BxOxSxS@protonmail.com>
Co-authored-by: Dennis <snap-roofing0h@icloud.com>
Co-authored-by: petri <pkajander@gmail.com>
Co-authored-by: 0xMarius <tech@marmakas.lt>
2023-08-10 17:59:42 +01:00
spaced4ndy de3fdde2f6 docs: create groups without establishing direct connections RFC (#2890) 2023-08-10 20:33:11 +04:00
spaced4ndy 0cf2af916b docs: contact-groups rfc (#2775) 2023-08-10 20:32:18 +04:00
Evgeny Poberezkin 2ab938db60 mobile: remove item status alerts (#2883) 2023-08-09 22:38:18 +01:00
Stanislav Dmitrenko 9543af4784 android: workaround of system restricted background (#2873)
* android: workaround of system restricted background

* strings

* exclude lockscreen call from requirements to unrestrict

* texts

* added button and changed behaviour

* texts 2

* button instead of alert

* padding

* bigger padding

* refactor

* don't jump on button hide

* no exceptions for lockscreen

* sometimes do not show off alert

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-09 19:56:53 +01:00
Evgeny Poberezkin 38dc14f041 core: update simplexmq (revert DB busy error handling) 2023-08-09 16:45:31 +01:00
Avently 2e205b055d android: lint & gradle issues 2023-08-08 23:33:51 +07:00
Evgeny Poberezkin 5353b466a9 directory: remove welcome when contact joins via group, member count in approval, chat commands via bot (#2872)
* directory: remove welcome when contact joins via group, member count in approval, chat commands via bot

* disable bot tests

* rename command
2023-08-08 16:06:56 +01:00
Stanislav Dmitrenko b28a51106f desktop: small fix to AppImage action (#2862) 2023-08-08 15:56:08 +01:00
spaced4ndy b095c09283 android: rework incognito mode - choose when making connection (#2867)
* android: rework incognito mode - choose when making connection

* remove commented code

* remove commented code

* change text

* text editor border

* smaller qr code

* chat preview height

* fix spacing

* desktop dialogue

* remove import

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-08 17:28:18 +04:00
spaced4ndy 1a567c88db ios: rework incognito mode - choose when making connection (#2851)
* wip

* layout

* more layout

* fix focus

* show incognito

* change icon layout

* remove presentation detents

* smaller button icon

* bigger icon

* show incognito profile status in connection info, layout, icons

* fix some lint warnings, update labels, add incognito label, conditionally hide toolbar to avoid jumping on iOS 17

* remove ignored color

* s/incognitoEnabled/incognito/

* shorter text

* remove parameter label

* restore note when creating a group

* add incognito icon to pending connections

* refactor

* refactor chat list action sheet

* revert to using new value in onChange

* remove unused variable

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-08 17:26:56 +04:00
spaced4ndy d80ee14f77 Revert "Revert "core: rework incognito mode - set per connection (#2838)""
This reverts commit b003d659e4.
2023-08-08 17:25:28 +04:00
Evgeny Poberezkin b374b5b753 Merge branch 'stable' 2023-08-07 21:04:33 +01:00
Evgeny Poberezkin 34c5658560 Merge pull request #2854 from simplex-chat/directory-service
SimpleX Directory Service
2023-08-07 12:49:30 +01:00
Evgeny Poberezkin 53662ef077 directory: store log (#2863)
* directory: store log

* store log test (fails)

* fix store log
2023-08-07 08:25:15 +01:00
Evgeny Poberezkin 4826a62d36 directory: list groups with group member counts (#2855)
* directory: list groups with group member counts

* list groups, test

* superuser can list all groups

* rename command

* remove type synonym

* add member count to search results

* fix test
2023-08-06 11:56:40 +01:00
Evgeny Poberezkin 8cd362eed8 5.3-beta.3: android 141, ios 164, desktop 1.1.0 2023-08-05 22:24:02 +01:00
Evgeny Poberezkin b7ac1b1b55 core: 5.3.0.2 2023-08-05 15:15:53 +01:00
Stanislav Dmitrenko 5952fd5290 desktop: font for emoji (#2853)
* desktop: font for emoji

* heart emoji for Mac

* limit font size

* alignment

* padding

* emoji item layout

* padding on desktop

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-04 22:28:09 +01:00
Stanislav Dmitrenko 353fe4539c desktop: package name for Mac (#2857)
* desktop: package name for Mac

* added Windows
2023-08-04 21:29:25 +01:00
Evgeny Poberezkin b003d659e4 Revert "core: rework incognito mode - set per connection (#2838)"
This reverts commit 4e27a4ea4f.
2023-08-04 16:55:55 +01:00
Evgeny Poberezkin 8f72328136 directory: delist/relist groups when service or owner roles change (#2844)
* directory: delist/relist groups when service or owner roles change

* test role changes

* correction

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* directory: suspend and resume group listing (#2848)

* directory: suspend and resume group listing

* correction

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-08-04 09:23:16 +01:00
Stanislav Dmitrenko 6d113ae2e2 multiplatform: limit link preview width (#2847) 2023-08-03 16:40:29 +01:00
Stanislav Dmitrenko f264470e14 desktop: fix saving files and images (#2846) 2023-08-03 16:34:35 +01:00
Stanislav Dmitrenko 65391756ef desktop: files Drag & Drop support (#2843)
* desktop: files Drag&Drop support

* reduce diff

* move

* move 2

* move 3

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-03 16:24:43 +01:00
spaced4ndy 4e27a4ea4f core: rework incognito mode - set per connection (#2838) 2023-08-03 17:41:23 +04:00
Stanislav Dmitrenko b23b109b00 desktop: fixed shift+enter (#2842) 2023-08-03 12:04:26 +01:00
spaced4ndy 8bf830ced9 android: don't show file cancelled error alerts for automatically received files (#2818) 2023-08-03 14:26:23 +04:00
spaced4ndy 80a77a1104 ios: change logic of not showing alerts on file auto-receive - only don't show on file cancelled errors (#2833) 2023-08-03 14:25:56 +04:00
Stanislav Dmitrenko 760282cdfd desktop: edit previous message with Up arrow (#2841) 2023-08-03 10:32:01 +01:00
Evgeny Poberezkin 497275646d directory: registration of duplicate groups (#2840)
* directory: confirm registration of duplicate groups

* do not send duplicate groups for approval

* add test
2023-08-03 09:21:48 +01:00
Stanislav Dmitrenko 105a6afb4b ci: Github Action to build desktop app binaries (#2814)
* desktop: Github Action for desktop

* only on tag

* AppImage support
2023-08-02 22:45:58 +01:00
Stanislav Dmitrenko 061125ab63 desktop: AppImage support (#2839) 2023-08-02 22:30:24 +01:00
Stanislav Dmitrenko 2f10633d1d multiplatform: update compose version (#2835)
* multiplatform: update compose version

* Revert "desktop: fix freeze in some situations (#2820)"

This reverts commit 6268f0a32b.

* Revert "desktop: prevent deadlock (#2785)"

This reverts commit d77980e50e.

* restore debug commands in comments

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-02 17:20:15 +01:00
Evgeny Poberezkin e2d5ad0e48 Merge branch 'master' into directory-service 2023-08-02 16:25:56 +01:00
Evgeny Poberezkin e34a8ef719 Merge branch 'stable' 2023-08-02 16:23:17 +01:00
spaced4ndy 2bb2042d7d ios, android: alert on connect via member address button (#2819)
* ios: alert on connect via member address button

* android

* Update apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>

* Update apps/multiplatform/common/src/commonMain/resources/MR/base/strings.xml

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>

* ios texts

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-02 12:10:11 +04:00
spaced4ndy 0a6133fe5b ios: update error types (#2821) 2023-08-02 11:10:29 +04:00
spaced4ndy a4a6e2418a android: update error types (#2827) 2023-08-02 11:09:54 +04:00
Evgeny Poberezkin 2b69103055 SimpleX Directory Service (#2766)
* SimpleX Directory Service

* more events

* update events

* fix

* Apply suggestions from code review

metavar

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* metavar 2

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>

* process events

* remove command serialization

* update

* update

* process group profile update

* basic group registration flow

* search works

* better messages

* improve messages

* test broadcast bot

* test for directory service

* better processing of group profile change, test

* refactor

* de-list group when owner or service is removed from the group, tests

* fix: removing any member or any member leaving should not delist the group

* refactor

* more tests, fixes

* disable bot tests in CI

* remove comment

---------

Co-authored-by: spaced4ndy <8711996+spaced4ndy@users.noreply.github.com>
2023-08-01 20:54:51 +01:00
spaced4ndy 7344398826 ios: don't show error alerts for automatically received files (#2813) 2023-08-01 18:18:14 +04:00
Stanislav Dmitrenko 7f662ec7cc desktop: theme detector try-catch (#2817) 2023-08-01 15:08:04 +01:00
Stanislav Dmitrenko 298dd9744f desktop: include more libs for copying (#2823)
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-08-01 15:07:10 +01:00
Stanislav Dmitrenko 6268f0a32b desktop: fix freeze in some situations (#2820)
* desktop: fix freeze in some situations

* old fashion

* small change
2023-08-01 14:58:26 +01:00
Evgeny Poberezkin f0d64a30e9 5.3-beta.2: ios 163, android 140, desktop 1.0.1 (#2812) 2023-07-31 17:57:56 +01:00
Evgeny Poberezkin d08df4cfbf core: 5.3.0.1 2023-07-31 16:13:19 +01:00
Evgeny Poberezkin 8e84b9e85f Merge branch 'stable' 2023-07-31 16:02:01 +01:00
spaced4ndy c935e8aff3 core: fix status parsing 2 (#2809) 2023-07-31 15:52:42 +01:00
spaced4ndy a0a567f5f7 core: fix status parsing (#2807) 2023-07-31 15:52:02 +01:00
spaced4ndy ddd97baf5a core: 5.2.1.0 2023-07-31 15:49:53 +01:00
spaced4ndy 98e68c8e74 core: read unparsable item status as unknown (#2805) 2023-07-31 15:46:31 +01:00
Evgeny Poberezkin 03edde18eb core: update preset smp relays (#2804) 2023-07-31 15:19:28 +01:00
Stanislav Dmitrenko 8e7e5209d3 desktop: include openssl lib on Mac (#2810) 2023-07-31 13:46:00 +01:00
Evgeny Poberezkin 631dfff5e9 Merge branch 'stable' 2023-07-29 16:54:50 +01:00
M. Sarmad Qadeer f69c842ba6 website: simplex explained graphics animation (#2713)
* website: animate simplex explained graphics

* website: update simplex network animation

* website: add lottie.min.js through node_modules

* website: update lottie.min.js copy command location
2023-07-29 14:20:51 +01:00
Evgeny Poberezkin 18c802159b android: build 138 2023-07-28 22:58:03 +01:00
Stanislav Dmitrenko 45e557fd80 android: make tmpDir (#2797) 2023-07-28 22:57:06 +01:00
Evgeny Poberezkin d50562cfee 5.3-beta.1: Android 137 2023-07-28 20:11:04 +01:00
Stanislav Dmitrenko 15d3d3b11a desktop: encoding utf8 (#2795)
* desktop: encoding utf8

* rename functions

* logs
2023-07-28 19:38:31 +01:00
Stanislav Dmitrenko 2b715a0d8c desktop: notifications support (#2754)
* desktop: notifications support

* adapted external lib for interacting with notificatioins

* disabled some functions
2023-07-28 19:01:08 +01:00
Stanislav Dmitrenko 02d00944ff desktop: fix creating tmpDir and providing name for file to save (#2789)
* desktop: creating tmpDir

* provide name for saved file

* directories only selection on Mac

* specified filename for file savers

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-28 17:57:48 +01:00
spaced4ndy 71d6410604 5.3-beta.0: iOS 161, Android 136 2023-07-28 14:11:39 +04:00
spaced4ndy 141611293f android: group snd status (#2784) 2023-07-28 13:25:39 +04:00
spaced4ndy c9400fe932 ios: group snd status (#2779) 2023-07-28 13:16:52 +04:00
spaced4ndy 445a8e75fe 5.3.0.0 2023-07-28 11:09:14 +04:00
Stanislav Dmitrenko 9d30a3495e multiplatform: open SimpleX links inside the app (#2778)
* multiplatform: open SimpleX links inside the app

* one more place

* exclude via browser links
2023-07-27 20:21:53 +01:00
Stanislav Dmitrenko d77980e50e desktop: prevent deadlock (#2785)
* desktop: prevent deadlock

* debug info
2023-07-27 15:59:06 +01:00
Stanislav Dmitrenko bb02f07370 desktop: distribution changes (#2782)
* desktop: distribution

* icons update

* package name

* windows

* icons

* package name

* Update apps/multiplatform/desktop/build.gradle.kts

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-27 15:58:24 +01:00
Stanislav Dmitrenko a3cd7ca89e desktop: enter + shift+enter keybindings (#2787) 2023-07-27 13:44:35 +01:00
Stanislav Dmitrenko 976fc68cc3 desktop: parsing html into annotated string (#2786) 2023-07-27 12:33:04 +01:00
Stanislav Dmitrenko 7c7e931aa9 desktop: bound long click to right click too (#2783)
* desktop: bound long click to right click too

* changes
2023-07-27 09:57:21 +01:00
Stanislav Dmitrenko e8e619effa desktop: small fixes in initial setup (#2781)
* desktop: small fixes in initial setup

* small changes

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-27 08:47:11 +01:00
Stanislav Dmitrenko bd0139eaab desktop: Linux lib path (#2780) 2023-07-26 20:13:06 +01:00
Stanislav Dmitrenko e9f77e1064 desktop: development alerts (#2777)
* desktop: development alerts

* strings

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-26 14:31:21 +01:00
Stanislav Dmitrenko 677b75f368 multiplatform: possible race in ChatList (#2757)
* multiplatform: possible race in ChatList

* more changes

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-26 13:27:54 +01:00
Stanislav Dmitrenko 92d13591f3 desktop: change libs path (#2776)
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-26 12:44:33 +01:00
Stanislav Dmitrenko 6be8476f90 desktop: decoding utf8 (#2774) 2023-07-26 12:38:49 +01:00
spaced4ndy ae9b83515c core: group snd status (#2763)
* core: group snd status

* schema, implementation

* refactor direct, tests

* configure, tests

* item info

* refactor

* refactor

* remove do

* rename

* remove receipts on events

* refactor

* refactor

* refactor

* refactor

* tests

* rename tests

* aggregates

* fix name

* refactor

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-26 14:49:35 +04:00
Stanislav Dmitrenko 26a233ab1a desktop: adapted UI (#2755)
* desktop: adapted UI

* more changes

* divider fix

* do not close screens on non-desktop in terminal view

* background click to close views and small changes

* dark theme detection on supported OSes

* fix text color after theme change

* placement of desktop text field

* marked as @Composable

* padding of text view

* window sizes

* screen layout

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-26 09:35:29 +01:00
Evgeny Poberezkin c7783a7039 Merge branch 'stable' 2023-07-22 20:09:03 +01:00
Evgeny Poberezkin 0c34a545fa Merge branch 'stable' 2023-07-22 16:27:37 +01:00
Evgeny Poberezkin 1d4afe591e Merge pull request #2750 from simplex-chat/ep/move-prefs
core: split preferences to separate file
2023-07-22 11:41:30 +01:00
Evgeny Poberezkin 10ec3dd8b6 Merge pull request #2746 from simplex-chat/multiplatform
desktop (multiplatform) app 🚀
2023-07-21 21:34:05 +01:00
Evgeny Poberezkin a715e847ad core: split preferences to separate file 2023-07-21 21:32:28 +01:00
Evgeny Poberezkin 9ac0f30c5a Merge branch 'master' into multiplatform 2023-07-21 13:12:05 +01:00
Evgeny Poberezkin 7996194f92 Merge pull request #2741 from simplex-chat/av/multiplatform-merge-master
multiplatform: merged master
2023-07-21 13:06:43 +01:00
Avently c2054b5ccf Merge branch 'master' into av/multiplatform-merge-master 2023-07-21 15:47:51 +07:00
Avently 1cb500bc16 Merge branch 'master' into av/multiplatform-merge-master 2023-07-20 20:43:35 +07:00
Avently f5825d20e4 follow up 2023-07-20 20:43:17 +07:00
Avently 77d249cc37 Merge branch 'master' into av/multiplatform-merge-master 2023-07-20 20:35:08 +07:00
Avently 3f905f59df Merge branch 'master' into av/multiplatform-merge-master 2023-07-20 20:30:12 +07:00
Stanislav Dmitrenko 27f4661ac4 desktop: send images and files (#2691)
* desktop: send images and files

* expect/actual

* file filter on non-Linux OSes

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-19 10:26:37 +01:00
Stanislav Dmitrenko 2389e870b3 desktop: do not show scan QR code screen (#2686)
* desktop: do not show scan QR code screen

* expect/actual and different button text

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-19 09:36:42 +01:00
Stanislav Dmitrenko d61ff0f2a7 desktop: expanded dropdown menu (#2687)
Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-18 22:52:18 +01:00
spaced4ndy f5d61e7838 Merge pull request #2694 from simplex-chat/av/multiplatform-merged-master2
multiplatform: merged master
2023-07-14 17:52:43 +04:00
spaced4ndy e762923410 Merge pull request #2685 from simplex-chat/av/multiplatform-merged-master
multiplatform: merged master
2023-07-14 17:40:41 +04:00
spaced4ndy d87b86199c Merge branch 'multiplatform' into av/multiplatform-merged-master 2023-07-14 17:29:04 +04:00
Stanislav Dmitrenko a7a66c2b55 multiplatform: adjusted database export path (#2698) 2023-07-14 17:28:13 +04:00
Avently f970ef264a Merge branch 'master' into av/multiplatform-merged-master2 2023-07-14 18:23:21 +07:00
Evgeny Poberezkin 3793cd138e Merge branch 'multiplatform' into av/multiplatform-merged-master 2023-07-14 12:01:48 +01:00
Stanislav Dmitrenko 8dd90733b8 multiplatform: default files and directories were changed (#2683)
* multiplatform: default files and directories were changed

* changes in paths and location of declaration

* more renames

* different paths

* update linux paths

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-14 12:00:37 +01:00
Stanislav Dmitrenko 0bdd96ae8a multiplatform: scripts for building the lib (#2682)
* multiplatform: scripts for building the lib

* refactor mac script

* fix path

* changes in Linux script

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-13 11:02:38 +01:00
Avently dd62b1cccb Merge branch 'master' into av/multiplatform-merged-master 2023-07-12 22:43:57 +07:00
Stanislav Dmitrenko 38f40fec3d multiplatform: split common/android/desktop (#2672)
* multiplatform: relocated code to its new place

* code becomes better

* renamed file

* fixes for BASE64 and images, and changes for appFileUri

* different Base64 for both platforms

* fix file saving on long click

* platformCallbacks refactoring

* renamed callbacks to platform

* eol

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-12 14:42:10 +01:00
Stanislav Dmitrenko ff7c22e114 multiplatform: divided files in pieces (#2664)
* multiplatform: divided files in pieces

* whitespace

* whitespace 2

---------

Co-authored-by: Evgeny Poberezkin <2769109+epoberezkin@users.noreply.github.com>
2023-07-07 11:44:22 +01:00
437 changed files with 19985 additions and 8515 deletions
+75 -4
View File
@@ -52,15 +52,19 @@ jobs:
- os: ubuntu-20.04
cache_path: ~/.cabal/store
asset_name: simplex-chat-ubuntu-20_04-x86-64
desktop_asset_name: simplex-desktop-ubuntu-20_04-x86_64.deb
- os: ubuntu-22.04
cache_path: ~/.cabal/store
asset_name: simplex-chat-ubuntu-22_04-x86-64
desktop_asset_name: simplex-desktop-ubuntu-22_04-x86_64.deb
- os: macos-latest
cache_path: ~/.cabal/store
asset_name: simplex-chat-macos-x86-64
desktop_asset_name: simplex-desktop-macos-x86_64.dmg
- os: windows-latest
cache_path: C:/cabal
asset_name: simplex-chat-windows-x86-64
desktop_asset_name: simplex-desktop-windows-x86_64.msi
steps:
- name: Configure pagefile (Windows)
if: matrix.os == 'windows-latest'
@@ -99,6 +103,10 @@ jobs:
echo " extra-lib-dirs: /usr/local/opt/openssl@1.1/lib" >> cabal.project.local
echo " flags: +openssl" >> cabal.project.local
- name: Install AppImage dependencies
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
run: sudo apt install -y desktop-file-utils
- name: Install pkg-config for Mac
if: matrix.os == 'macos-latest'
run: brew install pkg-config
@@ -111,23 +119,86 @@ jobs:
echo "package direct-sqlcipher" >> cabal.project.local
echo " flags: +openssl" >> cabal.project.local
- name: Unix build
id: unix_build
- name: Unix build CLI
id: unix_cli_build
if: matrix.os != 'windows-latest'
shell: bash
run: |
cabal build --enable-tests
echo "::set-output name=bin_path::$(cabal list-bin simplex-chat)"
- name: Unix upload binary to release
- name: Unix upload CLI binary to release
if: startsWith(github.ref, 'refs/tags/v') && matrix.os != 'windows-latest'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.unix_build.outputs.bin_path }}
file: ${{ steps.unix_cli_build.outputs.bin_path }}
asset_name: ${{ matrix.asset_name }}
tag: ${{ github.ref }}
- name: Setup Java
if: startsWith(github.ref, 'refs/tags/v')
uses: actions/setup-java@v3
with:
distribution: 'corretto'
java-version: '17'
cache: 'gradle'
- name: Linux build desktop
id: linux_desktop_build
if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
shell: bash
run: |
scripts/desktop/build-lib-linux.sh
cd apps/multiplatform
./gradlew packageDeb
echo "::set-output name=package_path::$(echo $PWD/release/main/deb/simplex_*_amd64.deb)"
- name: Linux make AppImage
id: linux_appimage_build
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
shell: bash
run: |
scripts/desktop/make-appimage-linux.sh
echo "::set-output name=appimage_path::$(echo $PWD/apps/multiplatform/release/main/*imple*.AppImage)"
- name: Mac build desktop
id: mac_desktop_build
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'macos-latest'
shell: bash
run: |
scripts/desktop/build-lib-mac.sh
cd apps/multiplatform
./gradlew packageDmg
echo "::set-output name=package_path::$(echo $PWD/release/main/dmg/SimpleX-*.dmg)"
- name: Linux upload desktop package to release
if: startsWith(github.ref, 'refs/tags/v') && (matrix.os == 'ubuntu-20.04' || matrix.os == 'ubuntu-22.04')
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.linux_desktop_build.outputs.package_path }}
asset_name: ${{ matrix.desktop_asset_name }}
tag: ${{ github.ref }}
- name: Linux upload AppImage to release
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'ubuntu-20.04'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.linux_appimage_build.outputs.appimage_path }}
asset_name: simplex-desktop-x86_64.AppImage
tag: ${{ github.ref }}
- name: Mac upload desktop package to release
if: startsWith(github.ref, 'refs/tags/v') && matrix.os == 'macos-latest'
uses: svenstaro/upload-release-action@v2
with:
repo_token: ${{ secrets.GITHUB_TOKEN }}
file: ${{ steps.mac_desktop_build.outputs.package_path }}
asset_name: ${{ matrix.desktop_asset_name }}
tag: ${{ github.ref }}
- name: Unix test
if: matrix.os != 'windows-latest'
timeout-minutes: 30
+1
View File
@@ -53,6 +53,7 @@ website/src/docs/
website/translations.json
website/src/img/images/
website/src/images/
website/src/js/lottie.min.js
# Generated files
website/package/generated*
+44 -24
View File
@@ -28,6 +28,17 @@ struct ContentView: View {
@State private var showWhatsNew = false
@State private var showChooseLAMode = false
@State private var showSetPasscode = false
@State private var chatListActionSheet: ChatListActionSheet? = nil
private enum ChatListActionSheet: Identifiable {
case connectViaUrl(action: ConnReqType, link: String)
var id: String {
switch self {
case .connectViaUrl: return "connectViaUrl \(link)"
}
}
}
var body: some View {
ZStack {
@@ -80,6 +91,11 @@ struct ContentView: View {
if case .onboardingComplete = step,
chatModel.currentUser != nil {
mainView()
.actionSheet(item: $chatListActionSheet) { sheet in
switch sheet {
case let .connectViaUrl(action, link): return connectViaUrlSheet(action, link)
}
}
} else {
OnboardingView(onboarding: step)
}
@@ -132,7 +148,9 @@ struct ContentView: View {
}
}
prefShowLANotice = true
connectViaUrl()
}
.onChange(of: chatModel.appOpenUrl) { _ in connectViaUrl() }
.sheet(isPresented: $showWhatsNew) {
WhatsNewView()
}
@@ -265,36 +283,38 @@ struct ContentView: View {
secondaryButton: .cancel()
)
}
}
func connectViaUrl() {
let m = ChatModel.shared
if let url = m.appOpenUrl {
m.appOpenUrl = nil
AlertManager.shared.showAlert(connectViaUrlAlert(url))
func connectViaUrl() {
let m = ChatModel.shared
if let url = m.appOpenUrl {
m.appOpenUrl = nil
var path = url.path
logger.debug("ContentView.connectViaUrl path: \(path)")
if (path == "/contact" || path == "/invitation") {
path.removeFirst()
let action: ConnReqType = path == "contact" ? .contact : .invitation
let link = url.absoluteString.replacingOccurrences(of: "///\(path)", with: "/\(path)")
chatListActionSheet = .connectViaUrl(action: action, link: link)
} else {
AlertManager.shared.showAlert(Alert(title: Text("Error: URL is invalid")))
}
}
}
}
func connectViaUrlAlert(_ url: URL) -> Alert {
var path = url.path
logger.debug("ChatListView.connectViaUrlAlert path: \(path)")
if (path == "/contact" || path == "/invitation") {
path.removeFirst()
let action: ConnReqType = path == "contact" ? .contact : .invitation
let link = url.absoluteString.replacingOccurrences(of: "///\(path)", with: "/\(path)")
private func connectViaUrlSheet(_ action: ConnReqType, _ link: String) -> ActionSheet {
let title: LocalizedStringKey
if case .contact = action { title = "Connect via contact link?" }
else { title = "Connect via one-time link?" }
return Alert(
switch action {
case .contact: title = "Connect via contact link"
case .invitation: title = "Connect via one-time link"
}
return ActionSheet(
title: Text(title),
message: Text("Your profile will be sent to the contact that you received this link from"),
primaryButton: .default(Text("Connect")) {
connectViaLink(link)
},
secondaryButton: .cancel()
buttons: [
.default(Text("Use current profile")) { connectViaLink(link, incognito: false) },
.default(Text("Use new incognito profile")) { connectViaLink(link, incognito: true) },
.cancel()
]
)
} else {
return Alert(title: Text("Error: URL is invalid"))
}
}
+6 -2
View File
@@ -43,9 +43,8 @@ final class ChatModel: ObservableObject {
@Published var tokenStatus: NtfTknStatus?
@Published var notificationMode = NotificationsMode.off
@Published var notificationPreview: NotificationPreviewMode = ntfPreviewModeGroupDefault.get()
@Published var incognito: Bool = incognitoGroupDefault.get()
// pending notification actions
@Published var ntfContactRequest: ChatId?
@Published var ntfContactRequest: NTFContactRequest?
@Published var ntfCallInvitationAction: (ChatId, NtfCallAction)?
// current WebRTC call
@Published var callInvitations: Dictionary<ChatId, RcvCallInvitation> = [:]
@@ -589,6 +588,11 @@ final class ChatModel: ObservableObject {
}
}
struct NTFContactRequest {
var incognito: Bool
var chatId: String
}
struct UnreadChatItemCounts {
var totalBelow: Int
var unreadBelow: Int
+16 -8
View File
@@ -12,6 +12,7 @@ import UIKit
import SimpleXChat
let ntfActionAcceptContact = "NTF_ACT_ACCEPT_CONTACT"
let ntfActionAcceptContactIncognito = "NTF_ACT_ACCEPT_CONTACT_INCOGNITO"
let ntfActionAcceptCall = "NTF_ACT_ACCEPT_CALL"
let ntfActionRejectCall = "NTF_ACT_REJECT_CALL"
@@ -41,12 +42,13 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
userId != chatModel.currentUser?.userId {
changeActiveUser(userId, viewPwd: nil)
}
if content.categoryIdentifier == ntfCategoryContactRequest && action == ntfActionAcceptContact,
if content.categoryIdentifier == ntfCategoryContactRequest && (action == ntfActionAcceptContact || action == ntfActionAcceptContactIncognito),
let chatId = content.userInfo["chatId"] as? String {
let incognito = action == ntfActionAcceptContactIncognito
if case let .contactRequest(contactRequest) = chatModel.getChat(chatId)?.chatInfo {
Task { await acceptContactRequest(contactRequest) }
Task { await acceptContactRequest(incognito: incognito, contactRequest: contactRequest) }
} else {
chatModel.ntfContactRequest = chatId
chatModel.ntfContactRequest = NTFContactRequest(incognito: incognito, chatId: chatId)
}
} else if let (chatId, ntfAction) = ntfCallAction(content, action) {
if let invitation = chatModel.callInvitations.removeValue(forKey: chatId) {
@@ -134,11 +136,17 @@ class NtfManager: NSObject, UNUserNotificationCenterDelegate, ObservableObject {
UNUserNotificationCenter.current().setNotificationCategories([
UNNotificationCategory(
identifier: ntfCategoryContactRequest,
actions: [UNNotificationAction(
identifier: ntfActionAcceptContact,
title: NSLocalizedString("Accept", comment: "accept contact request via notification"),
options: .foreground
)],
actions: [
UNNotificationAction(
identifier: ntfActionAcceptContact,
title: NSLocalizedString("Accept", comment: "accept contact request via notification"),
options: .foreground
), UNNotificationAction(
identifier: ntfActionAcceptContactIncognito,
title: NSLocalizedString("Accept incognito", comment: "accept contact request via notification"),
options: .foreground
)
],
intentIdentifiers: [],
hiddenPreviewsBodyPlaceholder: NSLocalizedString("New contact request", comment: "notification")
),
+40 -29
View File
@@ -171,6 +171,12 @@ func apiSetUserContactReceipts(_ userId: Int64, userMsgReceiptSettings: UserMsgR
throw r
}
func apiSetUserGroupReceipts(_ userId: Int64, userMsgReceiptSettings: UserMsgReceiptSettings) async throws {
let r = await chatSendCmd(.apiSetUserGroupReceipts(userId: userId, userMsgReceiptSettings: userMsgReceiptSettings))
if case .cmdOk = r { return }
throw r
}
func apiHideUser(_ userId: Int64, viewPwd: String) async throws -> User {
try await setUserPrivacy_(.apiHideUser(userId: userId, viewPwd: viewPwd))
}
@@ -246,12 +252,6 @@ func setXFTPConfig(_ cfg: XFTPFileConfig?) throws {
throw r
}
func apiSetIncognito(incognito: Bool) throws {
let r = chatSendCmdSync(.setIncognito(incognito: incognito))
if case .cmdOk = r { return }
throw r
}
func apiExportArchive(config: ArchiveConfig) async throws {
try await sendCommandOkResp(.apiExportArchive(config: config))
}
@@ -558,19 +558,25 @@ func apiVerifyGroupMember(_ groupId: Int64, _ groupMemberId: Int64, connectionCo
return nil
}
func apiAddContact() async -> String? {
func apiAddContact(incognito: Bool) async -> (String, PendingContactConnection)? {
guard let userId = ChatModel.shared.currentUser?.userId else {
logger.error("apiAddContact: no current user")
return nil
}
let r = await chatSendCmd(.apiAddContact(userId: userId), bgTask: false)
if case let .invitation(_, connReqInvitation) = r { return connReqInvitation }
let r = await chatSendCmd(.apiAddContact(userId: userId, incognito: incognito), bgTask: false)
if case let .invitation(_, connReqInvitation, connection) = r { return (connReqInvitation, connection) }
AlertManager.shared.showAlert(connectionErrorAlert(r))
return nil
}
func apiConnect(connReq: String) async -> ConnReqType? {
let (connReqType, alert) = await apiConnect_(connReq: connReq)
func apiSetConnectionIncognito(connId: Int64, incognito: Bool) async throws -> PendingContactConnection? {
let r = await chatSendCmd(.apiSetConnectionIncognito(connId: connId, incognito: incognito))
if case let .connectionIncognitoUpdated(_, toConnection) = r { return toConnection }
throw r
}
func apiConnect(incognito: Bool, connReq: String) async -> ConnReqType? {
let (connReqType, alert) = await apiConnect_(incognito: incognito, connReq: connReq)
if let alert = alert {
AlertManager.shared.showAlert(alert)
return nil
@@ -579,12 +585,12 @@ func apiConnect(connReq: String) async -> ConnReqType? {
}
}
func apiConnect_(connReq: String) async -> (ConnReqType?, Alert?) {
func apiConnect_(incognito: Bool, connReq: String) async -> (ConnReqType?, Alert?) {
guard let userId = ChatModel.shared.currentUser?.userId else {
logger.error("apiConnect: no current user")
return (nil, nil)
}
let r = await chatSendCmd(.apiConnect(userId: userId, connReq: connReq))
let r = await chatSendCmd(.apiConnect(userId: userId, incognito: incognito, connReq: connReq))
switch r {
case .sentConfirmation: return (.invitation, nil)
case .sentInvitation: return (.contact, nil)
@@ -760,8 +766,8 @@ func userAddressAutoAccept(_ autoAccept: AutoAccept?) async throws -> UserContac
}
}
func apiAcceptContactRequest(contactReqId: Int64) async -> Contact? {
let r = await chatSendCmd(.apiAcceptContact(contactReqId: contactReqId))
func apiAcceptContactRequest(incognito: Bool, contactReqId: Int64) async -> Contact? {
let r = await chatSendCmd(.apiAcceptContact(incognito: incognito, contactReqId: contactReqId))
let am = AlertManager.shared
if case let .acceptingContactRequest(_, contact) = r { return contact }
@@ -796,29 +802,35 @@ func apiChatUnread(type: ChatType, id: Int64, unreadChat: Bool) async throws {
try await sendCommandOkResp(.apiChatUnread(type: type, id: id, unreadChat: unreadChat))
}
func receiveFile(user: User, fileId: Int64) async {
if let chatItem = await apiReceiveFile(fileId: fileId) {
func receiveFile(user: User, fileId: Int64, auto: Bool = false) async {
if let chatItem = await apiReceiveFile(fileId: fileId, auto: auto) {
DispatchQueue.main.async { chatItemSimpleUpdate(user, chatItem) }
}
}
func apiReceiveFile(fileId: Int64, inline: Bool? = nil) async -> AChatItem? {
func apiReceiveFile(fileId: Int64, inline: Bool? = nil, auto: Bool = false) async -> AChatItem? {
let r = await chatSendCmd(.receiveFile(fileId: fileId, inline: inline))
let am = AlertManager.shared
if case let .rcvFileAccepted(_, chatItem) = r { return chatItem }
if case .rcvFileAcceptedSndCancelled = r {
am.showAlertMsg(
title: "Cannot receive file",
message: "Sender cancelled file transfer."
)
logger.debug("apiReceiveFile error: sender cancelled file transfer")
if !auto {
am.showAlertMsg(
title: "Cannot receive file",
message: "Sender cancelled file transfer."
)
}
} else if let networkErrorAlert = networkErrorAlert(r) {
logger.error("apiReceiveFile network error: \(String(describing: r))")
am.showAlert(networkErrorAlert)
} else {
logger.error("apiReceiveFile error: \(String(describing: r))")
switch r {
case .chatCmdError(_, .error(.fileAlreadyReceiving)):
switch chatError(r) {
case .fileCancelled:
logger.debug("apiReceiveFile ignoring fileCancelled error")
case .fileAlreadyReceiving:
logger.debug("apiReceiveFile ignoring fileAlreadyReceiving error")
default:
logger.error("apiReceiveFile error: \(String(describing: r))")
am.showAlertMsg(
title: "Error receiving file",
message: "Error: \(String(describing: r))"
@@ -863,8 +875,8 @@ func networkErrorAlert(_ r: ChatResponse) -> Alert? {
}
}
func acceptContactRequest(_ contactRequest: UserContactRequest) async {
if let contact = await apiAcceptContactRequest(contactReqId: contactRequest.apiId) {
func acceptContactRequest(incognito: Bool, contactRequest: UserContactRequest) async {
if let contact = await apiAcceptContactRequest(incognito: incognito, contactReqId: contactRequest.apiId) {
let chat = Chat(chatInfo: ChatInfo.direct(contact: contact), chatItems: [])
DispatchQueue.main.async { ChatModel.shared.replaceChat(contactRequest.id, chat) }
}
@@ -1098,7 +1110,6 @@ func initializeChat(start: Bool, dbKey: String? = nil, refreshInvitations: Bool
try apiSetTempFolder(tempFolder: getTempFilesDirectory().path)
try apiSetFilesFolder(filesFolder: getAppFilesDirectory().path)
try setXFTPConfig(getXFTPCfg())
try apiSetIncognito(incognito: incognitoGroupDefault.get())
m.chatInitialized = true
m.currentUser = try apiGetActiveUser()
if m.currentUser == nil {
@@ -1317,7 +1328,7 @@ func processReceivedMsg(_ res: ChatResponse) async {
}
if let file = cItem.autoReceiveFile() {
Task {
await receiveFile(user: user, fileId: file.fileId)
await receiveFile(user: user, fileId: file.fileId, auto: true)
}
}
if cItem.showNotification {
+3 -3
View File
@@ -139,10 +139,10 @@ struct SimpleXApp: App {
let chat = chatModel.getChat(id) {
loadChat(chat: chat)
}
if let chatId = chatModel.ntfContactRequest {
if let ncr = chatModel.ntfContactRequest {
chatModel.ntfContactRequest = nil
if case let .contactRequest(contactRequest) = chatModel.getChat(chatId)?.chatInfo {
Task { await acceptContactRequest(contactRequest) }
if case let .contactRequest(contactRequest) = chatModel.getChat(ncr.chatId)?.chatInfo {
Task { await acceptContactRequest(incognito: ncr.incognito, contactRequest: contactRequest) }
}
}
} catch let error {
@@ -143,7 +143,12 @@ struct ChatInfoView: View {
if let customUserProfile = customUserProfile {
Section("Incognito") {
infoRow("Your random profile", customUserProfile.chatViewName)
HStack {
Text("Your random profile")
Spacer()
Text(customUserProfile.chatViewName)
.foregroundStyle(.indigo)
}
}
}
@@ -197,7 +197,7 @@ struct CIFileView_Previews: PreviewProvider {
static var previews: some View {
let sentFile: ChatItem = ChatItem(
chatDir: .directSnd,
meta: CIMeta.getSample(1, .now, "", .sndSent, itemEdited: true),
meta: CIMeta.getSample(1, .now, "", .sndSent(sndProgress: .complete), itemEdited: true),
content: .sndMsgContent(msgContent: .file("")),
quotedItem: nil,
file: CIFile.getSample(fileStatus: .sndComplete)
@@ -13,6 +13,7 @@ struct CIMetaView: View {
@EnvironmentObject var chat: Chat
var chatItem: ChatItem
var metaColor = Color.secondary
var paleMetaColor = Color(UIColor.tertiaryLabel)
var body: some View {
if chatItem.isDeletedContent {
@@ -21,12 +22,23 @@ struct CIMetaView: View {
let meta = chatItem.meta
let ttl = chat.chatInfo.timedMessagesTTL
switch meta.itemStatus {
case .sndSent:
ciMetaText(meta, chatTTL: ttl, color: metaColor, sent: .sent)
case .sndRcvd:
ZStack {
ciMetaText(meta, chatTTL: ttl, color: metaColor, sent: .rcvd1)
ciMetaText(meta, chatTTL: ttl, color: metaColor, sent: .rcvd2)
case let .sndSent(sndProgress):
switch sndProgress {
case .complete: ciMetaText(meta, chatTTL: ttl, color: metaColor, sent: .sent)
case .partial: ciMetaText(meta, chatTTL: ttl, color: paleMetaColor, sent: .sent)
}
case let .sndRcvd(_, sndProgress):
switch sndProgress {
case .complete:
ZStack {
ciMetaText(meta, chatTTL: ttl, color: metaColor, sent: .rcvd1)
ciMetaText(meta, chatTTL: ttl, color: metaColor, sent: .rcvd2)
}
case .partial:
ZStack {
ciMetaText(meta, chatTTL: ttl, color: paleMetaColor, sent: .rcvd1)
ciMetaText(meta, chatTTL: ttl, color: paleMetaColor, sent: .rcvd2)
}
}
default:
ciMetaText(meta, chatTTL: ttl, color: metaColor)
@@ -61,7 +73,7 @@ func ciMetaText(_ meta: CIMeta, chatTTL: Int?, color: Color = .clear, transparen
switch sent {
case nil: r = r + t1
case .sent: r = r + t1 + gap
case .rcvd1: r = r + t.foregroundColor(transparent ? .clear : color.opacity(0.67)) + gap
case .rcvd1: r = r + t.foregroundColor(transparent ? .clear : statusColor.opacity(0.67)) + gap
case .rcvd2: r = r + gap + t1
}
r = r + Text(" ")
@@ -78,8 +90,12 @@ private func statusIconText(_ icon: String, _ color: Color) -> Text {
struct CIMetaView_Previews: PreviewProvider {
static var previews: some View {
Group {
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent))
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent, itemEdited: true))
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete)))
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .partial)))
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndRcvd(msgRcptStatus: .ok, sndProgress: .complete)))
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndRcvd(msgRcptStatus: .ok, sndProgress: .partial)))
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndRcvd(msgRcptStatus: .badMsgHash, sndProgress: .complete)))
CIMetaView(chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), itemEdited: true))
CIMetaView(chatItem: ChatItem.getDeletedContentSample())
}
.previewLayout(.fixed(width: 360, height: 100))
@@ -247,10 +247,10 @@ struct CIVideoView: View {
.padding([.trailing, .top], 11)
}
private func receiveFileIfValidSize(file: CIFile, receiveFile: @escaping (User, Int64) async -> Void) {
private func receiveFileIfValidSize(file: CIFile, receiveFile: @escaping (User, Int64, Bool) async -> Void) {
Task {
if let user = ChatModel.shared.currentUser {
await receiveFile(user, file.fileId)
await receiveFile(user, file.fileId, false)
}
}
}
@@ -269,7 +269,7 @@ struct CIVoiceView_Previews: PreviewProvider {
static var previews: some View {
let sentVoiceMessage: ChatItem = ChatItem(
chatDir: .directSnd,
meta: CIMeta.getSample(1, .now, "", .sndSent, itemEdited: true),
meta: CIMeta.getSample(1, .now, "", .sndSent(sndProgress: .complete), itemEdited: true),
content: .sndMsgContent(msgContent: .voice(text: "", duration: 30)),
quotedItem: nil,
file: CIFile.getSample(fileStatus: .sndComplete)
@@ -32,7 +32,7 @@ func emojiText(_ text: String) -> Text {
struct EmojiItemView_Previews: PreviewProvider {
static var previews: some View {
Group{
EmojiItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent))
EmojiItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete)))
EmojiItemView(chatItem: ChatItem.getSample(2, .directRcv, .now, "👍"))
}
.previewLayout(.fixed(width: 360, height: 70))
@@ -75,14 +75,14 @@ struct FramedCIVoiceView_Previews: PreviewProvider {
static var previews: some View {
let sentVoiceMessage: ChatItem = ChatItem(
chatDir: .directSnd,
meta: CIMeta.getSample(1, .now, "", .sndSent, itemEdited: true),
meta: CIMeta.getSample(1, .now, "", .sndSent(sndProgress: .complete), itemEdited: true),
content: .sndMsgContent(msgContent: .voice(text: "Hello there", duration: 30)),
quotedItem: nil,
file: CIFile.getSample(fileStatus: .sndComplete)
)
let voiceMessageWithQuote: ChatItem = ChatItem(
chatDir: .directSnd,
meta: CIMeta.getSample(1, .now, "", .sndSent, itemEdited: true),
meta: CIMeta.getSample(1, .now, "", .sndSent(sndProgress: .complete), itemEdited: true),
content: .sndMsgContent(msgContent: .voice(text: "", duration: 30)),
quotedItem: CIQuote.getSample(1, .now, "Hi", chatDir: .directRcv),
file: CIFile.getSample(fileStatus: .sndComplete)
@@ -349,8 +349,8 @@ struct FramedItemView_Previews: PreviewProvider {
Group{
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello"), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent, quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent, quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -"), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line "), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat"), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
@@ -363,10 +363,10 @@ struct FramedItemView_Previews: PreviewProvider {
struct FramedItemView_Edited_Previews: PreviewProvider {
static var previews: some View {
Group {
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd), itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent, quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent, quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -", .rcvRead, itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line ", .rcvRead, itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat", .rcvRead, itemEdited: true), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
@@ -381,10 +381,10 @@ struct FramedItemView_Edited_Previews: PreviewProvider {
struct FramedItemView_Deleted_Previews: PreviewProvider {
static var previews: some View {
Group {
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .groupRcv(groupMember: GroupMember.sampleData), .now, "hello", quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directSnd), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent, quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent, quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "https://simplex.chat", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "hi", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directSnd, .now, "👍", .sndSent(sndProgress: .complete), quotedItem: CIQuote.getSample(1, .now, "Hello too", chatDir: .directRcv), itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this covers -", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "hello there too!!! this text has the time on the same line ", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
FramedItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "https://simplex.chat", .rcvRead, itemDeleted: .deleted(deletedTs: .now)), allowMenu: Binding.constant(true), audioPlayer: .constant(nil), playbackState: .constant(.noPlayback), playbackTime: .constant(nil))
@@ -46,7 +46,7 @@ struct MarkedDeletedItemView: View {
struct MarkedDeletedItemView_Previews: PreviewProvider {
static var previews: some View {
Group {
MarkedDeletedItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, itemDeleted: .deleted(deletedTs: .now)))
MarkedDeletedItemView(chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)))
}
.previewLayout(.fixed(width: 360, height: 200))
}
@@ -14,11 +14,23 @@ struct ChatItemInfoView: View {
var ci: ChatItem
@Binding var chatItemInfo: ChatItemInfo?
@State private var selection: CIInfoTab = .history
@State private var alert: CIInfoViewAlert? = nil
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
enum CIInfoTab {
case history
case quote
case delivery
}
enum CIInfoViewAlert: Identifiable {
case alert(title: String, text: String)
var id: String {
switch self {
case let .alert(title, text): return "alert \(title) \(text)"
}
}
}
var body: some View {
@@ -31,6 +43,11 @@ struct ChatItemInfoView: View {
}
}
}
.alert(item: $alert) { a in
switch(a) {
case let .alert(title, text): return Alert(title: Text(title), message: Text(text))
}
}
}
}
@@ -40,19 +57,44 @@ struct ChatItemInfoView: View {
: NSLocalizedString("Received message", comment: "message info title")
}
private var numTabs: Int {
var numTabs = 1
if chatItemInfo?.memberDeliveryStatuses != nil {
numTabs += 1
}
if ci.quotedItem != nil {
numTabs += 1
}
return numTabs
}
@ViewBuilder private func itemInfoView() -> some View {
if let qi = ci.quotedItem {
if numTabs > 1 {
TabView(selection: $selection) {
if let mdss = chatItemInfo?.memberDeliveryStatuses {
deliveryTab(mdss)
.tabItem {
Label("Delivery", systemImage: "checkmark.message")
}
.tag(CIInfoTab.delivery)
}
historyTab()
.tabItem {
Label("History", systemImage: "clock")
}
.tag(CIInfoTab.history)
quoteTab(qi)
.tabItem {
Label("In reply to", systemImage: "arrowshape.turn.up.left")
}
.tag(CIInfoTab.quote)
if let qi = ci.quotedItem {
quoteTab(qi)
.tabItem {
Label("In reply to", systemImage: "arrowshape.turn.up.left")
}
.tag(CIInfoTab.quote)
}
}
.onAppear {
if chatItemInfo?.memberDeliveryStatuses != nil {
selection = .delivery
}
}
} else {
historyTab()
@@ -217,9 +259,87 @@ struct ChatItemInfoView: View {
: Color(uiColor: .tertiarySystemGroupedBackground)
}
@ViewBuilder private func deliveryTab(_ memberDeliveryStatuses: [MemberDeliveryStatus]) -> some View {
ScrollView {
VStack(alignment: .leading, spacing: 16) {
details()
Divider().padding(.vertical)
Text("Delivery")
.font(.title2)
.padding(.bottom, 4)
memberDeliveryStatusesView(memberDeliveryStatuses)
}
.padding()
}
.frame(maxHeight: .infinity, alignment: .top)
}
@ViewBuilder private func memberDeliveryStatusesView(_ memberDeliveryStatuses: [MemberDeliveryStatus]) -> some View {
VStack(alignment: .leading, spacing: 12) {
let mss = membersStatuses(memberDeliveryStatuses)
if !mss.isEmpty {
ForEach(mss, id: \.0.groupMemberId) { memberStatus in
memberDeliveryStatusView(memberStatus.0, memberStatus.1)
}
} else {
Text("No delivery information")
.foregroundColor(.secondary)
}
}
}
private func membersStatuses(_ memberDeliveryStatuses: [MemberDeliveryStatus]) -> [(GroupMember, CIStatus)] {
memberDeliveryStatuses.compactMap({ mds in
if let mem = ChatModel.shared.groupMembers.first(where: { $0.groupMemberId == mds.groupMemberId }) {
return (mem, mds.memberDeliveryStatus)
} else {
return nil
}
})
}
private func memberDeliveryStatusView(_ member: GroupMember, _ status: CIStatus) -> some View {
HStack{
ProfileImage(imageStr: member.image)
.frame(width: 30, height: 30)
.padding(.trailing, 2)
Text(member.chatViewName)
.lineLimit(1)
Spacer()
let v = Group {
if let (icon, statusColor) = status.statusIcon(Color.secondary) {
switch status {
case .sndRcvd:
ZStack(alignment: .trailing) {
Image(systemName: icon)
.foregroundColor(statusColor.opacity(0.67))
.padding(.trailing, 6)
Image(systemName: icon)
.foregroundColor(statusColor.opacity(0.67))
}
default:
Image(systemName: icon)
.foregroundColor(statusColor)
}
} else {
Image(systemName: "ellipsis")
.foregroundColor(Color.secondary)
}
}
if let (title, text) = status.statusInfo {
v.onTapGesture {
alert = .alert(title: title, text: text)
}
} else {
v
}
}
}
private func itemInfoShareText() -> String {
let meta = ci.meta
var shareText: [String] = [title, ""]
var shareText: [String] = [String.localizedStringWithFormat(NSLocalizedString("# %@", comment: "copied message info title, # <title>"), title), ""]
shareText += [String.localizedStringWithFormat(NSLocalizedString("Sent at: %@", comment: "copied message info"), localTimestamp(meta.itemTs))]
if !ci.chatDir.sent {
shareText += [String.localizedStringWithFormat(NSLocalizedString("Received at: %@", comment: "copied message info"), localTimestamp(meta.createdAt))]
@@ -245,7 +365,7 @@ struct ChatItemInfoView: View {
]
}
if let qi = ci.quotedItem {
shareText += ["", NSLocalizedString("In reply to", comment: "copied message info")]
shareText += ["", NSLocalizedString("## In reply to", comment: "copied message info")]
let t = qi.text
shareText += [""]
if let sender = qi.getSender(nil) {
@@ -264,7 +384,7 @@ struct ChatItemInfoView: View {
}
if let chatItemInfo = chatItemInfo,
!chatItemInfo.itemVersions.isEmpty {
shareText += ["", NSLocalizedString("History", comment: "copied message info")]
shareText += ["", NSLocalizedString("## History", comment: "copied message info")]
for (index, itemVersion) in chatItemInfo.itemVersions.enumerated() {
let t = itemVersion.msgContent.text
shareText += [
@@ -125,9 +125,9 @@ struct ChatItemView_Previews: PreviewProvider {
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂"), revealed: Binding.constant(false))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(2, .directRcv, .now, "🙂🙂🙂🙂🙂🙂"), revealed: Binding.constant(false))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getDeletedContentSample(), revealed: Binding.constant(false))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(false))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent, itemLive: true), revealed: Binding.constant(true))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, itemLive: true), revealed: Binding.constant(true))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now)), revealed: Binding.constant(false))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "🙂", .sndSent(sndProgress: .complete), itemLive: true), revealed: Binding.constant(true))
ChatItemView(chatInfo: ChatInfo.sampleData.direct, chatItem: ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemLive: true), revealed: Binding.constant(true))
}
.previewLayout(.fixed(width: 360, height: 70))
.environmentObject(Chat.sampleData)
@@ -770,6 +770,12 @@ struct ChatView: View {
await MainActor.run {
chatItemInfo = ciInfo
}
if case let .group(gInfo) = chat.chatInfo {
let groupMembers = await apiListMembers(gInfo.groupId)
await MainActor.run {
ChatModel.shared.groupMembers = groupMembers
}
}
} catch let error {
logger.error("apiGetChatItemInfo error: \(responseError(error))")
}
@@ -9,6 +9,8 @@
import SwiftUI
import SimpleXChat
let SMALL_GROUPS_RCPS_MEM_LIMIT: Int = 20
struct GroupChatInfoView: View {
@EnvironmentObject var chatModel: ChatModel
@Environment(\.dismiss) var dismiss: DismissAction
@@ -21,6 +23,8 @@ struct GroupChatInfoView: View {
@State private var showAddMembersSheet: Bool = false
@State private var connectionStats: ConnectionStats?
@State private var connectionCode: String?
@State private var sendReceipts = SendReceipts.userDefault(true)
@State private var sendReceiptsUserDefault = true
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
@State private var searchText: String = ""
@FocusState private var searchFocussed
@@ -30,6 +34,7 @@ struct GroupChatInfoView: View {
case clearChatAlert
case leaveGroupAlert
case cantInviteIncognitoAlert
case largeGroupReceiptsDisabled
var id: GroupChatInfoViewAlert { get { self } }
}
@@ -52,6 +57,11 @@ struct GroupChatInfoView: View {
addOrEditWelcomeMessage()
}
groupPreferencesButton($groupInfo)
if members.filter({ $0.memberCurrent }).count <= SMALL_GROUPS_RCPS_MEM_LIMIT {
sendReceiptsOption()
} else {
sendReceiptsOptionDisabled()
}
} header: {
Text("")
} footer: {
@@ -115,9 +125,14 @@ struct GroupChatInfoView: View {
case .clearChatAlert: return clearChatAlert()
case .leaveGroupAlert: return leaveGroupAlert()
case .cantInviteIncognitoAlert: return cantInviteIncognitoAlert()
case .largeGroupReceiptsDisabled: return largeGroupReceiptsDisabledAlert()
}
}
.onAppear {
if let currentUser = chatModel.currentUser {
sendReceiptsUserDefault = currentUser.sendRcptsSmallGroups
}
sendReceipts = SendReceipts.fromBool(groupInfo.chatSettings.sendRcpts, userDefault: sendReceiptsUserDefault)
do {
if let link = try apiGetGroupLink(groupInfo.groupId) {
(groupLink, groupLinkMemberRole) = link
@@ -328,6 +343,38 @@ struct GroupChatInfoView: View {
secondaryButton: .cancel()
)
}
private func sendReceiptsOption() -> some View {
Picker(selection: $sendReceipts) {
ForEach([.yes, .no, .userDefault(sendReceiptsUserDefault)]) { (opt: SendReceipts) in
Text(opt.text)
}
} label: {
Label("Send receipts", systemImage: "checkmark.message")
}
.frame(height: 36)
.onChange(of: sendReceipts) { _ in
setSendReceipts()
}
}
private func setSendReceipts() {
var chatSettings = chat.chatInfo.chatSettings ?? ChatSettings.defaults
chatSettings.sendRcpts = sendReceipts.bool()
updateChatSettings(chat, chatSettings: chatSettings)
}
private func sendReceiptsOptionDisabled() -> some View {
HStack {
Label("Send receipts", systemImage: "checkmark.message")
Spacer()
Text("disabled")
.foregroundStyle(.secondary)
}
.onTapGesture {
alert = .largeGroupReceiptsDisabled
}
}
}
func groupPreferencesButton(_ groupInfo: Binding<GroupInfo>, _ creatingGroup: Bool = false) -> some View {
@@ -356,6 +403,13 @@ func cantInviteIncognitoAlert() -> Alert {
)
}
func largeGroupReceiptsDisabledAlert() -> Alert {
Alert(
title: Text("Receipts are disabled"),
message: Text("This group has over \(SMALL_GROUPS_RCPS_MEM_LIMIT) members, delivery receipts are not sent.")
)
}
struct GroupChatInfoView_Previews: PreviewProvider {
static var previews: some View {
GroupChatInfoView(chat: Chat(chatInfo: ChatInfo.sampleData.group, chatItems: []), groupInfo: GroupInfo.sampleData)
@@ -19,6 +19,7 @@ struct GroupMemberInfoView: View {
@State private var connectionCode: String? = nil
@State private var newRole: GroupMemberRole = .member
@State private var alert: GroupMemberInfoViewAlert?
@State private var connectToMemberDialog: Bool = false
@AppStorage(DEFAULT_DEVELOPER_TOOLS) private var developerTools = false
@State private var justOpened = true
@@ -38,8 +39,8 @@ struct GroupMemberInfoView: View {
case let .changeMemberRoleAlert(_, role): return "changeMemberRoleAlert \(role.rawValue)"
case .switchAddressAlert: return "switchAddressAlert"
case .abortSwitchAddressAlert: return "abortSwitchAddressAlert"
case .connRequestSentAlert: return "connRequestSentAlert"
case .syncConnectionForceAlert: return "syncConnectionForceAlert"
case .connRequestSentAlert: return "connRequestSentAlert"
case let .error(title, _): return "error \(title)"
case let .other(alert): return "other \(alert)"
}
@@ -142,7 +143,7 @@ struct GroupMemberInfoView: View {
connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil }
|| connStats.ratchetSyncSendProhibited
)
if connStats.rcvQueuesInfo.contains { $0.rcvSwitchStatus != nil } {
if connStats.rcvQueuesInfo.contains(where: { $0.rcvSwitchStatus != nil }) {
Button("Abort changing address") {
alert = .abortSwitchAddressAlert
}
@@ -210,15 +211,19 @@ struct GroupMemberInfoView: View {
func connectViaAddressButton(_ contactLink: String) -> some View {
Button {
connectViaAddress(contactLink)
connectToMemberDialog = true
} label: {
Label("Connect", systemImage: "link")
}
.confirmationDialog("Connect directly", isPresented: $connectToMemberDialog, titleVisibility: .visible) {
Button("Use current profile") { connectViaAddress(incognito: false, contactLink: contactLink) }
Button("Use new incognito profile") { connectViaAddress(incognito: true, contactLink: contactLink) }
}
}
func connectViaAddress(_ contactLink: String) {
func connectViaAddress(incognito: Bool, contactLink: String) {
Task {
let (connReqType, connectAlert) = await apiConnect_(connReq: contactLink)
let (connReqType, connectAlert) = await apiConnect_(incognito: incognito, connReq: contactLink)
if let connReqType = connReqType {
alert = .connRequestSentAlert(type: connReqType)
} else if let connectAlert = connectAlert {
@@ -19,7 +19,7 @@ struct ScanCodeView: View {
VStack(alignment: .leading) {
CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit)
.border(.gray)
.cornerRadius(12)
Text("Scan security code from your contact's app.")
.padding(.top)
}
@@ -64,7 +64,7 @@ struct VerifyCodeView: View {
HStack {
NavigationLink {
ScanCodeView(connectionVerified: $connectionVerified, verify: verify)
.navigationBarTitleDisplayMode(.inline)
.navigationBarTitleDisplayMode(.large)
.navigationTitle("Scan code")
} label: {
Label("Scan code", systemImage: "qrcode")
@@ -222,9 +222,15 @@ struct ChatListNavLink: View {
ContactRequestView(contactRequest: contactRequest, chat: chat)
.swipeActions(edge: .trailing, allowsFullSwipe: true) {
Button {
Task { await acceptContactRequest(contactRequest) }
} label: { Label("Accept", systemImage: chatModel.incognito ? "theatermasks" : "checkmark") }
.tint(chatModel.incognito ? .indigo : .accentColor)
Task { await acceptContactRequest(incognito: false, contactRequest: contactRequest) }
} label: { Label("Accept", systemImage: "checkmark") }
.tint(.accentColor)
Button {
Task { await acceptContactRequest(incognito: true, contactRequest: contactRequest) }
} label: {
Label("Accept incognito", systemImage: "theatermasks")
}
.tint(.indigo)
Button {
AlertManager.shared.showAlert(rejectContactRequestAlert(contactRequest))
} label: {
@@ -234,9 +240,10 @@ struct ChatListNavLink: View {
}
.frame(height: rowHeights[dynamicTypeSize])
.onTapGesture { showContactRequestDialog = true }
.confirmationDialog("Connection request", isPresented: $showContactRequestDialog, titleVisibility: .visible) {
Button(chatModel.incognito ? "Accept incognito" : "Accept contact") { Task { await acceptContactRequest(contactRequest) } }
Button("Reject contact (sender NOT notified)", role: .destructive) { Task { await rejectContactRequest(contactRequest) } }
.confirmationDialog("Accept connection request?", isPresented: $showContactRequestDialog, titleVisibility: .visible) {
Button("Accept") { Task { await acceptContactRequest(incognito: false, contactRequest: contactRequest) } }
Button("Accept incognito") { Task { await acceptContactRequest(incognito: true, contactRequest: contactRequest) } }
Button("Reject (sender NOT notified)", role: .destructive) { Task { await rejectContactRequest(contactRequest) } }
}
}
@@ -60,8 +60,6 @@ struct ChatListView: View {
chatList
}
}
.onChange(of: chatModel.appOpenUrl) { _ in connectViaUrl() }
.onAppear() { connectViaUrl() }
.onDisappear() { withAnimation { userPickerVisible = false } }
.refreshable {
AlertManager.shared.showAlert(Alert(
@@ -108,11 +106,6 @@ struct ChatListView: View {
}
ToolbarItem(placement: .principal) {
HStack(spacing: 4) {
if (chatModel.incognito) {
Image(systemName: "theatermasks")
.foregroundColor(.indigo)
.padding(.trailing, 8)
}
Text("Chats")
.font(.headline)
if chatModel.chats.count > 0 {
@@ -41,11 +41,9 @@ struct ChatPreviewView: View {
ZStack(alignment: .topTrailing) {
chatMessagePreview(cItem)
if case .direct = chat.chatInfo {
chatStatusImage()
.padding(.top, 24)
.frame(maxWidth: .infinity, alignment: .trailing)
}
chatStatusImage()
.padding(.top, 26)
.frame(maxWidth: .infinity, alignment: .trailing)
}
.padding(.trailing, 8)
@@ -59,12 +57,9 @@ struct ChatPreviewView: View {
@ViewBuilder private func chatPreviewImageOverlayIcon() -> some View {
if case let .group(groupInfo) = chat.chatInfo {
switch (groupInfo.membership.memberStatus) {
case .memLeft:
groupInactiveIcon()
case .memRemoved:
groupInactiveIcon()
case .memGroupDeleted:
groupInactiveIcon()
case .memLeft: groupInactiveIcon()
case .memRemoved: groupInactiveIcon()
case .memGroupDeleted: groupInactiveIcon()
default: EmptyView()
}
} else {
@@ -74,7 +69,7 @@ struct ChatPreviewView: View {
@ViewBuilder private func groupInactiveIcon() -> some View {
Image(systemName: "multiply.circle.fill")
.foregroundColor(.secondary)
.foregroundColor(.secondary.opacity(0.65))
.background(Circle().foregroundColor(Color(uiColor: .systemBackground)))
}
@@ -198,10 +193,7 @@ struct ChatPreviewView: View {
@ViewBuilder private func groupInvitationPreviewText(_ groupInfo: GroupInfo) -> some View {
groupInfo.membership.memberIncognito
? chatPreviewInfoText("join as \(groupInfo.membership.memberProfile.displayName)")
: (chatModel.incognito
? chatPreviewInfoText("join as \(chatModel.currentUser?.profile.displayName ?? "yourself")")
: chatPreviewInfoText("you are invited to group")
)
: chatPreviewInfoText("you are invited to group")
}
@ViewBuilder private func chatPreviewInfoText(_ text: LocalizedStringKey) -> some View {
@@ -229,7 +221,7 @@ struct ChatPreviewView: View {
switch chat.chatInfo {
case let .direct(contact):
switch (chatModel.contactNetworkStatus(contact)) {
case .connected: EmptyView()
case .connected: incognitoIcon(chat.chatInfo.incognito)
case .error:
Image(systemName: "exclamationmark.circle")
.resizable()
@@ -240,11 +232,23 @@ struct ChatPreviewView: View {
ProgressView()
}
default:
EmptyView()
incognitoIcon(chat.chatInfo.incognito)
}
}
}
@ViewBuilder func incognitoIcon(_ incognito: Bool) -> some View {
if incognito {
Image(systemName: "theatermasks")
.resizable()
.scaledToFit()
.frame(width: 22, height: 22)
.foregroundColor(.secondary)
} else {
EmptyView()
}
}
func unreadCountText(_ n: Int) -> Text {
Text(n > 999 ? "\(n / 1000)k" : n > 0 ? "\(n)" : "")
}
@@ -258,20 +262,20 @@ struct ChatPreviewView_Previews: PreviewProvider {
))
ChatPreviewView(chat: Chat(
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent)]
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))]
))
ChatPreviewView(chat: Chat(
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent)],
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))],
chatStats: ChatStats(unreadCount: 11, minUnreadItemId: 0)
))
ChatPreviewView(chat: Chat(
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent, itemDeleted: .deleted(deletedTs: .now))]
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete), itemDeleted: .deleted(deletedTs: .now))]
))
ChatPreviewView(chat: Chat(
chatInfo: ChatInfo.sampleData.direct,
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent)],
chatItems: [ChatItem.getSample(1, .directSnd, .now, "hello", .sndSent(sndProgress: .complete))],
chatStats: ChatStats(unreadCount: 3, minUnreadItemId: 0)
))
ChatPreviewView(chat: Chat(
@@ -15,6 +15,7 @@ struct ContactConnectionInfo: View {
@State var contactConnection: PendingContactConnection
@State private var alert: CCInfoAlert?
@State private var localAlias = ""
@State private var showIncognitoSheet = false
@FocusState private var aliasTextFieldFocused: Bool
enum CCInfoAlert: Identifiable {
@@ -31,19 +32,14 @@ struct ContactConnectionInfo: View {
var body: some View {
NavigationView {
List {
let v = List {
Group {
Text(contactConnection.initiated ? "You invited your contact" : "You accepted connection")
Text(contactConnection.initiated ? "You invited a contact" : "You accepted connection")
.font(.largeTitle)
.bold()
.padding(.bottom, 16)
.padding(.bottom)
Text(contactConnectionText(contactConnection))
.padding(.bottom, 16)
if let connReqInv = contactConnection.connReqInv {
OneTimeLinkProfileText(contactConnection: contactConnection, connReqInvitation: connReqInv)
}
}
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
@@ -65,10 +61,16 @@ struct ContactConnectionInfo: View {
if contactConnection.initiated,
let connReqInv = contactConnection.connReqInv {
oneTimeLinkSection(contactConnection: contactConnection, connReqInvitation: connReqInv)
QRCode(uri: connReqInv)
incognitoEnabled()
shareLinkButton(connReqInv)
oneTimeLinkLearnMoreButton()
} else {
incognitoEnabled()
oneTimeLinkLearnMoreButton()
}
} footer: {
sharedProfileInfo(contactConnection.incognito)
}
Section {
@@ -80,6 +82,14 @@ struct ContactConnectionInfo: View {
}
}
}
if #available(iOS 16, *) {
v
} else {
// navigationBarHidden is added conditionally,
// because the view jumps in iOS 17 if this is added,
// and on iOS 16+ it is hidden without it.
v.navigationBarHidden(true)
}
}
.alert(item: $alert) { _alert in
switch _alert {
@@ -128,6 +138,30 @@ struct ContactConnectionInfo: View {
)
: "You will be connected when your contact's device is online, please wait or check later!"
}
@ViewBuilder private func incognitoEnabled() -> some View {
if contactConnection.incognito {
ZStack(alignment: .leading) {
Image(systemName: "theatermasks.fill")
.frame(maxWidth: 24, maxHeight: 24, alignment: .center)
.foregroundColor(Color.indigo)
.font(.system(size: 14))
HStack(spacing: 6) {
Text("Incognito")
Image(systemName: "info.circle")
.foregroundColor(.accentColor)
.font(.system(size: 14))
}
.onTapGesture {
showIncognitoSheet = true
}
.padding(.leading, 36)
}
.sheet(isPresented: $showIncognitoSheet) {
IncognitoHelp()
}
}
}
}
struct ContactConnectionInfo_Previews: PreviewProvider {
@@ -58,10 +58,14 @@ struct ContactConnectionView: View {
}
.padding(.bottom, 2)
Text(contactConnection.description)
.frame(alignment: .topLeading)
.padding(.horizontal, 8)
.padding(.bottom, 2)
ZStack(alignment: .topTrailing) {
Text(contactConnection.description)
.frame(maxWidth: .infinity, alignment: .leading)
incognitoIcon(contactConnection.incognito)
.padding(.top, 26)
.frame(maxWidth: .infinity, alignment: .trailing)
}
.padding(.horizontal, 8)
Spacer()
}
@@ -24,7 +24,7 @@ struct ContactRequestView: View {
Text(contactRequest.chatViewName)
.font(.title3)
.fontWeight(.bold)
.foregroundColor(chatModel.incognito ? .indigo : .accentColor)
.foregroundColor(.accentColor)
.padding(.leading, 8)
.frame(alignment: .topLeading)
Spacer()
@@ -12,38 +12,92 @@ import SimpleXChat
struct AddContactView: View {
@EnvironmentObject private var chatModel: ChatModel
var contactConnection: PendingContactConnection? = nil
@Binding var contactConnection: PendingContactConnection?
var connReqInvitation: String
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
var body: some View {
List {
OneTimeLinkProfileText(contactConnection: contactConnection, connReqInvitation: connReqInvitation)
.listRowBackground(Color.clear)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
Section("1-time link") {
oneTimeLinkSection(contactConnection: contactConnection, connReqInvitation: connReqInvitation)
VStack {
List {
Section {
if connReqInvitation != "" {
QRCode(uri: connReqInvitation)
} else {
ProgressView()
.progressViewStyle(.circular)
.scaleEffect(2)
.frame(maxWidth: .infinity)
.padding(.vertical)
}
IncognitoToggle(incognitoEnabled: $incognitoDefault)
.disabled(contactConnection == nil)
shareLinkButton(connReqInvitation)
oneTimeLinkLearnMoreButton()
} header: {
Text("1-time link")
} footer: {
sharedProfileInfo(incognitoDefault)
}
}
}
.onAppear { chatModel.connReqInv = connReqInvitation }
.onChange(of: incognitoDefault) { incognito in
Task {
do {
if let contactConn = contactConnection,
let conn = try await apiSetConnectionIncognito(connId: contactConn.pccConnId, incognito: incognito) {
await MainActor.run {
contactConnection = conn
ChatModel.shared.updateContactConnection(conn)
}
}
} catch {
logger.error("apiSetConnectionIncognito error: \(responseError(error))")
}
}
}
}
}
@ViewBuilder func oneTimeLinkSection(contactConnection: PendingContactConnection? = nil, connReqInvitation: String) -> some View {
if connReqInvitation != "" {
QRCode(uri: connReqInvitation)
} else {
ProgressView()
.progressViewStyle(.circular)
.scaleEffect(2)
.frame(maxWidth: .infinity)
.padding(.vertical)
struct IncognitoToggle: View {
@Binding var incognitoEnabled: Bool
@State private var showIncognitoSheet = false
var body: some View {
ZStack(alignment: .leading) {
Image(systemName: incognitoEnabled ? "theatermasks.fill" : "theatermasks")
.frame(maxWidth: 24, maxHeight: 24, alignment: .center)
.foregroundColor(incognitoEnabled ? Color.indigo : .secondary)
.font(.system(size: 14))
Toggle(isOn: $incognitoEnabled) {
HStack(spacing: 6) {
Text("Incognito")
Image(systemName: "info.circle")
.foregroundColor(.accentColor)
.font(.system(size: 14))
}
.onTapGesture {
showIncognitoSheet = true
}
}
.padding(.leading, 36)
}
.sheet(isPresented: $showIncognitoSheet) {
IncognitoHelp()
}
}
shareLinkButton(connReqInvitation)
oneTimeLinkLearnMoreButton()
}
private func shareLinkButton(_ connReqInvitation: String) -> some View {
func sharedProfileInfo(_ incognito: Bool) -> Text {
let name = ChatModel.shared.currentUser?.displayName ?? ""
return Text(
incognito
? "A new random profile will be shared."
: "Your profile **\(name)** will be shared."
)
}
func shareLinkButton(_ connReqInvitation: String) -> some View {
Button {
showShareSheet(items: [connReqInvitation])
} label: {
@@ -65,26 +119,11 @@ func oneTimeLinkLearnMoreButton() -> some View {
}
}
struct OneTimeLinkProfileText: View {
@EnvironmentObject private var chatModel: ChatModel
var contactConnection: PendingContactConnection? = nil
var connReqInvitation: String
var body: some View {
HStack {
if (contactConnection?.incognito ?? chatModel.incognito) {
Image(systemName: "theatermasks").foregroundColor(.indigo)
Text("A random profile will be sent to your contact")
} else {
Image(systemName: "info.circle").foregroundColor(.secondary)
Text("Your chat profile will be sent to your contact")
}
}
}
}
struct AddContactView_Previews: PreviewProvider {
static var previews: some View {
AddContactView(connReqInvitation: "https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FFe5ICmvrm4wkrr6X1LTMii-lhBqLeB76%23MCowBQYDK2VuAyEAdhZZsHpuaAk3Hh1q0uNb_6hGTpuwBIrsp2z9U2T0oC0%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAcz6jJk71InuxA0bOX7OUhddfB8Ov7xwQIlIDeXBRZaOntUU4brU5Y3rBzroZBdQJi0FKdtt_D7I%3D%2CMEIwBQYDK2VvAzkA-hDvk1duBi1hlOr08VWSI-Ou4JNNSQjseY69QyKm7Kgg1zZjbpGfyBqSZ2eqys6xtoV4ZtoQUXQ%3D")
AddContactView(
contactConnection: Binding.constant(PendingContactConnection.getSampleData()),
connReqInvitation: "https://simplex.chat/invitation#/?v=1&smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FFe5ICmvrm4wkrr6X1LTMii-lhBqLeB76%23MCowBQYDK2VuAyEAdhZZsHpuaAk3Hh1q0uNb_6hGTpuwBIrsp2z9U2T0oC0%3D&e2e=v%3D1%26x3dh%3DMEIwBQYDK2VvAzkAcz6jJk71InuxA0bOX7OUhddfB8Ov7xwQIlIDeXBRZaOntUU4brU5Y3rBzroZBdQJi0FKdtt_D7I%3D%2CMEIwBQYDK2VvAzkA-hDvk1duBi1hlOr08VWSI-Ou4JNNSQjseY69QyKm7Kgg1zZjbpGfyBqSZ2eqys6xtoV4ZtoQUXQ%3D"
)
}
}
@@ -47,21 +47,13 @@ struct AddGroupView: View {
.padding(.vertical, 4)
Text("The group is fully decentralized it is visible only to the members.")
.padding(.bottom, 4)
if (m.incognito) {
HStack {
Image(systemName: "info.circle").foregroundColor(.orange).font(.footnote)
Spacer().frame(width: 8)
Text("Incognito mode is not supported here - your main profile will be sent to group members").font(.footnote)
}
.padding(.bottom)
} else {
HStack {
Image(systemName: "info.circle").foregroundColor(.secondary).font(.footnote)
Spacer().frame(width: 8)
Text("Your chat profile will be sent to group members").font(.footnote)
}
.padding(.bottom)
HStack {
Image(systemName: "info.circle").foregroundColor(.secondary).font(.footnote)
Spacer().frame(width: 8)
Text("Your chat profile will be sent to group members").font(.footnote)
}
.padding(.bottom)
ZStack(alignment: .center) {
ZStack(alignment: .topTrailing) {
@@ -7,6 +7,7 @@
//
import SwiftUI
import SimpleXChat
enum CreateLinkTab {
case oneTime
@@ -24,6 +25,7 @@ struct CreateLinkView: View {
@EnvironmentObject var m: ChatModel
@State var selection: CreateLinkTab
@State var connReqInvitation: String = ""
@State var contactConnection: PendingContactConnection? = nil
@State private var creatingConnReq = false
var viaNavLink = false
@@ -39,7 +41,7 @@ struct CreateLinkView: View {
private func createLinkView() -> some View {
TabView(selection: $selection) {
AddContactView(connReqInvitation: connReqInvitation)
AddContactView(contactConnection: $contactConnection, connReqInvitation: connReqInvitation)
.tabItem {
Label(
connReqInvitation == ""
@@ -56,7 +58,7 @@ struct CreateLinkView: View {
.tag(CreateLinkTab.longTerm)
}
.onChange(of: selection) { _ in
if case .oneTime = selection, connReqInvitation == "" && !creatingConnReq {
if case .oneTime = selection, connReqInvitation == "", contactConnection == nil && !creatingConnReq {
createInvitation()
}
}
@@ -69,12 +71,14 @@ struct CreateLinkView: View {
private func createInvitation() {
creatingConnReq = true
Task {
let connReq = await apiAddContact()
await MainActor.run {
if let connReq = connReq {
if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) {
await MainActor.run {
connReqInvitation = connReq
contactConnection = pcc
m.connReqInv = connReq
} else {
}
} else {
await MainActor.run {
creatingConnReq = false
}
}
@@ -10,13 +10,13 @@ import SwiftUI
import SimpleXChat
enum NewChatAction: Identifiable {
case createLink(link: String)
case createLink(link: String, connection: PendingContactConnection)
case connectViaLink
case createGroup
var id: String {
switch self {
case let .createLink(link): return "createLink \(link)"
case let .createLink(link, _): return "createLink \(link)"
case .connectViaLink: return "connectViaLink"
case .createGroup: return "createGroup"
}
@@ -41,8 +41,8 @@ struct NewChatButton: View {
}
.sheet(item: $actionSheet) { sheet in
switch sheet {
case let .createLink(link):
CreateLinkView(selection: .oneTime, connReqInvitation: link)
case let .createLink(link, pcc):
CreateLinkView(selection: .oneTime, connReqInvitation: link, contactConnection: pcc)
case .connectViaLink: ConnectViaLinkView()
case .createGroup: AddGroupView()
}
@@ -51,8 +51,8 @@ struct NewChatButton: View {
func addContactAction() {
Task {
if let connReq = await apiAddContact() {
actionSheet = .createLink(link: connReq)
if let (connReq, pcc) = await apiAddContact(incognito: incognitoGroupDefault.get()) {
actionSheet = .createLink(link: connReq, connection: pcc)
}
}
}
@@ -63,9 +63,9 @@ enum ConnReqType: Equatable {
case invitation
}
func connectViaLink(_ connectionLink: String, _ dismiss: DismissAction? = nil) {
func connectViaLink(_ connectionLink: String, dismiss: DismissAction? = nil, incognito: Bool) {
Task {
if let connReqType = await apiConnect(connReq: connectionLink) {
if let connReqType = await apiConnect(incognito: incognito, connReq: connectionLink) {
DispatchQueue.main.async {
dismiss?()
AlertManager.shared.showAlert(connReqSentAlert(connReqType))
@@ -100,12 +100,12 @@ func checkCRDataGroup(_ crData: CReqClientData) -> Bool {
return crData.type == "group" && crData.groupLinkId != nil
}
func groupLinkAlert(_ connectionLink: String) -> Alert {
func groupLinkAlert(_ connectionLink: String, incognito: Bool) -> Alert {
return Alert(
title: Text("Connect via group link?"),
message: Text("You will join a group this link refers to and connect to its group members."),
primaryButton: .default(Text("Connect")) {
connectViaLink(connectionLink)
primaryButton: .default(Text(incognito ? "Connect incognito" : "Connect")) {
connectViaLink(connectionLink, incognito: incognito)
},
secondaryButton: .cancel()
)
@@ -7,76 +7,77 @@
//
import SwiftUI
import SimpleXChat
struct PasteToConnectView: View {
@EnvironmentObject var chatModel: ChatModel
@Environment(\.dismiss) var dismiss: DismissAction
@State private var connectionLink: String = ""
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
@FocusState private var linkEditorFocused: Bool
var body: some View {
ScrollView {
VStack(alignment: .leading) {
Text("Connect via link")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
.padding(.vertical)
Text("Paste the link you received into the box below to connect with your contact.")
.padding(.bottom, 4)
if (chatModel.incognito) {
HStack {
Image(systemName: "theatermasks").foregroundColor(.indigo).font(.footnote)
Spacer().frame(width: 8)
Text("A random profile will be sent to the contact that you received this link from").font(.footnote)
List {
Text("Connect via link")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
.listRowBackground(Color.clear)
.listRowSeparator(.hidden)
.listRowInsets(EdgeInsets(top: 0, leading: 0, bottom: 0, trailing: 0))
.onTapGesture { linkEditorFocused = false }
Section {
linkEditor()
Button {
if connectionLink == "" {
connectionLink = UIPasteboard.general.string ?? ""
} else {
connectionLink = ""
}
.padding(.bottom)
} else {
HStack {
Image(systemName: "info.circle").foregroundColor(.secondary).font(.footnote)
Spacer().frame(width: 8)
Text("Your profile will be sent to the contact that you received this link from").font(.footnote)
} label: {
if connectionLink == "" {
settingsRow("doc.plaintext") { Text("Paste") }
} else {
settingsRow("multiply") { Text("Clear") }
}
.padding(.bottom)
}
Button {
connect()
} label: {
settingsRow("link") { Text("Connect") }
}
.disabled(connectionLink == "" || connectionLink.trimmingCharacters(in: .whitespaces).firstIndex(of: " ") != nil)
IncognitoToggle(incognitoEnabled: $incognitoDefault)
} footer: {
sharedProfileInfo(incognitoDefault)
+ Text(String("\n\n"))
+ Text("You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.")
}
}
}
private func linkEditor() -> some View {
ZStack {
Group {
if connectionLink.isEmpty {
TextEditor(text: Binding.constant(NSLocalizedString("Paste the link you received to connect with your contact.", comment: "placeholder")))
.foregroundColor(.secondary)
.disabled(true)
}
TextEditor(text: $connectionLink)
.onSubmit(connect)
.textInputAutocapitalization(.never)
.disableAutocorrection(true)
.allowsTightening(false)
.frame(height: 180)
.overlay(
RoundedRectangle(cornerRadius: 10)
.strokeBorder(.secondary, lineWidth: 0.3, antialiased: true)
)
HStack(spacing: 20) {
if connectionLink == "" {
Button {
connectionLink = UIPasteboard.general.string ?? ""
} label: {
Label("Paste", systemImage: "doc.plaintext")
}
} else {
Button {
connectionLink = ""
} label: {
Label("Clear", systemImage: "multiply")
}
}
Spacer()
Button(action: connect, label: {
Label("Connect", systemImage: "link")
})
.disabled(connectionLink == "" || connectionLink.trimmingCharacters(in: .whitespaces).firstIndex(of: " ") != nil)
}
.frame(height: 48)
.padding(.bottom)
Text("You can also connect by clicking the link. If it opens in the browser, click **Open in mobile app** button.")
.focused($linkEditorFocused)
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
.allowsTightening(false)
.padding(.horizontal, -5)
.padding(.top, -8)
.frame(height: 180, alignment: .topLeading)
.frame(maxWidth: .infinity, alignment: .leading)
}
}
@@ -85,9 +86,9 @@ struct PasteToConnectView: View {
if let crData = parseLinkQueryData(link),
checkCRDataGroup(crData) {
dismiss()
AlertManager.shared.showAlert(groupLinkAlert(link))
AlertManager.shared.showAlert(groupLinkAlert(link, incognito: incognitoDefault))
} else {
connectViaLink(link, dismiss)
connectViaLink(link, dismiss: dismiss, incognito: incognitoDefault)
}
}
}
@@ -7,11 +7,12 @@
//
import SwiftUI
import SimpleXChat
import CodeScanner
struct ScanToConnectView: View {
@EnvironmentObject var chatModel: ChatModel
@Environment(\.dismiss) var dismiss: DismissAction
@AppStorage(GROUP_DEFAULT_INCOGNITO, store: groupDefaults) private var incognitoDefault = false
var body: some View {
ScrollView {
@@ -19,34 +20,35 @@ struct ScanToConnectView: View {
Text("Scan QR code")
.font(.largeTitle)
.bold()
.fixedSize(horizontal: false, vertical: true)
.padding(.vertical)
if (chatModel.incognito) {
HStack {
Image(systemName: "theatermasks").foregroundColor(.indigo).font(.footnote)
Spacer().frame(width: 8)
Text("A random profile will be sent to your contact").font(.footnote)
}
.padding(.bottom)
} else {
HStack {
Image(systemName: "info.circle").foregroundColor(.secondary).font(.footnote)
Spacer().frame(width: 8)
Text("Your chat profile will be sent to your contact").font(.footnote)
}
.padding(.bottom)
CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit)
.cornerRadius(12)
IncognitoToggle(incognitoEnabled: $incognitoDefault)
.padding(.horizontal)
.padding(.vertical, 6)
.background(
RoundedRectangle(cornerRadius: 12, style: .continuous)
.fill(Color(uiColor: .systemBackground))
)
.padding(.top)
Group {
sharedProfileInfo(incognitoDefault)
+ Text(String("\n\n"))
+ Text("If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.")
}
ZStack {
CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit)
.border(.gray)
}
.padding(.bottom)
Text("If you cannot meet in person, you can **scan QR code in the video call**, or your contact can share an invitation link.")
.padding(.bottom)
.font(.footnote)
.foregroundColor(.secondary)
.padding(.horizontal)
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
}
.background(Color(.systemGroupedBackground))
}
func processQRCode(_ resp: Result<ScanResult, ScanError>) {
@@ -55,9 +57,9 @@ struct ScanToConnectView: View {
if let crData = parseLinkQueryData(r.string),
checkCRDataGroup(crData) {
dismiss()
AlertManager.shared.showAlert(groupLinkAlert(r.string))
AlertManager.shared.showAlert(groupLinkAlert(r.string, incognito: incognitoDefault))
} else {
Task { connectViaLink(r.string, dismiss) }
Task { connectViaLink(r.string, dismiss: dismiss, incognito: incognitoDefault) }
}
case let .failure(e):
logger.error("ConnectContactView.processQRCode QR code error: \(e.localizedDescription)")
@@ -18,10 +18,9 @@ struct IncognitoHelp: View {
ScrollView {
VStack(alignment: .leading) {
Group {
Text("Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.")
Text("Incognito mode protects your privacy by using a new random profile for each contact.")
Text("It allows having many anonymous connections without any shared data between them in a single chat profile.")
Text("When you share an incognito profile with somebody, this profile will be used for the groups they invite you to.")
Text("To find the profile used for an incognito connection, tap the contact or group name on top of the chat.")
}
.padding(.bottom)
}
@@ -21,6 +21,10 @@ struct PrivacySettings: View {
@State private var contactReceiptsReset = false
@State private var contactReceiptsOverrides = 0
@State private var contactReceiptsDialogue = false
@State private var groupReceipts = false
@State private var groupReceiptsReset = false
@State private var groupReceiptsOverrides = 0
@State private var groupReceiptsDialogue = false
@State private var alert: PrivacySettingsViewAlert?
enum PrivacySettingsViewAlert: Identifiable {
@@ -89,15 +93,15 @@ struct PrivacySettings: View {
settingsRow("person") {
Toggle("Contacts", isOn: $contactReceipts)
}
// settingsRow("person.2") {
// Toggle("Small groups (max 20)", isOn: Binding.constant(false))
// }
settingsRow("person.2") {
Toggle("Small groups (max 20)", isOn: $groupReceipts)
}
} header: {
Text("Send delivery receipts to")
} footer: {
VStack(alignment: .leading) {
Text("These settings are for your current profile **\(ChatModel.shared.currentUser?.displayName ?? "")**.")
Text("They can be overridden in contact settings")
Text("They can be overridden in contact and group settings.")
}
.frame(maxWidth: .infinity, alignment: .leading)
}
@@ -113,19 +117,44 @@ struct PrivacySettings: View {
contactReceipts.toggle()
}
}
.confirmationDialog(groupReceiptsDialogTitle, isPresented: $groupReceiptsDialogue, titleVisibility: .visible) {
Button(groupReceipts ? "Enable (keep overrides)" : "Disable (keep overrides)") {
setSendReceiptsGroups(groupReceipts, clearOverrides: false)
}
Button(contactReceipts ? "Enable for all" : "Disable for all", role: .destructive) {
setSendReceiptsGroups(groupReceipts, clearOverrides: true)
}
Button("Cancel", role: .cancel) {
groupReceiptsReset = true
groupReceipts.toggle()
}
}
}
}
.onChange(of: contactReceipts) { _ in // sometimes there is race with onAppear
.onChange(of: contactReceipts) { _ in
if contactReceiptsReset {
contactReceiptsReset = false
} else {
setOrAskSendReceiptsContacts(contactReceipts)
}
}
.onChange(of: groupReceipts) { _ in
if groupReceiptsReset {
groupReceiptsReset = false
} else {
setOrAskSendReceiptsGroups(groupReceipts)
}
}
.onAppear {
if let u = m.currentUser, contactReceipts != u.sendRcptsContacts {
contactReceiptsReset = true
contactReceipts = u.sendRcptsContacts
if let u = m.currentUser {
if contactReceipts != u.sendRcptsContacts {
contactReceiptsReset = true
contactReceipts = u.sendRcptsContacts
}
if groupReceipts != u.sendRcptsSmallGroups {
groupReceiptsReset = true
groupReceipts = u.sendRcptsSmallGroups
}
}
}
.alert(item: $alert) { alert in
@@ -184,6 +213,54 @@ struct PrivacySettings: View {
}
}
private func setOrAskSendReceiptsGroups(_ enable: Bool) {
groupReceiptsOverrides = m.chats.reduce(0) { count, chat in
let sendRcpts = chat.chatInfo.groupInfo?.chatSettings.sendRcpts
return count + (sendRcpts == nil || sendRcpts == enable ? 0 : 1)
}
if groupReceiptsOverrides == 0 {
setSendReceiptsGroups(enable, clearOverrides: false)
} else {
groupReceiptsDialogue = true
}
}
private var groupReceiptsDialogTitle: LocalizedStringKey {
groupReceipts
? "Sending receipts is disabled for \(groupReceiptsOverrides) groups"
: "Sending receipts is enabled for \(groupReceiptsOverrides) groups"
}
private func setSendReceiptsGroups(_ enable: Bool, clearOverrides: Bool) {
Task {
do {
if let currentUser = m.currentUser {
let userMsgReceiptSettings = UserMsgReceiptSettings(enable: enable, clearOverrides: clearOverrides)
try await apiSetUserGroupReceipts(currentUser.userId, userMsgReceiptSettings: userMsgReceiptSettings)
privacyDeliveryReceiptsSet.set(true)
await MainActor.run {
var updatedUser = currentUser
updatedUser.sendRcptsSmallGroups = enable
m.updateUser(updatedUser)
if clearOverrides {
m.chats.forEach { chat in
if var groupInfo = chat.chatInfo.groupInfo {
let sendRcpts = groupInfo.chatSettings.sendRcpts
if sendRcpts != nil && sendRcpts != enable {
groupInfo.chatSettings.sendRcpts = nil
m.updateGroup(groupInfo)
}
}
}
}
}
}
} catch let error {
alert = .error(title: "Error setting delivery receipts!", error: "Error: \(responseError(error))")
}
}
}
private func simplexLockRow(_ value: LocalizedStringKey) -> some View {
HStack {
Text("SimpleX Lock")
@@ -21,11 +21,10 @@ struct ScanProtocolServer: View {
.font(.largeTitle)
.bold()
.padding(.vertical)
ZStack {
CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit)
.border(.gray)
}
CodeScannerView(codeTypes: [.qr], completion: processQRCode)
.aspectRatio(1, contentMode: .fit)
.cornerRadius(12)
.padding(.top)
}
.padding()
.frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .top)
@@ -131,7 +131,6 @@ struct SettingsView: View {
@EnvironmentObject var chatModel: ChatModel
@EnvironmentObject var sceneDelegate: SceneDelegate
@Binding var showSettings: Bool
@State private var settingsSheet: SettingsSheet?
var body: some View {
ZStack {
@@ -161,8 +160,6 @@ struct SettingsView: View {
settingsRow("person.crop.rectangle.stack") { Text("Your chat profiles") }
}
incognitoRow()
NavigationLink {
UserAddressView(shareViaProfile: chatModel.currentUser!.addressShared)
.navigationTitle("SimpleX address")
@@ -298,39 +295,6 @@ struct SettingsView: View {
}
.navigationTitle("Your settings")
}
.sheet(item: $settingsSheet) { sheet in
switch sheet {
case .incognitoInfo: IncognitoHelp()
}
}
}
@ViewBuilder private func incognitoRow() -> some View {
ZStack(alignment: .leading) {
Image(systemName: chatModel.incognito ? "theatermasks.fill" : "theatermasks")
.frame(maxWidth: 24, maxHeight: 24, alignment: .center)
.foregroundColor(chatModel.incognito ? Color.indigo : .secondary)
Toggle(isOn: $chatModel.incognito) {
HStack(spacing: 6) {
Text("Incognito")
Image(systemName: "info.circle")
.foregroundColor(.accentColor)
.font(.system(size: 14))
}
.onTapGesture {
settingsSheet = .incognitoInfo
}
}
.onChange(of: chatModel.incognito) { incognito in
incognitoGroupDefault.set(incognito)
do {
try apiSetIncognito(incognito: incognito)
} catch {
logger.error("apiSetIncognito: cannot set incognito \(responseError(error))")
}
}
.padding(.leading, indent)
}
}
private func chatDatabaseRow() -> some View {
@@ -351,12 +315,6 @@ struct SettingsView: View {
}
}
private enum SettingsSheet: Identifiable {
case incognitoInfo
var id: SettingsSheet { get { self } }
}
private enum NotificationAlert {
case enable
case error(LocalizedStringKey, String)
@@ -3630,6 +3630,31 @@ SimpleX servers cannot see your profile.</source>
<source>\~strike~</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ servers" xml:space="preserve" approved="no">
<source>%@ servers</source>
<target state="translated">%@ الخوادم</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ (current)" xml:space="preserve" approved="no">
<source>%@ (current)</source>
<target state="translated">%@ (الحالي)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ (current):" xml:space="preserve" approved="no">
<source>%@ (current):</source>
<target state="translated">%@ (الحالي):</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%@:" xml:space="preserve" approved="no">
<source>%@:</source>
<target state="needs-translation">%@:</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve" approved="no">
<source>%1$@ at %2$@:</source>
<target state="translated">%1$@ في %2$@:</target>
<note>copied message info, &lt;sender&gt; at &lt;time&gt;</note>
</trans-unit>
</body>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="ar" datatype="plaintext">
@@ -5,57 +5,71 @@
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
<trans-unit id="&#10;" xml:space="preserve" approved="no">
<source>
</source>
<target state="translated">
</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" " xml:space="preserve">
<trans-unit id=" " xml:space="preserve" approved="no">
<source> </source>
<target state="translated"> </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" " xml:space="preserve">
<trans-unit id=" " xml:space="preserve" approved="no">
<source> </source>
<target state="translated"> </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" " xml:space="preserve">
<trans-unit id=" " xml:space="preserve" approved="no">
<source> </source>
<target state="translated"> </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" (" xml:space="preserve">
<trans-unit id=" (" xml:space="preserve" approved="no">
<source> (</source>
<target state="translated"> (</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" (can be copied)" xml:space="preserve">
<trans-unit id=" (can be copied)" xml:space="preserve" approved="no">
<source> (can be copied)</source>
<target state="translated"> (може да се копира)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="!1 colored!" xml:space="preserve">
<trans-unit id="!1 colored!" xml:space="preserve" approved="no">
<source>!1 colored!</source>
<target state="translated">!1 цветно!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<trans-unit id="#secret#" xml:space="preserve" approved="no">
<source>#secret#</source>
<target state="translated">#тайно#</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@" xml:space="preserve">
<trans-unit id="%@" xml:space="preserve" approved="no">
<source>%@</source>
<target state="translated">%@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ %@" xml:space="preserve">
<trans-unit id="%@ %@" xml:space="preserve" approved="no">
<source>%@ %@</source>
<target state="translated">%@ %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ (current)" xml:space="preserve">
<trans-unit id="%@ (current)" xml:space="preserve" approved="no">
<source>%@ (current)</source>
<target state="translated">%@ (текущ)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ (current):" xml:space="preserve">
<trans-unit id="%@ (current):" xml:space="preserve" approved="no">
<source>%@ (current):</source>
<target state="translated">%@ (текущ):</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%@ / %@" xml:space="preserve">
<trans-unit id="%@ / %@" xml:space="preserve" approved="no">
<source>%@ / %@</source>
<target state="translated">%@ / %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve">
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="cs" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 barevný!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#tajný#</target>
@@ -397,14 +409,8 @@
<target>Nový kontakt</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Náhodný profil bude zaslán kontaktu, od kterého jste obdrželi tento odkaz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Vašemu kontaktu bude zaslán náhodný profil</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,8 +466,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Přijmout kontakt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Přijmout inkognito</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1046,8 +1052,16 @@
<target>Připojit</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Připojit se přes kontaktní odkaz?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1066,8 +1080,8 @@
<target>Připojit se prostřednictvím odkazu / QR kódu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Připojit se jednorázovým odkazem?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1096,11 +1110,6 @@
<target>Chyba spojení (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Žádost o připojení</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Požadavek na připojení byl odeslán!</target>
@@ -1549,6 +1558,10 @@
<target>Smazáno v: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Potvrzení o doručení jsou vypnuté!</target>
@@ -2046,6 +2059,7 @@
</trans-unit>
<trans-unit id="Error setting delivery receipts!" xml:space="preserve">
<source>Error setting delivery receipts!</source>
<target>Chyba nastavování potvrzení o doručení!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error starting chat" xml:space="preserve">
@@ -2255,7 +2269,7 @@
</trans-unit>
<trans-unit id="Full name (optional)" xml:space="preserve">
<source>Full name (optional)</source>
<target>Celé jméno (volitelné)</target>
<target>Celé jméno (volitelně)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Full name:" xml:space="preserve">
@@ -2436,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>Historie</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2546,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>V odpovědi na</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2558,14 +2572,8 @@
<target>Režim inkognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>Zde není podporován režim inkognito - členům skupiny bude zaslán váš hlavní profil</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>Režim inkognito chrání soukromí vašeho hlavního profilového jména a obrázku - pro každý nový kontakt je vytvořen nový náhodný profil.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2640,6 +2648,10 @@
<target>Neplatná adresa serveru!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Platnost pozvánky vypršela!</target>
@@ -2899,7 +2911,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Chyba doručení zprávy</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2986,6 +2998,10 @@
<target>Další vylepšení se chystají již brzy!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Tento kontakt s největší pravděpodobností smazal spojení s vámi.</target>
@@ -3091,6 +3107,10 @@
<target>Žádné kontakty k přidání</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>Žádný token zařízení!</target>
@@ -3345,10 +3365,10 @@
<target>Vložení přijatého odkazu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Vložte odkaz, který jste obdrželi, do pole níže a spojte se se svým kontaktem.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3547,6 +3567,7 @@
</trans-unit>
<trans-unit id="Protocol timeout per KB" xml:space="preserve">
<source>Protocol timeout per KB</source>
<target>Časový limit protokolu na KB</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Push notifications" xml:space="preserve">
@@ -3561,6 +3582,7 @@
</trans-unit>
<trans-unit id="React…" xml:space="preserve">
<source>React…</source>
<target>Reagovat…</target>
<note>chat item menu</note>
</trans-unit>
<trans-unit id="Read" xml:space="preserve">
@@ -3593,6 +3615,10 @@
<target>Přečtěte si více v našem [GitHub repozitáři](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Přijato v</target>
@@ -3615,6 +3641,7 @@
</trans-unit>
<trans-unit id="Receiving address will be changed to a different server. Address change will complete after sender comes online." xml:space="preserve">
<source>Receiving address will be changed to a different server. Address change will complete after sender comes online.</source>
<target>Přijímací adresa bude změněna na jiný server. Změna adresy bude dokončena po připojení odesílatele.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receiving file will be stopped." xml:space="preserve">
@@ -3634,10 +3661,12 @@
</trans-unit>
<trans-unit id="Reconnect all connected servers to force message delivery. It uses additional traffic." xml:space="preserve">
<source>Reconnect all connected servers to force message delivery. It uses additional traffic.</source>
<target>Znovu připojte všechny připojené servery a vynuťte doručení zprávy. Využívá další provoz.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reconnect servers?" xml:space="preserve">
<source>Reconnect servers?</source>
<target>Znovu připojit servery?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Record updated at" xml:space="preserve">
@@ -3660,8 +3689,8 @@
<target>Odmítnout</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Odmítnout kontakt (odesílatel NEBUDE upozorněn)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -3972,6 +4001,7 @@
</trans-unit>
<trans-unit id="Send delivery receipts to" xml:space="preserve">
<source>Send delivery receipts to</source>
<target>Potvrzení o doručení zasílat na</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send direct message" xml:space="preserve">
@@ -4049,11 +4079,19 @@
<target>Odesílání potvrzení o doručení je vypnuto pro %lld kontakty</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>Odesílání potvrzení o doručení je povoleno pro %lld kontakty</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Odesílání přes</target>
@@ -4274,6 +4312,10 @@
<target>Přeskočené zprávy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Během importu došlo k nezávažným chybám - podrobnosti naleznete v chat konzoli.</target>
@@ -4533,6 +4575,7 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
</trans-unit>
<trans-unit id="The second tick we missed! ✅" xml:space="preserve">
<source>The second tick we missed! ✅</source>
<target>Druhé zaškrtnutí jsme přehlédli! ✅</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve">
@@ -4565,8 +4608,8 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<target>Toto nastavení je pro váš aktuální profil **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Mohou být přepsány v nastavení kontaktů</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4585,6 +4628,10 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<target>Tuto akci nelze vzít zpět - váš profil, kontakty, zprávy a soubory budou nenávratně ztraceny.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Tato skupina již neexistuje.</target>
@@ -4605,11 +4652,6 @@ Může se to stát kvůli nějaké chybě, nebo pokud je spojení kompromitován
<target>Pro připojení může váš kontakt naskenovat QR kód, nebo použít odkaz v aplikaci.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Chcete-li najít profil použitý pro inkognito připojení, klepněte na název kontaktu nebo skupiny v horní části chatu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Vytvoření nového připojení</target>
@@ -4690,7 +4732,7 @@ Před zapnutím této funkce budete vyzváni k dokončení ověření.</target>
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Neočekávaná chyba: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4829,6 +4871,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Použijte chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Použít pro nová připojení</target>
@@ -4839,6 +4885,10 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Použít rozhraní volání iOS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Použít server</target>
@@ -5129,8 +5179,8 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Musíte zadat přístupovou frázi při každém spuštění aplikace - není uložena v zařízení.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Pozvali jste svůj kontakt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5259,11 +5309,6 @@ Chcete-li se připojit, požádejte svůj kontakt o vytvoření dalšího odkazu
<target>Váš chat profil bude zaslán členům skupiny</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Váš chat profil bude odeslán vašemu kontaktu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Vaše chat profily</target>
@@ -5318,6 +5363,10 @@ Můžete ji změnit v Nastavení.</target>
<target>Vaše soukromí</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5325,11 +5374,6 @@ SimpleX servers cannot see your profile.</source>
Servery SimpleX nevidí váš profil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Váš profil bude zaslán kontaktu, od kterého jste obdrželi tento odkaz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení.</target>
@@ -5577,10 +5621,12 @@ Servery SimpleX nevidí váš profil.</target>
</trans-unit>
<trans-unit id="default (no)" xml:space="preserve">
<source>default (no)</source>
<target>výchozí (ne)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="default (yes)" xml:space="preserve">
<source>default (yes)</source>
<target>výchozí (ano)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="deleted" xml:space="preserve">
@@ -5603,6 +5649,10 @@ Servery SimpleX nevidí váš profil.</target>
<target>přímo</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>duplicitní zpráva</target>
@@ -6088,7 +6138,7 @@ Servery SimpleX nevidí váš profil.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="cs" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6120,7 +6170,7 @@ Servery SimpleX nevidí váš profil.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="cs" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "cs",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="de" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 farbig!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#geheim#</target>
@@ -397,14 +409,8 @@
<target>Ein neuer Kontakt</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Ein zufälliges Profil wird an den Kontakt gesendet, von dem Sie diesen Link erhalten haben</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Ein zufälliges Profil wird an Ihren Kontakt gesendet</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,8 +466,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Kontakt annehmen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Inkognito akzeptieren</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -542,7 +548,7 @@
</trans-unit>
<trans-unit id="All data is erased when it is entered." xml:space="preserve">
<source>All data is erased when it is entered.</source>
<target>Alle Daten werden gelöscht, sobald diese eingegeben wird.</target>
<target>Alle Daten werden gelöscht, sobald dieser eingegeben wird.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All group members will remain connected." xml:space="preserve">
@@ -572,12 +578,12 @@
</trans-unit>
<trans-unit id="Allow calls only if your contact allows them." xml:space="preserve">
<source>Allow calls only if your contact allows them.</source>
<target>Anrufe sind nur erlaubt, wenn Ihr Kontakt das ebenfalls erlaubt.</target>
<target>Erlauben Sie Anrufe nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow disappearing messages only if your contact allows it to you." xml:space="preserve">
<source>Allow disappearing messages only if your contact allows it to you.</source>
<target>Verschwindende Nachrichten nur erlauben, wenn Ihr Kontakt das ebenfalls erlaubt.</target>
<target>Erlauben Sie verschwindende Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow irreversible message deletion only if your contact allows it to you." xml:space="preserve">
@@ -587,7 +593,7 @@
</trans-unit>
<trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve">
<source>Allow message reactions only if your contact allows them.</source>
<target>Reaktionen auf Nachrichten sind nur möglich, falls Ihr Kontakt dies erlaubt.</target>
<target>Erlauben Sie Reaktionen auf Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow message reactions." xml:space="preserve">
@@ -622,7 +628,7 @@
</trans-unit>
<trans-unit id="Allow voice messages only if your contact allows them." xml:space="preserve">
<source>Allow voice messages only if your contact allows them.</source>
<target>Erlauben Sie Sprachnachrichten nur dann, wenn Ihr Kontakt diese ebenfalls erlaubt.</target>
<target>Erlauben Sie Sprachnachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow voice messages?" xml:space="preserve">
@@ -1046,8 +1052,16 @@
<target>Verbinden</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Über den Kontakt-Link verbinden?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1066,8 +1080,8 @@
<target>Über einen Link / QR-Code verbinden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Über einen Einmal-Link verbinden?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1096,11 +1110,6 @@
<target>Verbindungsfehler (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Verbindungsanfrage</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Verbindungsanfrage wurde gesendet!</target>
@@ -1549,14 +1558,18 @@
<target>Gelöscht um: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Zustellungs-Quittierungen sind deaktiviert!</target>
<target>Empfangsbestätigungen sind deaktiviert!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts!" xml:space="preserve">
<source>Delivery receipts!</source>
<target>Zustellungs-Quittierungen!</target>
<target>Empfangsbestätigungen!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Description" xml:space="preserve">
@@ -2437,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>Vergangenheit</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2547,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>Als Antwort auf</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2572,8 @@
<target>Inkognito Modus</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>Der Inkognito-Modus wird hier nicht unterstützt - Ihr Hauptprofil wird an die Gruppenmitglieder gesendet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>Der Inkognito-Modus schützt die Privatsphäre Ihres Hauptprofilnamens und -bildes für jeden neuen Kontakt wird ein neues Zufallsprofil erstellt.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2648,10 @@
<target>Ungültige Serveradresse!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Einladung abgelaufen!</target>
@@ -2900,7 +2911,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Fehler bei der Nachrichtenzustellung</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2987,6 +2998,10 @@
<target>Weitere Verbesserungen sind bald verfügbar!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Dieser Kontakt hat sehr wahrscheinlich die Verbindung mit Ihnen gelöscht.</target>
@@ -3092,6 +3107,10 @@
<target>Keine Kontakte zum Hinzufügen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>Kein Geräte-Token!</target>
@@ -3346,10 +3365,10 @@
<target>Fügen Sie den erhaltenen Link ein</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Um sich mit Ihrem Kontakt zu verbinden, fügen Sie den erhaltenen Link in das Feld unten ein.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3596,6 +3615,10 @@
<target>Erfahren Sie in unserem [GitHub-Repository](https://github.com/simplex-chat/simplex-chat#readme) mehr dazu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Empfangen um</target>
@@ -3666,8 +3689,8 @@
<target>Ablehnen</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Kontakt ablehnen (der Absender wird NICHT benachrichtigt)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -3978,7 +4001,7 @@
</trans-unit>
<trans-unit id="Send delivery receipts to" xml:space="preserve">
<source>Send delivery receipts to</source>
<target>Zustellungs-Quittierungen versenden an</target>
<target>Empfangsbestätigungen senden an</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send direct message" xml:space="preserve">
@@ -4056,11 +4079,19 @@
<target>Das Senden von Empfangsbestätigungen an %lld Kontakte ist deaktiviert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>Das Senden von Empfangsbestätigungen an %lld Kontakte ist aktiviert</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Senden über</target>
@@ -4281,6 +4312,10 @@
<target>Übersprungene Nachrichten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Während des Imports sind einige nicht schwerwiegende Fehler aufgetreten - in der Chat-Konsole finden Sie weitere Einzelheiten.</target>
@@ -4540,7 +4575,7 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
</trans-unit>
<trans-unit id="The second tick we missed! ✅" xml:space="preserve">
<source>The second tick we missed! ✅</source>
<target>Das zweite Häkchen, welches wir vermisst haben! ✅</target>
<target>Wir haben das zweite Häkchen vermisst! ✅</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The sender will NOT be notified" xml:space="preserve">
@@ -4573,9 +4608,9 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Diese Einstellungen betreffen Ihr aktuelles Profil **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<target>Diese können in den Kontakteinstellungen überschrieben werden</target>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Sie können in den Kontakteinstellungen überschrieben werden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." xml:space="preserve">
@@ -4593,6 +4628,10 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Diese Aktion kann nicht rückgängig gemacht werden! Ihr Profil und Ihre Kontakte, Nachrichten und Dateien gehen unwiderruflich verloren.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Diese Gruppe existiert nicht mehr.</target>
@@ -4613,11 +4652,6 @@ Dies kann passieren, wenn es einen Fehler gegeben hat oder die Verbindung kompro
<target>Um eine Verbindung herzustellen, kann Ihr Kontakt den QR-Code scannen oder den Link in der App verwenden.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Um das für eine Inkognito-Verbindung verwendete Profil zu finden, tippen Sie oben im Chat auf den Kontakt- oder Gruppennamen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Um eine Verbindung mit einem neuen Kontakt zu erstellen</target>
@@ -4698,7 +4732,7 @@ Sie werden aufgefordert, die Authentifizierung abzuschließen, bevor diese Funkt
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Unerwarteter Fehler: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4837,6 +4871,10 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Verwenden Sie Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Für neue Verbindungen nutzen</target>
@@ -4847,6 +4885,10 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>iOS Anrufschnittstelle nutzen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Server nutzen</target>
@@ -5137,8 +5179,8 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Sie müssen das Passwort jedes Mal eingeben, wenn die App startet. Es wird nicht auf dem Gerät gespeichert.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Sie haben Ihren Kontakt eingeladen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5267,11 +5309,6 @@ Bitten Sie Ihren Kontakt darum einen weiteren Verbindungs-Link zu erzeugen, um s
<target>Ihr Chat-Profil wird an Gruppenmitglieder gesendet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Ihr Chat-Profil wird an Ihren Kontakt gesendet</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Meine Chat-Profile</target>
@@ -5326,6 +5363,10 @@ Sie können es in den Einstellungen ändern.</target>
<target>Meine Privatsphäre</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5333,11 +5374,6 @@ SimpleX servers cannot see your profile.</source>
SimpleX-Server können Ihr Profil nicht einsehen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Ihr Profil wird an den Kontakt gesendet, von dem Sie diesen Link erhalten haben</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert.</target>
@@ -5613,6 +5649,10 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
<target>direkt</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>Doppelte Nachricht</target>
@@ -6098,7 +6138,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="de" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6130,7 +6170,7 @@ SimpleX-Server können Ihr Profil nicht einsehen.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="de" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "de",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="en" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,21 @@
<target>!1 colored!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<target># %@</target>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<target>## History</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<target>## In reply to</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#secret#</target>
@@ -397,14 +412,9 @@
<target>A new contact</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>A random profile will be sent to the contact that you received this link from</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>A random profile will be sent to your contact</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<target>A new random profile will be shared.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,9 +470,9 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<target>Accept contact</target>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Accept connection request?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept contact request from %@?" xml:space="preserve">
@@ -473,7 +483,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Accept incognito</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1046,9 +1056,19 @@
<target>Connect</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<target>Connect via contact link?</target>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<target>Connect directly</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<target>Connect incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Connect via contact link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via group link?" xml:space="preserve">
@@ -1066,9 +1086,9 @@
<target>Connect via link / QR code</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<target>Connect via one-time link?</target>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Connect via one-time link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@@ -1096,11 +1116,6 @@
<target>Connection error (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Connection request</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Connection request sent!</target>
@@ -1549,6 +1564,11 @@
<target>Deleted at: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<target>Delivery</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Delivery receipts are disabled!</target>
@@ -2437,7 +2457,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>History</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2547,7 +2567,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>In reply to</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2579,9 @@
<target>Incognito mode</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>Incognito mode is not supported here - your main profile will be sent to group members</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<target>Incognito mode protects your privacy by using a new random profile for each contact.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2656,11 @@
<target>Invalid server address!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<target>Invalid status</target>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Invitation expired!</target>
@@ -2900,7 +2920,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Message delivery error</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2987,6 +3007,11 @@
<target>More improvements are coming soon!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<target>Most likely this connection is deleted.</target>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Most likely this contact has deleted the connection with you.</target>
@@ -3092,6 +3117,11 @@
<target>No contacts to add</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<target>No delivery information</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>No device token!</target>
@@ -3346,10 +3376,10 @@
<target>Paste received link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<target>Paste the link you received into the box below to connect with your contact.</target>
<note>No comment provided by engineer.</note>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Paste the link you received to connect with your contact.</target>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3596,6 +3626,11 @@
<target>Read more in our [GitHub repository](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<target>Receipts are disabled</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Received at</target>
@@ -3666,9 +3701,9 @@
<target>Reject</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<target>Reject contact (sender NOT notified)</target>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Reject (sender NOT notified)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reject contact request" xml:space="preserve">
@@ -4056,11 +4091,21 @@
<target>Sending receipts is disabled for %lld contacts</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<target>Sending receipts is disabled for %lld groups</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>Sending receipts is enabled for %lld contacts</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<target>Sending receipts is enabled for %lld groups</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Sending via</target>
@@ -4281,6 +4326,11 @@
<target>Skipped messages</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<target>Small groups (max 20)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Some non-fatal errors occurred during import - you may see Chat console for more details.</target>
@@ -4573,9 +4623,9 @@ It can happen because of some bug or when the connection is compromised.</target
<target>These settings are for your current profile **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<target>They can be overridden in contact settings</target>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>They can be overridden in contact and group settings.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." xml:space="preserve">
@@ -4593,6 +4643,11 @@ It can happen because of some bug or when the connection is compromised.</target
<target>This action cannot be undone - your profile, contacts, messages and files will be irreversibly lost.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<target>This group has over %lld members, delivery receipts are not sent.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>This group no longer exists.</target>
@@ -4613,11 +4668,6 @@ It can happen because of some bug or when the connection is compromised.</target
<target>To connect, your contact can scan QR code or use the link in the app.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>To make a new connection</target>
@@ -4698,7 +4748,7 @@ You will be prompted to complete authentication before this feature is enabled.<
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Unexpected error: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4837,6 +4887,11 @@ To connect, please ask your contact to create another connection link and check
<target>Use chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<target>Use current profile</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Use for new connections</target>
@@ -4847,6 +4902,11 @@ To connect, please ask your contact to create another connection link and check
<target>Use iOS call interface</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<target>Use new incognito profile</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Use server</target>
@@ -5137,9 +5197,9 @@ To connect, please ask your contact to create another connection link and check
<target>You have to enter passphrase every time the app starts - it is not stored on the device.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<target>You invited your contact</target>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>You invited a contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You joined this group" xml:space="preserve">
@@ -5267,11 +5327,6 @@ To connect, please ask your contact to create another connection link and check
<target>Your chat profile will be sent to group members</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Your chat profile will be sent to your contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Your chat profiles</target>
@@ -5326,6 +5381,11 @@ You can change it in Settings.</target>
<target>Your privacy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<target>Your profile **%@** will be shared.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5333,11 +5393,6 @@ SimpleX servers cannot see your profile.</source>
SimpleX servers cannot see your profile.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Your profile will be sent to the contact that you received this link from</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Your profile, contacts and delivered messages are stored on your device.</target>
@@ -5613,6 +5668,11 @@ SimpleX servers cannot see your profile.</target>
<target>direct</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<target>disabled</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>duplicate message</target>
@@ -6098,7 +6158,7 @@ SimpleX servers cannot see your profile.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="en" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6130,7 +6190,7 @@ SimpleX servers cannot see your profile.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="en" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "en",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="es" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 coloreado!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#secreto#</target>
@@ -397,14 +409,8 @@
<target>Contacto nuevo</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Se enviará un perfil aleatorio al contacto del que recibió este enlace</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Se enviará un perfil aleatorio a tu contacto</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,8 +466,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Aceptar contacto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Aceptar incógnito</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1046,8 +1052,16 @@
<target>Conectar</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>¿Conectar mediante enlace de contacto?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1066,8 +1080,8 @@
<target>Conecta vía enlace / Código QR</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>¿Conectar mediante enlace de un uso?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1096,11 +1110,6 @@
<target>Error conexión (Autenticación)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Solicitud de conexión</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>¡Solicitud de conexión enviada!</target>
@@ -1549,6 +1558,10 @@
<target>Eliminado: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>¡Las confirmaciones de entrega están desactivadas!</target>
@@ -2196,7 +2209,7 @@
</trans-unit>
<trans-unit id="Filter unread and favorite chats." xml:space="preserve">
<source>Filter unread and favorite chats.</source>
<target>Filtrar chats no leídos y favoritos.</target>
<target>Filtra chats no leídos y favoritos.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Finally, we have them! 🚀" xml:space="preserve">
@@ -2206,7 +2219,7 @@
</trans-unit>
<trans-unit id="Find chats faster" xml:space="preserve">
<source>Find chats faster</source>
<target>Encontrar chats mas rápido</target>
<target>Encuentra chats mas rápido</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix" xml:space="preserve">
@@ -2226,7 +2239,7 @@
</trans-unit>
<trans-unit id="Fix encryption after restoring backups." xml:space="preserve">
<source>Fix encryption after restoring backups.</source>
<target>Reparar el cifrado tras restaurar copias de seguridad.</target>
<target>Repara el cifrado tras restaurar copias de seguridad.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix not supported by contact" xml:space="preserve">
@@ -2437,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>Historial</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2547,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>En respuesta a</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2572,8 @@
<target>Modo incógnito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>El modo incógnito no se admite aquí, tu perfil principal aparecerá en miembros del grupo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>La función del modo incógnito es proteger la identidad del perfil principal: por cada contacto nuevo se genera un perfil aleatorio.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2648,10 @@
<target>¡Dirección de servidor no válida!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>¡Invitación caducada!</target>
@@ -2900,7 +2911,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Error en la entrega del mensaje</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2987,6 +2998,10 @@
<target>¡Pronto habrá más mejoras!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Lo más probable es que este contacto haya eliminado la conexión contigo.</target>
@@ -3092,6 +3107,10 @@
<target>Sin contactos que añadir</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>¡Sin dispositivo token!</target>
@@ -3346,10 +3365,10 @@
<target>Pegar enlace recibido</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Pega el enlace que has recibido en el recuadro para conectar con tu contacto.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3493,32 +3512,32 @@
</trans-unit>
<trans-unit id="Prohibit audio/video calls." xml:space="preserve">
<source>Prohibit audio/video calls.</source>
<target>Prohibir las llamadas y videollamadas.</target>
<target>No se permiten llamadas y videollamadas.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit irreversible message deletion." xml:space="preserve">
<source>Prohibit irreversible message deletion.</source>
<target>Prohibir la eliminación irreversible de mensajes.</target>
<target>No se permite la eliminación irreversible de mensajes.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit message reactions." xml:space="preserve">
<source>Prohibit message reactions.</source>
<target>Prohibir reacciones a mensajes.</target>
<target>No se permiten reacciones a los mensajes.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit messages reactions." xml:space="preserve">
<source>Prohibit messages reactions.</source>
<target>Prohibir reacciones a mensajes.</target>
<target>No se permiten reacciones a los mensajes.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit sending direct messages to members." xml:space="preserve">
<source>Prohibit sending direct messages to members.</source>
<target>Prohibir mensajes directos a miembros.</target>
<target>No se permiten mensajes directos entre miembros.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit sending disappearing messages." xml:space="preserve">
<source>Prohibit sending disappearing messages.</source>
<target>Prohibir envío de mensajes temporales.</target>
<target>No se permiten mensajes temporales.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit sending files and media." xml:space="preserve">
@@ -3528,7 +3547,7 @@
</trans-unit>
<trans-unit id="Prohibit sending voice messages." xml:space="preserve">
<source>Prohibit sending voice messages.</source>
<target>Prohibir el envío de mensajes de voz.</target>
<target>No se permiten mensajes de voz.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Protect app screen" xml:space="preserve">
@@ -3538,7 +3557,7 @@
</trans-unit>
<trans-unit id="Protect your chat profiles with a password!" xml:space="preserve">
<source>Protect your chat profiles with a password!</source>
<target>¡Protege tus perfiles de chat con contraseña!</target>
<target>¡Protege tus perfiles con contraseña!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Protocol timeout" xml:space="preserve">
@@ -3553,7 +3572,7 @@
</trans-unit>
<trans-unit id="Push notifications" xml:space="preserve">
<source>Push notifications</source>
<target>Notificaciones push</target>
<target>Notificaciones automáticas</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Rate the app" xml:space="preserve">
@@ -3596,6 +3615,10 @@
<target>Más información en nuestro [repositorio GitHub](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Recibido a las</target>
@@ -3633,7 +3656,7 @@
</trans-unit>
<trans-unit id="Recipients see updates as you type them." xml:space="preserve">
<source>Recipients see updates as you type them.</source>
<target>Los destinatarios ven actualizaciones mientras les escribes.</target>
<target>Los destinatarios ven actualizarse mientras escribes.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reconnect all connected servers to force message delivery. It uses additional traffic." xml:space="preserve">
@@ -3648,17 +3671,17 @@
</trans-unit>
<trans-unit id="Record updated at" xml:space="preserve">
<source>Record updated at</source>
<target>Registro actualizado a las</target>
<target>Registro actualiz.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Record updated at: %@" xml:space="preserve">
<source>Record updated at: %@</source>
<target>Registro actualizado a las: %@</target>
<target>Registro actualiz: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Reduced battery usage" xml:space="preserve">
<source>Reduced battery usage</source>
<target>Uso de la batería reducido</target>
<target>Reducción del uso de batería</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Reject" xml:space="preserve">
@@ -3666,8 +3689,8 @@
<target>Rechazar</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Rechazar contacto (NO se notifica al remitente)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -3703,7 +3726,7 @@
</trans-unit>
<trans-unit id="Remove passphrase from keychain?" xml:space="preserve">
<source>Remove passphrase from keychain?</source>
<target>¿Eliminar la contraseña del llavero?</target>
<target>¿Eliminar contraseña de Keychain?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Renegotiate" xml:space="preserve">
@@ -3848,7 +3871,7 @@
</trans-unit>
<trans-unit id="Save auto-accept settings" xml:space="preserve">
<source>Save auto-accept settings</source>
<target>Guardar configuración de aceptación automática (auto-accept)</target>
<target>Guardar configuración de auto aceptar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Save group profile" xml:space="preserve">
@@ -4056,11 +4079,19 @@
<target>El envío de confirmaciones está desactivado para %lld contactos</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>El envío de confirmaciones está activado para %lld contactos</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Enviando vía</target>
@@ -4281,6 +4312,10 @@
<target>Mensajes omitidos</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Algunos errores no críticos ocurrieron durante la importación - para más detalles puedes ver la consola de Chat.</target>
@@ -4573,8 +4608,8 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
<target>Esta configuración afecta a tu perfil actual **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Se pueden anular en la configuración de contactos</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4593,6 +4628,10 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
<target>Esta acción no se puede deshacer. Tu perfil, contactos, mensajes y archivos se perderán irreversiblemente.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Este grupo ya no existe.</target>
@@ -4613,11 +4652,6 @@ Puede ocurrir por algún bug o cuando la conexión está comprometida.</target>
<target>Para conectarse, tu contacto puede escanear el código QR o usar el enlace en la aplicación.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Para conocer el perfil usado en una conexión en modo incógnito, pulsa el nombre del contacto o del grupo en la parte superior del chat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Para hacer una conexión nueva</target>
@@ -4698,7 +4732,7 @@ Se te pedirá que completes la autenticación antes de activar esta función.</t
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Error inesperado: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4838,6 +4872,10 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb
<target>Usar Chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Usar para conexiones nuevas</target>
@@ -4848,6 +4886,10 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb
<target>Usar interfaz de llamada de iOS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Usar servidor</target>
@@ -5138,8 +5180,8 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb
<target>La contraseña no se almacena en el dispositivo, tienes que introducirla cada vez que inicies la aplicación.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Has invitado a tu contacto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5268,11 +5310,6 @@ Para conectarte, pide a tu contacto que cree otro enlace de conexión y comprueb
<target>Tu perfil Chat será enviado a los miembros del grupo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Tu perfil Chat será enviado a tu contacto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Mis perfiles</target>
@@ -5327,6 +5364,10 @@ Puedes cambiarlo en Configuración.</target>
<target>Privacidad</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5334,11 +5375,6 @@ SimpleX servers cannot see your profile.</source>
Los servidores de SimpleX no pueden ver tu perfil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Tu perfil se enviará al contacto del que has recibido este enlace</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Tu perfil, contactos y mensajes entregados se almacenan en tu dispositivo.</target>
@@ -5614,6 +5650,10 @@ Los servidores de SimpleX no pueden ver tu perfil.</target>
<target>directa</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>mensaje duplicado</target>
@@ -6099,7 +6139,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="es" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6131,7 +6171,7 @@ Los servidores de SimpleX no pueden ver tu perfil.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="es" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "es",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
File diff suppressed because it is too large Load Diff
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="fr" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 coloré!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#secret#</target>
@@ -397,14 +409,8 @@
<target>Un nouveau contact</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Un profil aléatoire sera envoyé au contact qui vous a envoyé ce lien</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Un profil aléatoire sera envoyé à votre contact</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,8 +466,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Accepter le contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Accepter en incognito</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -757,7 +763,7 @@
</trans-unit>
<trans-unit id="Auto-accept" xml:space="preserve">
<source>Auto-accept</source>
<target>Auto-acceptation</target>
<target>Auto-accepter</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Auto-accept contact requests" xml:space="preserve">
@@ -1046,8 +1052,16 @@
<target>Se connecter</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Se connecter via le lien du contact?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1066,9 +1080,9 @@
<target>Se connecter via un lien / code QR</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<target>Se connecter via un lien unique?</target>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Se connecter via le lien du contact?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve">
@@ -1096,11 +1110,6 @@
<target>Erreur de connexion (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Demande de connexion</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Demande de connexion envoyée !</target>
@@ -1268,7 +1277,7 @@
</trans-unit>
<trans-unit id="Database IDs and Transport isolation option." xml:space="preserve">
<source>Database IDs and Transport isolation option.</source>
<target>IDs de base de données et option d'isolation du transport.</target>
<target>IDs de base de données et option d'isolement du transport.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database downgrade" xml:space="preserve">
@@ -1549,6 +1558,10 @@
<target>Supprimé à : %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Les accusés de réception sont désactivés !</target>
@@ -1591,7 +1604,7 @@
</trans-unit>
<trans-unit id="Different names, avatars and transport isolation." xml:space="preserve">
<source>Different names, avatars and transport isolation.</source>
<target>Différents noms, avatars et mode d'isolation de transport.</target>
<target>Différents noms, avatars et modes d'isolement de transport.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Direct messages" xml:space="preserve">
@@ -2437,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>Historique</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2547,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>En réponse à</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2572,8 @@
<target>Mode Incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>Le mode Incognito n'est pas supporté ici - votre profil principal sera envoyé aux membres du groupe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>Le mode Incognito protège la confidentialité de votre profil principal — pour chaque nouveau contact un nouveau profil aléatoire est créé.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2648,10 @@
<target>Adresse de serveur invalide !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Invitation expirée !</target>
@@ -2900,7 +2911,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Erreur de distribution du message</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2987,6 +2998,10 @@
<target>Plus d'améliorations à venir !</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Il est fort probable que ce contact ait supprimé la connexion avec vous.</target>
@@ -3092,6 +3107,10 @@
<target>Aucun contact à ajouter</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>Pas de token d'appareil!</target>
@@ -3346,10 +3365,10 @@
<target>Coller le lien reçu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Collez le lien que vous avez reçu dans le cadre ci-dessous pour vous connecter avec votre contact.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3596,6 +3615,10 @@
<target>Pour en savoir plus, consultez notre [dépôt GitHub](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Reçu à</target>
@@ -3666,8 +3689,8 @@
<target>Rejeter</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Rejeter le contact (l'expéditeur N'en est PAS informé)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -3923,7 +3946,7 @@
</trans-unit>
<trans-unit id="Search" xml:space="preserve">
<source>Search</source>
<target>Chercher</target>
<target>Recherche</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve">
@@ -4056,11 +4079,19 @@
<target>L'envoi d'accusés de réception est désactivé pour %lld contacts</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>L'envoi d'accusés de réception est activé pour %lld contacts</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Envoi via</target>
@@ -4281,6 +4312,10 @@
<target>Messages manqués</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Des erreurs non fatales se sont produites lors de l'importation - vous pouvez consulter la console de chat pour plus de détails.</target>
@@ -4408,7 +4443,7 @@
</trans-unit>
<trans-unit id="Tap to activate profile." xml:space="preserve">
<source>Tap to activate profile.</source>
<target>Appuyez pour activer le profil.</target>
<target>Appuyez pour activer un profil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Tap to join" xml:space="preserve">
@@ -4573,8 +4608,8 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>Ces paramètres s'appliquent à votre profil actuel **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Ils peuvent être remplacés dans les paramètres des contacts</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4593,6 +4628,10 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>Cette action ne peut être annulée - votre profil, vos contacts, vos messages et vos fichiers seront irréversiblement perdus.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Ce groupe n'existe plus.</target>
@@ -4613,11 +4652,6 @@ Cela peut se produire en raison d'un bug ou lorsque la connexion est compromise.
<target>Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l'application.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Pour trouver le profil utilisé lors d'une connexion incognito, appuyez sur le nom du contact ou du groupe en haut du chat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Pour établir une nouvelle connexion</target>
@@ -4662,7 +4696,7 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s
</trans-unit>
<trans-unit id="Transport isolation" xml:space="preserve">
<source>Transport isolation</source>
<target>Isolement du transport</target>
<target>Transport isolé</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Trying to connect to the server used to receive messages from this contact (error: %@)." xml:space="preserve">
@@ -4698,7 +4732,7 @@ Vous serez invité à confirmer l'authentification avant que cette fonction ne s
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Erreur inattendue: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4799,7 +4833,7 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
</trans-unit>
<trans-unit id="Update transport isolation mode?" xml:space="preserve">
<source>Update transport isolation mode?</source>
<target>Mettre à jour le mode d'isolation du transport ?</target>
<target>Mettre à jour le mode d'isolement du transport ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Updating settings will re-connect the client to all servers." xml:space="preserve">
@@ -4837,6 +4871,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Utiliser le chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Utiliser pour les nouvelles connexions</target>
@@ -4847,6 +4885,10 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Utiliser l'interface d'appel d'iOS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Utiliser ce serveur</target>
@@ -5137,8 +5179,8 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Vous devez saisir la phrase secrète à chaque fois que l'application démarre - elle n'est pas stockée sur l'appareil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Vous avez invité votre contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5267,11 +5309,6 @@ Pour vous connecter, veuillez demander à votre contact de créer un autre lien
<target>Votre profil de chat sera envoyé aux membres du groupe</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Votre profil de chat sera envoyé à votre contact</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Vos profils de chat</target>
@@ -5326,6 +5363,10 @@ Vous pouvez modifier ce choix dans les Paramètres.</target>
<target>Votre vie privée</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5333,11 +5374,6 @@ SimpleX servers cannot see your profile.</source>
Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Votre profil sera envoyé au contact qui vous a envoyé ce lien</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil.</target>
@@ -5613,6 +5649,10 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
<target>direct</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>message dupliqué</target>
@@ -6098,7 +6138,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="fr" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6130,7 +6170,7 @@ Les serveurs SimpleX ne peuvent pas voir votre profil.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="fr" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "fr",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -8,7 +8,7 @@
<trans-unit id="&#10;" xml:space="preserve" approved="no">
<source>
</source>
<target state="needs-translation">
<target state="translated">
</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -19,22 +19,22 @@ Available in v5.1</source>
</trans-unit>
<trans-unit id=" " xml:space="preserve" approved="no">
<source> </source>
<target state="needs-translation"> </target>
<target state="translated"> </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" " xml:space="preserve" approved="no">
<source> </source>
<target state="needs-translation"> </target>
<target state="translated"> </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" " xml:space="preserve" approved="no">
<source> </source>
<target state="needs-translation"> </target>
<target state="translated"> </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" (" xml:space="preserve" approved="no">
<source> (</source>
<target state="needs-translation"> (</target>
<target state="translated"> (</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" (can be copied)" xml:space="preserve" approved="no">
@@ -279,7 +279,7 @@ Available in v5.1</source>
</trans-unit>
<trans-unit id=", " xml:space="preserve" approved="no">
<source>, </source>
<target state="needs-translation">, </target>
<target state="translated">, </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="." xml:space="preserve" approved="no">
@@ -4976,6 +4976,11 @@ SimpleX servers cannot see your profile.</source>
<target state="translated">אם תזינו קוד גישה זה בעת פתיחת האפליקציה, כל נתוני האפליקציה יימחקו באופן בלתי הפיך!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve" approved="no">
<source>%1$@ at %2$@:</source>
<target state="translated">%1$@ בזמן %2$@:</target>
<note>copied message info, &lt;sender&gt; at &lt;time&gt;</note>
</trans-unit>
</body>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="he" datatype="plaintext">
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="it" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 colorato!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#segreto#</target>
@@ -397,14 +409,8 @@
<target>Un contatto nuovo</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Verrà inviato un profilo casuale al contatto da cui hai ricevuto questo link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Verrà inviato un profilo casuale al tuo contatto</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,8 +466,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Accetta il contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Accetta in incognito</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1046,8 +1052,16 @@
<target>Connetti</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Connettere via link del contatto?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1066,8 +1080,8 @@
<target>Connetti via link / codice QR</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Connettere via link una tantum?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1096,11 +1110,6 @@
<target>Errore di connessione (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Richiesta di connessione</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Richiesta di connessione inviata!</target>
@@ -1549,6 +1558,10 @@
<target>Eliminato il: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Le ricevute di consegna sono disattivate!</target>
@@ -2437,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>Cronologia</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2547,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>In risposta a</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2572,8 @@
<target>Modalità incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>La modalità in incognito non è supportata qui: il tuo profilo principale verrà inviato ai membri del gruppo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>La modalità in incognito protegge la privacy del nome e dell'immagine del tuo profilo principale: per ogni nuovo contatto viene creato un nuovo profilo casuale.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2648,10 @@
<target>Indirizzo del server non valido!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Invito scaduto!</target>
@@ -2900,7 +2911,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Errore di recapito del messaggio</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2987,6 +2998,10 @@
<target>Altri miglioramenti sono in arrivo!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Probabilmente questo contatto ha eliminato la connessione con te.</target>
@@ -3092,6 +3107,10 @@
<target>Nessun contatto da aggiungere</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>Nessun token del dispositivo!</target>
@@ -3346,10 +3365,10 @@
<target>Incolla il link ricevuto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Incolla il link che hai ricevuto nella casella sottostante per connetterti con il tuo contatto.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3596,6 +3615,10 @@
<target>Maggiori informazioni nel nostro [repository GitHub](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Ricevuto il</target>
@@ -3666,8 +3689,8 @@
<target>Rifiuta</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Rifiuta contatto (mittente NON avvisato)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4056,11 +4079,19 @@
<target>L'invio di ricevute è disattivato per %lld contatti</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>L'invio di ricevute è attivo per %lld contatti</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Invio tramite</target>
@@ -4281,6 +4312,10 @@
<target>Messaggi saltati</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Si sono verificati alcuni errori non gravi durante l'importazione: vedi la console della chat per i dettagli.</target>
@@ -4573,8 +4608,8 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>Queste impostazioni sono per il tuo profilo attuale **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Possono essere sovrascritte nelle impostazioni dei contatti</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4593,6 +4628,10 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>Questa azione non può essere annullata: il tuo profilo, i contatti, i messaggi e i file andranno persi in modo irreversibile.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Questo gruppo non esiste più.</target>
@@ -4613,11 +4652,6 @@ Può accadere a causa di qualche bug o quando la connessione è compromessa.</ta
<target>Per connettervi, il tuo contatto può scansionare il codice QR o usare il link nell'app.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Per trovare il profilo usato per una connessione in incognito, tocca il nome del contatto o del gruppo in cima alla chat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Per creare una nuova connessione</target>
@@ -4698,7 +4732,7 @@ Ti verrà chiesto di completare l'autenticazione prima di attivare questa funzio
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Errore imprevisto: % @</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4837,6 +4871,10 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Usa la chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Usa per connessioni nuove</target>
@@ -4847,6 +4885,10 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Usa interfaccia di chiamata iOS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Usa il server</target>
@@ -5137,8 +5179,8 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Devi inserire la password ogni volta che si avvia l'app: non viene memorizzata sul dispositivo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Hai invitato il contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5267,11 +5309,6 @@ Per connetterti, chiedi al tuo contatto di creare un altro link di connessione e
<target>Il tuo profilo di chat verrà inviato ai membri del gruppo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Il tuo profilo di chat verrà inviato al tuo contatto</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>I tuoi profili di chat</target>
@@ -5326,6 +5363,10 @@ Puoi modificarlo nelle impostazioni.</target>
<target>La tua privacy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5333,11 +5374,6 @@ SimpleX servers cannot see your profile.</source>
I server di SimpleX non possono vedere il tuo profilo.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Il tuo profilo verrà inviato al contatto da cui hai ricevuto questo link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Il tuo profilo, i contatti e i messaggi recapitati sono memorizzati sul tuo dispositivo.</target>
@@ -5613,6 +5649,10 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
<target>diretta</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>messaggio duplicato</target>
@@ -6098,7 +6138,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="it" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6130,7 +6170,7 @@ I server di SimpleX non possono vedere il tuo profilo.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="it" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "it",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="ja" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 色付き!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>シークレット</target>
@@ -392,14 +404,8 @@
<target>新しい連絡先</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>このリンクの送信元にランダムなプロフィール(ダミー)が送られます</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>連絡先にランダムなプロフィール(ダミー)が送られます</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -452,8 +458,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>連絡を受け入れる</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -465,7 +471,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>シークレットモードで承諾</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1035,8 +1041,16 @@
<target>接続</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>連絡先リンク経由で接続しますか?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1055,8 +1069,8 @@
<target>リンク・QRコード経由で接続</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>使い捨てリンク経由で接続しますか?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1085,11 +1099,6 @@
<target>接続エラー (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>接続のリクエスト</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>接続リクエストを送信しました!</target>
@@ -1537,6 +1546,10 @@
<target>削除完了: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<note>No comment provided by engineer.</note>
@@ -2399,7 +2412,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>履歴</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2508,7 +2521,7 @@
</trans-unit>
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2520,14 +2533,8 @@
<target>シークレットモード</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>ここではシークレットモードが無効です。メインのプロフィールがグループのメンバーに送られます</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>シークレットモードとは、メインのプロフィールとプロフィール画像を守るために、新しい連絡先を追加する時に、その連絡先に対してランダムなプロフィールが作成されます。</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2602,6 +2609,10 @@
<target>無効なサーバアドレス!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>招待が期限切れました!</target>
@@ -2859,7 +2870,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>メッセージ送信エラー</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2945,6 +2956,10 @@
<target>まだまだ改善してまいります!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>恐らくこの連絡先があなたとの接続を削除しました。</target>
@@ -3050,6 +3065,10 @@
<target>追加できる連絡先がありません</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>デバイストークンがありません!</target>
@@ -3301,10 +3320,10 @@
<target>頂いたリンクを貼り付ける</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>連絡相手から頂いたリンクを以下の入力欄に貼り付けて繋がります。</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3548,6 +3567,10 @@
<target>詳しくは[GitHubリポジトリ](https://simplex.chat/docs/guide/app-settings.html#your-simplex-contact-address)をご覧ください。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>受信</target>
@@ -3615,8 +3638,8 @@
<target>拒否</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>連絡を拒否(送信者には通知されません)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -3997,10 +4020,18 @@
<source>Sending receipts is disabled for %lld contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>経由で送信</target>
@@ -4221,6 +4252,10 @@
<target>飛ばしたメッセージ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<note>No comment provided by engineer.</note>
@@ -4509,8 +4544,8 @@ It can happen because of some bug or when the connection is compromised.</source
<source>These settings are for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." xml:space="preserve">
@@ -4528,6 +4563,10 @@ It can happen because of some bug or when the connection is compromised.</source
<target>あなたのプロフィール、連絡先、メッセージ、ファイルが完全削除されます (※元に戻せません※)。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>このグループはもう存在しません。</target>
@@ -4548,11 +4587,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>接続するにはQRコードを読み込むか、アプリ内のリンクを使用する必要があります。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>シークレットモード接続のプロフィールを確認するには、チャットの上部の連絡先、またはグループ名をタップします。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>新規に接続する場合</target>
@@ -4633,7 +4667,7 @@ You will be prompted to complete authentication before this feature is enabled.<
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>予期しないエラー: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4771,6 +4805,10 @@ To connect, please ask your contact to create another connection link and check
<target>チャット</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>新しい接続に使う</target>
@@ -4781,6 +4819,10 @@ To connect, please ask your contact to create another connection link and check
<target>iOS通話インターフェースを使用する</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>サーバを使う</target>
@@ -5069,8 +5111,8 @@ To connect, please ask your contact to create another connection link and check
<target>アプリ起動時にパスフレーズを入力しなければなりません。端末に保存されてません。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>連絡先に招待を送りました</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5199,11 +5241,6 @@ To connect, please ask your contact to create another connection link and check
<target>あなたのチャットプロフィールが他のグループメンバーに送られます</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>あなたのチャットプロフィールが連絡相手に送られます</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>あなたのチャットプロフィール</target>
@@ -5258,6 +5295,10 @@ You can change it in Settings.</source>
<target>あなたのプライバシー</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5265,11 +5306,6 @@ SimpleX servers cannot see your profile.</source>
SimpleX サーバーはあなたのプロファイルを参照できません。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>あなたのプロフィールは、このリンクを受け取った連絡先に送信されます</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>あなたのプロフィール、連絡先、送信したメッセージがご自分の端末に保存されます。</target>
@@ -5539,6 +5575,10 @@ SimpleX サーバーはあなたのプロファイルを参照できません。
<target>直接</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>重複メッセージ</target>
@@ -6014,7 +6054,7 @@ SimpleX サーバーはあなたのプロファイルを参照できません。
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="ja" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6046,7 +6086,7 @@ SimpleX サーバーはあなたのプロファイルを参照できません。
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="ja" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "ja",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="nl" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 gekleurd!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#geheim#</target>
@@ -397,14 +409,8 @@
<target>Een nieuw contact</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Er wordt een willekeurig profiel verzonden naar het contact van wie je deze link hebt ontvangen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Er wordt een willekeurig profiel naar uw contactpersoon verzonden</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,8 +466,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Accepteer contactpersoon</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Accepteer incognito</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1046,8 +1052,16 @@
<target>Verbind</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Verbinden via contact link?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1066,8 +1080,8 @@
<target>Maak verbinding via link / QR-code</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Verbinden via een eenmalige link?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1096,11 +1110,6 @@
<target>Verbindingsfout (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Verbindingsverzoek</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Verbindingsverzoek verzonden!</target>
@@ -1549,6 +1558,10 @@
<target>Verwijderd om: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Ontvangstbewijzen zijn uitgeschakeld!</target>
@@ -1641,12 +1654,12 @@
</trans-unit>
<trans-unit id="Disappears at" xml:space="preserve">
<source>Disappears at</source>
<target>Verdwijnt om</target>
<target>Verdwijnt op</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Disappears at: %@" xml:space="preserve">
<source>Disappears at: %@</source>
<target>Verdwijnt om: %@</target>
<target>Verdwijnt op: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Disconnect" xml:space="preserve">
@@ -1961,7 +1974,7 @@
</trans-unit>
<trans-unit id="Error enabling delivery receipts!" xml:space="preserve">
<source>Error enabling delivery receipts!</source>
<target>Fout bij het inschakelen van ontvangstbevestiging!</target>
<target>Fout bij het inschakelen van ontvangst bevestiging!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error enabling notifications" xml:space="preserve">
@@ -2046,7 +2059,7 @@
</trans-unit>
<trans-unit id="Error setting delivery receipts!" xml:space="preserve">
<source>Error setting delivery receipts!</source>
<target>Fout bij het instellen van ontvangstbevestiging!</target>
<target>Fout bij het instellen van ontvangst bevestiging!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error starting chat" xml:space="preserve">
@@ -2161,7 +2174,7 @@
</trans-unit>
<trans-unit id="File will be received when your contact completes uploading it." xml:space="preserve">
<source>File will be received when your contact completes uploading it.</source>
<target>Het bestand wordt ontvangen wanneer uw contactpersoon het uploaden heeft voltooid.</target>
<target>Het bestand wordt gedownload wanneer uw contactpersoon het uploaden heeft voltooid.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="File will be received when your contact is online, please wait or check later!" xml:space="preserve">
@@ -2437,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>Geschiedenis</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2501,7 +2514,7 @@
</trans-unit>
<trans-unit id="Image will be received when your contact completes uploading it." xml:space="preserve">
<source>Image will be received when your contact completes uploading it.</source>
<target>De afbeelding wordt ontvangen wanneer uw contactpersoon het uploaden heeft voltooid.</target>
<target>De afbeelding wordt gedownload wanneer uw contactpersoon het uploaden heeft voltooid.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Image will be received when your contact is online, please wait or check later!" xml:space="preserve">
@@ -2547,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>In antwoord op</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2572,8 @@
<target>Incognito modus</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>Incognito modus wordt hier niet ondersteund, uw hoofdprofiel wordt naar groepsleden verzonden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>De incognito modus beschermt de privacy van uw hoofdprofielnaam en afbeelding, voor elk nieuw contact wordt een nieuw willekeurig profiel gemaakt.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2648,10 @@
<target>Ongeldig server adres!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Uitnodiging verlopen!</target>
@@ -2900,11 +2911,11 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Fout bij bezorging van bericht</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
<target>Ontvangstbevestiging voor berichten!</target>
<target>Ontvangst bevestiging voor berichten!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Message draft" xml:space="preserve">
@@ -2987,6 +2998,10 @@
<target>Meer verbeteringen volgen snel!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Hoogstwaarschijnlijk heeft dit contact de verbinding met jou verwijderd.</target>
@@ -3092,6 +3107,10 @@
<target>Geen contacten om toe te voegen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>Geen apparaattoken!</target>
@@ -3346,10 +3365,10 @@
<target>Plak de ontvangen link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Plak de link die je hebt ontvangen in het vak hieronder om verbinding te maken met je contactpersoon.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3596,6 +3615,10 @@
<target>Lees meer in onze [GitHub-repository](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Ontvangen op</target>
@@ -3666,8 +3689,8 @@
<target>Afwijzen</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Contact afwijzen (afzender NIET op de hoogte)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4038,12 +4061,12 @@
</trans-unit>
<trans-unit id="Sending delivery receipts will be enabled for all contacts in all visible chat profiles." xml:space="preserve">
<source>Sending delivery receipts will be enabled for all contacts in all visible chat profiles.</source>
<target>Het verzenden van ontvangstbevestiging wordt ingeschakeld voor alle contacten in alle zichtbare chatprofielen.</target>
<target>Het verzenden van ontvangst bevestiging wordt ingeschakeld voor alle contacten in alle zichtbare chatprofielen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending delivery receipts will be enabled for all contacts." xml:space="preserve">
<source>Sending delivery receipts will be enabled for all contacts.</source>
<target>Het verzenden van ontvangstbevestiging wordt ingeschakeld voor alle contactpersonen.</target>
<target>Het verzenden van ontvangst bevestiging wordt ingeschakeld voor alle contactpersonen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending file will be stopped." xml:space="preserve">
@@ -4053,12 +4076,20 @@
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is disabled for %lld contacts</source>
<target>Het verzenden van ontvangstbevestiging is uitgeschakeld voor %lld-contactpersonen</target>
<target>Het verzenden van ontvangst bevestiging is uitgeschakeld voor %lld-contactpersonen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>Het verzenden van ontvangstbevestiging is ingeschakeld voor %lld-contactpersonen</target>
<target>Het verzenden van ontvangst bevestiging is ingeschakeld voor %lld-contactpersonen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
@@ -4281,6 +4312,10 @@
<target>Overgeslagen berichten</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Er zijn enkele niet-fatale fouten opgetreden tijdens het importeren - u kunt de Chat console raadplegen voor meer details.</target>
@@ -4573,8 +4608,8 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>Deze instellingen zijn voor uw huidige profiel **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Ze kunnen worden overschreven in contactinstellingen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4593,6 +4628,10 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>Deze actie kan niet ongedaan worden gemaakt. Uw profiel, contacten, berichten en bestanden gaan onomkeerbaar verloren.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Deze groep bestaat niet meer.</target>
@@ -4613,11 +4652,6 @@ Het kan gebeuren vanwege een bug of wanneer de verbinding is aangetast.</target>
<target>Om verbinding te maken, kan uw contact persoon de QR-code scannen of de link in de app gebruiken.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Om het profiel te vinden dat wordt gebruikt voor een incognito verbinding, tikt u op de naam van het contact of de groep bovenaan de chat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Om een nieuwe verbinding te maken</target>
@@ -4698,7 +4732,7 @@ U wordt gevraagd de authenticatie te voltooien voordat deze functie wordt ingesc
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Onverwachte fout: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4837,6 +4871,10 @@ Om verbinding te maken, vraagt u uw contactpersoon om een andere verbinding link
<target>Gebruik chat</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Gebruik voor nieuwe verbindingen</target>
@@ -4847,6 +4885,10 @@ Om verbinding te maken, vraagt u uw contactpersoon om een andere verbinding link
<target>De iOS-oproepinterface gebruiken</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Gebruik server</target>
@@ -4889,7 +4931,7 @@ Om verbinding te maken, vraagt u uw contactpersoon om een andere verbinding link
</trans-unit>
<trans-unit id="Video will be received when your contact completes uploading it." xml:space="preserve">
<source>Video will be received when your contact completes uploading it.</source>
<target>De video wordt ontvangen wanneer uw contactpersoon het uploaden heeft voltooid.</target>
<target>De video wordt gedownload wanneer uw contactpersoon het uploaden heeft voltooid.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Video will be received when your contact is online, please wait or check later!" xml:space="preserve">
@@ -5137,8 +5179,8 @@ Om verbinding te maken, vraagt u uw contactpersoon om een andere verbinding link
<target>U moet elke keer dat de app start het wachtwoord invoeren, deze wordt niet op het apparaat opgeslagen.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Je hebt je contactpersoon uitgenodigd</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5267,11 +5309,6 @@ Om verbinding te maken, vraagt u uw contactpersoon om een andere verbinding link
<target>Uw chat profiel wordt verzonden naar de groepsleden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Uw chat profiel wordt naar uw contactpersoon verzonden</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Uw chat profielen</target>
@@ -5325,6 +5362,10 @@ You can change it in Settings.</source>
<target>Uw privacy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5332,11 +5373,6 @@ SimpleX servers cannot see your profile.</source>
SimpleX servers kunnen uw profiel niet zien.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Je profiel wordt verzonden naar het contact van wie je deze link hebt ontvangen</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Uw profiel, contacten en afgeleverde berichten worden op uw apparaat opgeslagen.</target>
@@ -5612,6 +5648,10 @@ SimpleX servers kunnen uw profiel niet zien.</target>
<target>direct</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>dubbel bericht</target>
@@ -6097,7 +6137,7 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="nl" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6129,7 +6169,7 @@ SimpleX servers kunnen uw profiel niet zien.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="nl" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "nl",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="pl" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 kolorowy!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#sekret#</target>
@@ -397,14 +409,8 @@
<target>Nowy kontakt</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Losowy profil zostanie wysłany do kontaktu, od którego otrzymałeś ten link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Losowy profil zostanie wysłany do Twojego kontaktu</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,8 +466,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Akceptuj kontakt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Akceptuj incognito</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1046,8 +1052,16 @@
<target>Połącz</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Połączyć się przez link kontaktowy?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1066,8 +1080,8 @@
<target>Połącz się przez link / kod QR</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Połączyć się przez jednorazowy link?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1096,11 +1110,6 @@
<target>Błąd połączenia (UWIERZYTELNIANIE)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Prośba o połączenie</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Prośba o połączenie wysłana!</target>
@@ -1549,6 +1558,10 @@
<target>Usunięto o: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Potwierdzenia dostawy są wyłączone!</target>
@@ -2437,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>Historia</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2547,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>W odpowiedzi na</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2572,8 @@
<target>Tryb incognito</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>Tryb Incognito nie jest tutaj obsługiwany - główny profil zostanie wysłany do członków grupy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>Tryb incognito chroni prywatność nazwy i obrazu głównego profilu — dla każdego nowego kontaktu tworzony jest nowy losowy profil.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2648,10 @@
<target>Nieprawidłowy adres serwera!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Zaproszenie wygasło!</target>
@@ -2900,7 +2911,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Błąd dostarczenia wiadomości</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2987,6 +2998,10 @@
<target>Więcej ulepszeń już wkrótce!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Najprawdopodobniej ten kontakt usunął połączenie z Tobą.</target>
@@ -3092,6 +3107,10 @@
<target>Brak kontaktów do dodania</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>Brak tokenu urządzenia!</target>
@@ -3346,10 +3365,10 @@
<target>Wklej otrzymany link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Wklej otrzymany link w pole poniżej, aby połączyć się z kontaktem.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3596,6 +3615,10 @@
<target>Przeczytaj więcej na naszym [repozytorium GitHub](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Otrzymane o</target>
@@ -3666,8 +3689,8 @@
<target>Odrzuć</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Odrzuć kontakt (nadawca NIE został powiadomiony)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4056,11 +4079,19 @@
<target>Wysyłanie potwierdzeń jest wyłączone dla %lld kontaktów</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>Wysyłanie potwierdzeń jest włączone dla %lld kontaktów</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Wysyłanie przez</target>
@@ -4281,6 +4312,10 @@
<target>Pominięte wiadomości</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Podczas importu wystąpiły niekrytyczne błędy - więcej szczegółów można znaleźć w konsoli czatu.</target>
@@ -4573,8 +4608,8 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Te ustawienia dotyczą Twojego bieżącego profilu **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Można je nadpisać w ustawieniach kontaktu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4593,6 +4628,10 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Tego działania nie można cofnąć - Twój profil, kontakty, wiadomości i pliki zostaną nieodwracalnie utracone.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Ta grupa już nie istnieje.</target>
@@ -4613,11 +4652,6 @@ Może się to zdarzyć z powodu jakiegoś błędu lub gdy połączenie jest skom
<target>Aby się połączyć, Twój kontakt może zeskanować kod QR lub skorzystać z linku w aplikacji.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Aby znaleźć profil używany do połączenia incognito, dotknij nazwę kontaktu lub grupy w górnej części czatu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Aby nawiązać nowe połączenie</target>
@@ -4698,7 +4732,7 @@ Przed włączeniem tej funkcji zostanie wyświetlony monit uwierzytelniania.</ta
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Nieoczekiwany błąd: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4837,6 +4871,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Użyj czatu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Użyj dla nowych połączeń</target>
@@ -4847,6 +4885,10 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Użyj interfejsu połączeń iOS</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Użyj serwera</target>
@@ -5137,8 +5179,8 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Musisz wprowadzić hasło przy każdym uruchomieniu aplikacji - nie jest one przechowywane na urządzeniu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Zaprosiłeś swój kontakt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5267,11 +5309,6 @@ Aby się połączyć, poproś Twój kontakt o utworzenie kolejnego linku połąc
<target>Twój profil czatu zostanie wysłany do członków grupy</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Twój profil czatu zostanie wysłany do Twojego kontaktu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Twoje profile czatu</target>
@@ -5326,6 +5363,10 @@ Możesz to zmienić w Ustawieniach.</target>
<target>Twoja prywatność</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5333,11 +5374,6 @@ SimpleX servers cannot see your profile.</source>
Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Twój profil zostanie wysłany do kontaktu, od którego otrzymałeś ten link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu.</target>
@@ -5613,6 +5649,10 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
<target>bezpośredni</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>zduplikowana wiadomość</target>
@@ -6098,7 +6138,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="pl" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6130,7 +6170,7 @@ Serwery SimpleX nie mogą zobaczyć Twojego profilu.</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="pl" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "pl",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="ru" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 цвет!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#секрет#</target>
@@ -397,14 +409,8 @@
<target>Новый контакт</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>Контакту, от которого Вы получили эту ссылку, будет отправлен случайный профиль</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>Вашему контакту будет отправлен случайный профиль</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -460,9 +466,9 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<target>Принять запрос</target>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>Принять запрос?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Accept contact request from %@?" xml:space="preserve">
@@ -473,7 +479,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>Принять инкогнито</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1046,9 +1052,17 @@
<target>Соединиться</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<target>Соединиться через ссылку-контакт?</target>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>Соединиться через ссылку-контакт</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via group link?" xml:space="preserve">
@@ -1066,8 +1080,8 @@
<target>Соединиться через ссылку / QR код</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>Соединиться через одноразовую ссылку?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1096,11 +1110,6 @@
<target>Ошибка соединения (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>Запрос на соединение</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>Запрос на соединение отправлен!</target>
@@ -1549,6 +1558,10 @@
<target>Удалено: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<target>Отчёты о доставке выключены!</target>
@@ -2437,7 +2450,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>История</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2547,7 +2560,7 @@
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<target>В ответ на</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2559,14 +2572,8 @@
<target>Режим Инкогнито</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>Режим Инкогнито здесь не поддерживается - Ваш основной профиль будет отправлен членам группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>Режим Инкогнито защищает конфиденциальность имени и изображения Вашего основного профиля — для каждого нового контакта создается новый случайный профиль.</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2641,6 +2648,10 @@
<target>Ошибка в адресе сервера!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>Приглашение истекло!</target>
@@ -2900,7 +2911,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>Ошибка доставки сообщения</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2987,6 +2998,10 @@
<target>Дополнительные улучшения скоро!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>Скорее всего, этот контакт удалил соединение с Вами.</target>
@@ -3092,6 +3107,10 @@
<target>Нет контактов для добавления</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>Отсутствует токен устройства!</target>
@@ -3346,10 +3365,10 @@
<target>Вставить полученную ссылку</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>Чтобы соединиться, вставьте ссылку, полученную от Вашего контакта.</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3596,6 +3615,10 @@
<target>Узнайте больше из нашего [GitHub репозитория](https://github.com/simplex-chat/simplex-chat#readme).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>Получено</target>
@@ -3666,8 +3689,8 @@
<target>Отклонить</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>Отклонить (не уведомляя отправителя)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4056,11 +4079,19 @@
<target>Отправка отчётов о доставке выключена для %lld контактов</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<target>Отправка отчётов о доставке включена для %lld контактов</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>Отправка через</target>
@@ -4281,6 +4312,10 @@
<target>Пропущенные сообщения</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>Во время импорта произошли некоторые ошибки - для получения более подробной информации вы можете обратиться к консоли.</target>
@@ -4573,9 +4608,9 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Установки для Вашего активного профиля **%@**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<target>Они могут быть переопределены в настройках контактов</target>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<target>Они могут быть переопределены в настройках контактов и групп.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." xml:space="preserve">
@@ -4593,6 +4628,10 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Это действие нельзя отменить — Ваш профиль, контакты, сообщения и файлы будут безвозвратно утеряны.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>Эта группа больше не существует.</target>
@@ -4613,11 +4652,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>Чтобы соединиться с Вами, Ваш контакт может отсканировать QR-код или использовать ссылку в приложении.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>Чтобы найти инкогнито профиль, используемый в разговоре, нажмите на имя контакта или группы в верхней части чата.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>Чтобы соединиться</target>
@@ -4698,7 +4732,7 @@ You will be prompted to complete authentication before this feature is enabled.<
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>Неожиданная ошибка: %@</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4837,6 +4871,10 @@ To connect, please ask your contact to create another connection link and check
<target>Использовать чат</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>Использовать для новых соединений</target>
@@ -4847,6 +4885,10 @@ To connect, please ask your contact to create another connection link and check
<target>Использовать интерфейс iOS для звонков</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>Использовать сервер</target>
@@ -5137,9 +5179,9 @@ To connect, please ask your contact to create another connection link and check
<target>Пароль не сохранен на устройстве — Вы будете должны ввести его при каждом запуске чата.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<target>Вы пригласили Ваш контакт</target>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>Вы пригласили контакт</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You joined this group" xml:space="preserve">
@@ -5267,11 +5309,6 @@ To connect, please ask your contact to create another connection link and check
<target>Ваш профиль чата будет отправлен членам группы</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>Ваш профиль будет отправлен Вашему контакту</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>Ваши профили чата</target>
@@ -5326,6 +5363,10 @@ You can change it in Settings.</source>
<target>Конфиденциальность</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5333,11 +5374,6 @@ SimpleX servers cannot see your profile.</source>
SimpleX серверы не могут получить доступ к Вашему профилю.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>Ваш профиль будет отправлен Вашему контакту.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>Ваш профиль, контакты и доставленные сообщения хранятся на Вашем устройстве.</target>
@@ -5613,6 +5649,10 @@ SimpleX серверы не могут получить доступ к Ваше
<target>прямое</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>повторное сообщение</target>
@@ -6098,7 +6138,7 @@ SimpleX серверы не могут получить доступ к Ваше
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="ru" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6130,7 +6170,7 @@ SimpleX серверы не могут получить доступ к Ваше
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="ru" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "ru",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -84,7 +84,7 @@
</trans-unit>
<trans-unit id="%@ is verified" xml:space="preserve" approved="no">
<source>%@ is verified</source>
<target state="translated">%@ ได้รับการยืนยันแล้ว</target>
<target state="translated">%@ ได้รับการตรวจสอบแล้ว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ servers" xml:space="preserve" approved="no">
@@ -279,7 +279,7 @@
</trans-unit>
<trans-unit id="**e2e encrypted** audio call" xml:space="preserve" approved="no">
<source>**e2e encrypted** audio call</source>
<target state="translated">**encrypted จากต้นจนจบ** โทรด้วยเสียง</target>
<target state="translated">การโทรเสียงแบบ **encrypted จากต้นจนจบ**</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**e2e encrypted** video call" xml:space="preserve" approved="no">
@@ -798,7 +798,7 @@
</trans-unit>
<trans-unit id="Can't invite contacts!" xml:space="preserve" approved="no">
<source>Can't invite contacts!</source>
<target state="translated">ไม่สามารถเชิญผู้ติดต่อทั้งหลายได้!</target>
<target state="translated">ไม่สามารถเชิญผู้ติดต่อได้!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Cancel" xml:space="preserve" approved="no">
@@ -869,7 +869,7 @@
</trans-unit>
<trans-unit id="Chat archive" xml:space="preserve" approved="no">
<source>Chat archive</source>
<target state="translated">ที่เก็บแชทเก่า</target>
<target state="translated">ที่เก็บแชทถาวร</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat console" xml:space="preserve" approved="no">
@@ -894,7 +894,7 @@
</trans-unit>
<trans-unit id="Chat is running" xml:space="preserve" approved="no">
<source>Chat is running</source>
<target state="translated">แชทกําลังทํางานอยู่</target>
<target state="translated">แชทกลังทงานอยู่</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chat is stopped" xml:space="preserve" approved="no">
@@ -904,7 +904,7 @@
</trans-unit>
<trans-unit id="Chat preferences" xml:space="preserve" approved="no">
<source>Chat preferences</source>
<target state="translated">การตั้งค่าการแชท</target>
<target state="translated">ค่ากําหนดในการแชท</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Chats" xml:space="preserve" approved="no">
@@ -1024,7 +1024,7 @@
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve" approved="no">
<source>Connect via one-time link?</source>
<target state="translated">เชื่อมต่อผ่านลิงค์แบบครั้งเดียว?</target>
<target state="translated">เชื่อมต่อผ่านลิงค์แบบใช้ครั้งเดียว?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connecting server…" xml:space="preserve" approved="no">
@@ -1034,7 +1034,7 @@
</trans-unit>
<trans-unit id="Connecting server… (error: %@)" xml:space="preserve" approved="no">
<source>Connecting to server… (error: %@)</source>
<target state="translated">กำลังเชื่อมต่อกับเซิร์ฟเวอร์... (ผิดพลาด: %@)</target>
<target state="translated">กำลังเชื่อมต่อกับเซิร์ฟเวอร์... (ข้อผิดพลาด: %@)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection" xml:space="preserve" approved="no">
@@ -1044,12 +1044,12 @@
</trans-unit>
<trans-unit id="Connection error" xml:space="preserve" approved="no">
<source>Connection error</source>
<target state="translated">การเชื่อมต่อล้มเหลว</target>
<target state="translated">การเชื่อมต่อผิดพลาด</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection error (AUTH)" xml:space="preserve" approved="no">
<source>Connection error (AUTH)</source>
<target state="translated">การเชื่อมต่อล้มเหลว (AUTH)</target>
<target state="translated">การเชื่อมต่อผิดพลาด (AUTH)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve" approved="no">
@@ -1084,7 +1084,7 @@
</trans-unit>
<trans-unit id="Contact hidden:" xml:space="preserve" approved="no">
<source>Contact hidden:</source>
<target state="translated">ซ่อนผู้ติดต่อ:</target>
<target state="translated">ผู้ติดต่อถูกซ่อน:</target>
<note>notification</note>
</trans-unit>
<trans-unit id="Contact is connected" xml:space="preserve" approved="no">
@@ -1104,7 +1104,7 @@
</trans-unit>
<trans-unit id="Contact preferences" xml:space="preserve" approved="no">
<source>Contact preferences</source>
<target state="translated">การตั้งค่าผู้ติดต่อ</target>
<target state="translated">การกําหนดลักษณะการติดต่อ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts can mark messages for deletion; you will be able to view them." xml:space="preserve" approved="no">
@@ -1139,7 +1139,7 @@
</trans-unit>
<trans-unit id="Create an address to let people connect with you." xml:space="preserve" approved="no">
<source>Create an address to let people connect with you.</source>
<target state="translated">สร้างที่อยู่เพื่อให้ผู้คนติดต่อกับคุณ</target>
<target state="translated">สร้างที่อยู่เพื่อให้ผู้อื่นเชื่อมต่อกับคุณ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Create file" xml:space="preserve" approved="no">
@@ -1229,7 +1229,7 @@
</trans-unit>
<trans-unit id="Database encrypted!" xml:space="preserve" approved="no">
<source>Database encrypted!</source>
<target state="translated">encrypt ฐานข้อมูลอย่างปลอดภัยแล้ว!</target>
<target state="translated">ฐานข้อมูลถูก encrypt แล้ว!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Database encryption passphrase will be updated and stored in the keychain.&#10;" xml:space="preserve" approved="no">
@@ -1242,7 +1242,7 @@
<trans-unit id="Database encryption passphrase will be updated.&#10;" xml:space="preserve" approved="no">
<source>Database encryption passphrase will be updated.
</source>
<target state="translated">รหัส encryption ของฐานข้อมูลจะได้รับการอัปเดต
<target state="translated">รหัสผ่าน encryption ของฐานข้อมูลจะได้รับการอัปเดต
</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1307,12 +1307,12 @@
</trans-unit>
<trans-unit id="Decentralized" xml:space="preserve" approved="no">
<source>Decentralized</source>
<target state="translated">กระจายอำนาจ</target>
<target state="translated">กระจายอำนาจแล้ว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Decryption error" xml:space="preserve" approved="no">
<source>Decryption error</source>
<target state="translated">ข้อผิดพลาดในการถอดรหัส</target>
<target state="translated">ข้อผิดพลาดในการ decrypt</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete" xml:space="preserve" approved="no">
@@ -1417,7 +1417,7 @@
</trans-unit>
<trans-unit id="Delete group?" xml:space="preserve" approved="no">
<source>Delete group?</source>
<target state="translated">ลบกลุ่มไหม?</target>
<target state="translated">ลบกลุ่ม?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete invitation" xml:space="preserve" approved="no">
@@ -1452,7 +1452,7 @@
</trans-unit>
<trans-unit id="Delete messages after" xml:space="preserve" approved="no">
<source>Delete messages after</source>
<target state="translated">ลบข้อความทีหลัง</target>
<target state="translated">ลบข้อความหลังจาก</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete old database" xml:space="preserve" approved="no">
@@ -1537,12 +1537,12 @@
</trans-unit>
<trans-unit id="Direct messages" xml:space="preserve" approved="no">
<source>Direct messages</source>
<target state="translated">ข้อความส่วนตัว</target>
<target state="translated">ข้อความโดยตรง</target>
<note>chat feature</note>
</trans-unit>
<trans-unit id="Direct messages between members are prohibited in this group." xml:space="preserve" approved="no">
<source>Direct messages between members are prohibited in this group.</source>
<target state="translated">ข้อความส่วนตัวระหว่างสมาชิกเป็นสิ่งต้องห้ามในกลุ่มนี้</target>
<target state="translated">ข้อความโดยตรงระหว่างสมาชิกเป็นสิ่งต้องห้ามในกลุ่มนี้</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Disable SimpleX Lock" xml:space="preserve" approved="no">
@@ -1662,7 +1662,7 @@
</trans-unit>
<trans-unit id="Enable automatic message deletion?" xml:space="preserve" approved="no">
<source>Enable automatic message deletion?</source>
<target state="translated">เปิดใช้งานการลบข้อความอัตโนมัติไหม?</target>
<target state="translated">เปิดใช้งานการลบข้อความอัตโนมัติ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable instant notifications?" xml:space="preserve" approved="no">
@@ -1937,7 +1937,7 @@
</trans-unit>
<trans-unit id="Error saving user password" xml:space="preserve" approved="no">
<source>Error saving user password</source>
<target state="translated">เกิดข้อผิดพลาดในการบันทึกรหัสผ่านของผู้ใช้</target>
<target state="translated">เกิดข้อผิดพลาดในการบันทึกรหัสผ่านผู้ใช้</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error sending email" xml:space="preserve" approved="no">
@@ -2142,7 +2142,7 @@
</trans-unit>
<trans-unit id="Group invitation is no longer valid, it was removed by sender." xml:space="preserve" approved="no">
<source>Group invitation is no longer valid, it was removed by sender.</source>
<target state="translated">คำเชิญเข้าร่วมกลุ่มใช้ไม่ได้อีกต่อไป คำเชิญถูกลบโดยผู้ส่ง</target>
<target state="translated">คำเชิญเข้าร่วมกลุ่มใช้ไม่ถูกต้องอีกต่อไป คำเชิญถูกลบโดยผู้ส่ง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group link" xml:space="preserve" approved="no">
@@ -2167,7 +2167,7 @@
</trans-unit>
<trans-unit id="Group members can send direct messages." xml:space="preserve" approved="no">
<source>Group members can send direct messages.</source>
<target state="translated">สมาชิกกลุ่มสามารถส่งข้อความส่วนตัวได้</target>
<target state="translated">สมาชิกกลุ่มสามารถส่งข้อความโดยตรงได้</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group members can send disappearing messages." xml:space="preserve" approved="no">
@@ -2187,12 +2187,12 @@
</trans-unit>
<trans-unit id="Group moderation" xml:space="preserve" approved="no">
<source>Group moderation</source>
<target state="translated">การดูแลกลุ่ม</target>
<target state="translated">การกลั่นกรองกลุ่ม</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group preferences" xml:space="preserve" approved="no">
<source>Group preferences</source>
<target state="translated">การตั้งค่ากลุ่ม</target>
<target state="translated">ค่ากําหนดลักษณะกลุ่ม</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group profile" xml:space="preserve" approved="no">
@@ -2312,7 +2312,7 @@
</trans-unit>
<trans-unit id="If you enter your self-destruct passcode while opening the app:" xml:space="preserve" approved="no">
<source>If you enter your self-destruct passcode while opening the app:</source>
<target state="translated">หากคุณใส่รหัสทำลายตัวเองขณะเปิดแอป:</target>
<target state="translated">หากคุณใส่รหัสผ่านทำลายตัวเองขณะเปิดแอป:</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="If you need to use the chat now tap **Do it later** below (you will be offered to migrate the database when you restart the app)." xml:space="preserve" approved="no">
@@ -2342,7 +2342,7 @@
</trans-unit>
<trans-unit id="Immune to spam and abuse" xml:space="preserve" approved="no">
<source>Immune to spam and abuse</source>
<target state="translated">ป้องกันจากสแปมและการละเมิด</target>
<target state="translated">มีภูมิคุ้มกันต่อสแปมและการละเมิด</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Import" xml:space="preserve" approved="no">
@@ -2367,7 +2367,7 @@
</trans-unit>
<trans-unit id="Improved server configuration" xml:space="preserve" approved="no">
<source>Improved server configuration</source>
<target state="translated">ปรับปรุงการตั้งค่าเซิร์ฟเวอร์แล้ว</target>
<target state="translated">ปรับปรุงการกําหนดค่าเซิร์ฟเวอร์แล้ว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve" approved="no">
@@ -2494,7 +2494,7 @@
</trans-unit>
<trans-unit id="Irreversible message deletion is prohibited in this group." xml:space="preserve" approved="no">
<source>Irreversible message deletion is prohibited in this group.</source>
<target state="translated">การลบข้อความแบบกลับไม่ได้เป็นสิ่งที่ห้ามในกลุ่มนี้</target>
<target state="translated">การลบข้อความแบบแก้ไขไม่ได้เป็นสิ่งที่ห้ามในกลุ่มนี้</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="It allows having many anonymous connections without any shared data between them in a single chat profile." xml:space="preserve" approved="no">
@@ -2595,7 +2595,7 @@
</trans-unit>
<trans-unit id="Let's talk in SimpleX Chat" xml:space="preserve" approved="no">
<source>Let's talk in SimpleX Chat</source>
<target state="translated">มาพูดคุยกันใน SimpleX Chat</target>
<target state="translated">มาคุยกันใน SimpleX Chat</target>
<note>email subject</note>
</trans-unit>
<trans-unit id="Light" xml:space="preserve" approved="no">
@@ -2640,7 +2640,7 @@
</trans-unit>
<trans-unit id="Make a private connection" xml:space="preserve" approved="no">
<source>Make a private connection</source>
<target state="translated">สร้างการเชื่อมต่อส่วนตัว</target>
<target state="translated">สร้างการเชื่อมต่อแบบส่วนตัว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Make profile private!" xml:space="preserve" approved="no">
@@ -2675,7 +2675,7 @@
</trans-unit>
<trans-unit id="Mark verified" xml:space="preserve" approved="no">
<source>Mark verified</source>
<target state="translated">ทเครื่องหมายยืนยัน</target>
<target state="translated">ทําเครื่องหมายว่ายืนยันแล้ว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Markdown in messages" xml:space="preserve" approved="no">
@@ -2695,12 +2695,12 @@
</trans-unit>
<trans-unit id="Member role will be changed to &quot;%@&quot;. All group members will be notified." xml:space="preserve" approved="no">
<source>Member role will be changed to "%@". All group members will be notified.</source>
<target state="translated">บทบาทของสมาชิกจะเปลี่ยนเป็น "%@" สมาชิกกลุ่มทั้งหมดจะได้รับแจ้ง</target>
<target state="translated">บทบาทของสมาชิกจะถูกเปลี่ยนเป็น "%@" สมาชิกกลุ่มทั้งหมดจะได้รับแจ้ง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Member role will be changed to &quot;%@&quot;. The member will receive a new invitation." xml:space="preserve" approved="no">
<source>Member role will be changed to "%@". The member will receive a new invitation.</source>
<target state="translated">บทบาทของสมาชิกจะเปลี่ยนเป็น "%@" สมาชิกจะได้รับคำเชิญใหม่</target>
<target state="translated">บทบาทของสมาชิกจะถูกเปลี่ยนเป็น "%@" สมาชิกจะได้รับคำเชิญใหม่</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Member will be removed from group - this cannot be undone!" xml:space="preserve" approved="no">
@@ -2964,7 +2964,7 @@
</trans-unit>
<trans-unit id="One-time invitation link" xml:space="preserve" approved="no">
<source>One-time invitation link</source>
<target state="translated">ลิงก์คำเชิญแบบครั้งเดียว</target>
<target state="translated">ลิงก์คำเชิญแบบใช้ครั้งเดียว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Onion hosts will be required for connection. Requires enabling VPN." xml:space="preserve" approved="no">
@@ -2989,7 +2989,7 @@
</trans-unit>
<trans-unit id="Only group owners can change group preferences." xml:space="preserve" approved="no">
<source>Only group owners can change group preferences.</source>
<target state="translated">เฉพาะเจ้าของกลุ่มเท่านั้นที่สามารถเปลี่ยนการตั้งค่ากลุ่มได้</target>
<target state="translated">เฉพาะเจ้าของกลุ่มเท่านั้นที่สามารถเปลี่ยนค่ากําหนดลักษณะกลุ่มได้</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only group owners can enable voice messages." xml:space="preserve" approved="no">
@@ -3229,7 +3229,7 @@
</trans-unit>
<trans-unit id="Preserve the last message draft, with attachments." xml:space="preserve" approved="no">
<source>Preserve the last message draft, with attachments.</source>
<target state="translated">เก็บร่างข้อความล่าสุดพร้อมไฟล์แนบ</target>
<target state="translated">เก็บข้อความที่ร่างไว้ล่าสุดพร้อมไฟล์แนบ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Preset server" xml:space="preserve" approved="no">
@@ -3304,7 +3304,7 @@
</trans-unit>
<trans-unit id="Prohibit sending direct messages to members." xml:space="preserve" approved="no">
<source>Prohibit sending direct messages to members.</source>
<target state="translated">ห้ามส่งข้อความส่วนตัวถึงสมาชิก</target>
<target state="translated">ห้ามส่งข้อความโดยตรงถึงสมาชิก</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Prohibit sending disappearing messages." xml:space="preserve" approved="no">
@@ -3774,7 +3774,7 @@
</trans-unit>
<trans-unit id="Sender may have deleted the connection request." xml:space="preserve" approved="no">
<source>Sender may have deleted the connection request.</source>
<target state="translated">ผู้ส่งอาจลบคําขอการเชื่อมต่อ</target>
<target state="translated">ผู้ส่งอาจลบคําขอการเชื่อมต่อแล้ว</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending file will be stopped." xml:space="preserve" approved="no">
@@ -3849,7 +3849,7 @@
</trans-unit>
<trans-unit id="Set it instead of system authentication." xml:space="preserve" approved="no">
<source>Set it instead of system authentication.</source>
<target state="translated">ตั้งค่าแทนการรับรองความถูกต้องของระบบ</target>
<target state="translated">ตั้งแทนการรับรองความถูกต้องของระบบ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Set passcode" xml:space="preserve" approved="no">
@@ -3859,12 +3859,12 @@
</trans-unit>
<trans-unit id="Set passphrase to export" xml:space="preserve" approved="no">
<source>Set passphrase to export</source>
<target state="translated">ตั้งค่ารหัสผ่านเพื่อส่งออก</target>
<target state="translated">ตั้งรหัสผ่านเพื่อส่งออก</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Set the message shown to new members!" xml:space="preserve" approved="no">
<source>Set the message shown to new members!</source>
<target state="translated">ตั้งค่าข้อความที่แสดงต่อสมาชิกใหม่!</target>
<target state="translated">ตั้งข้อความที่แสดงต่อสมาชิกใหม่!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Set timeouts for proxy/VPN" xml:space="preserve" approved="no">
@@ -4079,7 +4079,7 @@
</trans-unit>
<trans-unit id="Support SimpleX Chat" xml:space="preserve" approved="no">
<source>Support SimpleX Chat</source>
<target state="translated">สนับสนุนแชท SimpleX</target>
<target state="translated">สนับสนุน SimpleX แชท</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="System" xml:space="preserve" approved="no">
@@ -4353,7 +4353,7 @@ You will be prompted to complete authentication before this feature is enabled.<
</trans-unit>
<trans-unit id="To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page." xml:space="preserve" approved="no">
<source>To reveal your hidden profile, enter a full password into a search field in **Your chat profiles** page.</source>
<target state="translated">หากต้องการเปิดเผยโปรไฟล์ที่ซ่อนอยู่ ให้ป้อนรหัสผ่านแบบเต็มในช่องค้นหาในหน้า **โปรไฟล์แชทของคุณ**</target>
<target state="translated">หากต้องการเปิดเผยโปรไฟล์ที่ซ่อนอยู่ของคุณ ให้ป้อนรหัสผ่านแบบเต็มในช่องค้นหาในหน้า **โปรไฟล์แชทของคุณ**</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To support instant push notifications the chat database has to be migrated." xml:space="preserve" approved="no">
@@ -4690,7 +4690,7 @@ To connect, please ask your contact to create another connection link and check
</trans-unit>
<trans-unit id="With optional welcome message." xml:space="preserve" approved="no">
<source>With optional welcome message.</source>
<target state="translated">พร้อมข้อความต้อนรับเพิ่มเติม</target>
<target state="translated">พร้อมข้อความต้อนรับที่ไม่บังคับ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Wrong database passphrase" xml:space="preserve" approved="no">
@@ -4815,7 +4815,7 @@ SimpleX Lock must be enabled.</source>
</trans-unit>
<trans-unit id="You could not be verified; please try again." xml:space="preserve" approved="no">
<source>You could not be verified; please try again.</source>
<target state="translated">เราไม่สามารถยืนยันคุณได้ กรุณาลองอีกครั้ง.</target>
<target state="translated">เราไม่สามารถตรวจสอบคุณได้ กรุณาลองอีกครั้ง.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You have no chats" xml:space="preserve" approved="no">
@@ -5145,12 +5145,12 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="changed address for you" xml:space="preserve" approved="no">
<source>changed address for you</source>
<target state="translated">เปลี่ยนที่อยู่สําหรับคุณ</target>
<target state="translated">เปลี่ยนที่อยู่สําหรับคุณแล้ว</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="changed role of %@ to %@" xml:space="preserve" approved="no">
<source>changed role of %1$@ to %2$@</source>
<target state="translated">เปลี่ยนบทบาทของ %1$@ เป็น %2$@</target>
<target state="translated">เปลี่ยนบทบาทของ %1$@ เป็น %2$@ แล้ว</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="changed your role to %@" xml:space="preserve" approved="no">
@@ -5205,7 +5205,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="connecting (introduced)" xml:space="preserve" approved="no">
<source>connecting (introduced)</source>
<target state="translated">กำลังการเชื่อมต่อ (แนะนําแล้ว)</target>
<target state="translated">กำลังเชื่อมต่อ (แนะนํา)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="connecting (introduction invitation)" xml:space="preserve" approved="no">
@@ -5255,7 +5255,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="database version is newer than the app, but no down migration for: %@" xml:space="preserve" approved="no">
<source>database version is newer than the app, but no down migration for: %@</source>
<target state="translated">เวอร์ชันฐานข้อมูลใหม่กว่าแอป แต่ไม่มีการย้ายข้อมูลสำหรับ: %@</target>
<target state="translated">เวอร์ชันฐานข้อมูลใหม่กว่าแอป แต่ไม่มีการย้ายข้อมูลลงสำหรับ: %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="days" xml:space="preserve" approved="no">
@@ -5365,7 +5365,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="incognito via one-time link" xml:space="preserve" approved="no">
<source>incognito via one-time link</source>
<target state="translated">ไม่ระบุตัวตนผ่านลิงก์แบบครั้งเดียว</target>
<target state="translated">ไม่ระบุตัวตนผ่านลิงก์แบบใช้ครั้งเดียว</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="indirect (%d)" xml:space="preserve" approved="no">
@@ -5410,7 +5410,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="invited via your group link" xml:space="preserve" approved="no">
<source>invited via your group link</source>
<target state="translated">เชิญผ่านลิงค์กลุ่มของคุณ</target>
<target state="translated">ถูกเชิญผ่านลิงค์กลุ่มของคุณ</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="italic" xml:space="preserve" approved="no">
@@ -5511,12 +5511,12 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="offered %@" xml:space="preserve" approved="no">
<source>offered %@</source>
<target state="translated">เสนอ %@</target>
<target state="translated">เสนอแล้ว %@</target>
<note>feature offered item</note>
</trans-unit>
<trans-unit id="offered %@: %@" xml:space="preserve" approved="no">
<source>offered %1$@: %2$@</source>
<target state="translated">เสนอ %1$@: %2$@</target>
<target state="translated">เสนอแล้ว %1$@: %2$@</target>
<note>feature offered item</note>
</trans-unit>
<trans-unit id="on" xml:space="preserve" approved="no">
@@ -5586,7 +5586,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="starting…" xml:space="preserve" approved="no">
<source>starting…</source>
<target state="translated">เริ่มต้น…</target>
<target state="translated">กำลังเริ่มต้น…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="strike" xml:space="preserve" approved="no">
@@ -5626,7 +5626,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="via one-time link" xml:space="preserve" approved="no">
<source>via one-time link</source>
<target state="translated">ผ่านลิงค์แบบครั้งเดียว</target>
<target state="translated">ผ่านลิงค์แบบใช้ครั้งเดียว</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via relay" xml:space="preserve" approved="no">
@@ -5676,7 +5676,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve" approved="no">
<source>you changed address</source>
<target state="translated">คุณเปลี่ยนที่อยู่</target>
<target state="translated">คุณเปลี่ยนที่อยู่แล้ว</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="you changed address for %@" xml:space="preserve" approved="no">
@@ -5706,12 +5706,12 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="you shared one-time link" xml:space="preserve" approved="no">
<source>you shared one-time link</source>
<target state="translated">คุณแชร์ลิงก์แบบใช้ครั้งเดียว</target>
<target state="translated">คุณแชร์ลิงก์แบบใช้ครั้งเดียวแล้ว</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="you shared one-time link incognito" xml:space="preserve" approved="no">
<source>you shared one-time link incognito</source>
<target state="translated">คุณแชร์ลิงก์แบบใช้ครั้งเดียวโดยไม่ระบุตัวตน</target>
<target state="translated">คุณแชร์ลิงก์แบบใช้ครั้งเดียวโดยไม่ระบุตัวตนแล้ว</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve" approved="no">
@@ -5806,7 +5806,7 @@ SimpleX servers cannot see your profile.</source>
</trans-unit>
<trans-unit id="Receiving address will be changed to a different server. Address change will complete after sender comes online." xml:space="preserve" approved="no">
<source>Receiving address will be changed to a different server. Address change will complete after sender comes online.</source>
<target state="translated">คุณลักษณะนี้เป็นการทดลอง! จะใช้งานได้ก็ต่อเมื่อลูกค้าอื่นติดตั้งเวอร์ชัน 4.2 คุณควรเห็นข้อความในการสนทนาเมื่อการเปลี่ยนแปลงที่อยู่เสร็จสิ้น – โปรดตรวจสอบว่าคุณยังคงสามารถรับข้อความจากผู้ติดต่อนี้ (หรือสมาชิกในกลุ่ม)</target>
<target state="translated">ที่อยู่ผู้รับจะถูกเปลี่ยนเป็นเซิร์ฟเวอร์อื่น การเปลี่ยนแปลงที่อยู่จะเสร็จสมบูรณ์หลังจากที่ผู้ส่งออนไลน์</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unfav." xml:space="preserve" approved="no">
@@ -5814,6 +5814,330 @@ SimpleX servers cannot see your profile.</source>
<target state="translated">เลิกชอบ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Make one message disappear" xml:space="preserve" approved="no">
<source>Make one message disappear</source>
<target state="translated">ทำให้ข้อความหายไปหนึ่งข้อความ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="React…" xml:space="preserve" approved="no">
<source>React…</source>
<target state="translated">ตอบสนอง…</target>
<note>chat item menu</note>
</trans-unit>
<trans-unit id="Reconnect all connected servers to force message delivery. It uses additional traffic." xml:space="preserve" approved="no">
<source>Reconnect all connected servers to force message delivery. It uses additional traffic.</source>
<target state="translated">เชื่อมต่อเซิร์ฟเวอร์ที่เชื่อมต่อทั้งหมดอีกครั้งเพื่อบังคับให้ส่งข้อความ มันใช้การจราจรเพิ่มเติม</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send delivery receipts to" xml:space="preserve" approved="no">
<source>Send delivery receipts to</source>
<target state="translated">ส่งใบเสร็จรับการจัดส่งข้อความไปที่</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send receipts" xml:space="preserve" approved="no">
<source>Send receipts</source>
<target state="translated">ส่งใบเสร็จ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve" approved="no">
<source>Sending receipts is enabled for %lld contacts</source>
<target state="translated">การส่งใบเสร็จถูกเปิดใช้งานสำหรับผู้ติดต่อ %lld</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The encryption is working and the new encryption agreement is not required. It may result in connection errors!" xml:space="preserve" approved="no">
<source>The encryption is working and the new encryption agreement is not required. It may result in connection errors!</source>
<target state="translated">encryption กำลังทำงานและไม่จำเป็นต้องใช้ข้อตกลง encryption ใหม่ อาจทำให้การเชื่อมต่อผิดพลาดได้!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="The second tick we missed! ✅" xml:space="preserve" approved="no">
<source>The second tick we missed! ✅</source>
<target state="translated">ขีดที่สองที่เราพลาด! ✅</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A few more things" xml:space="preserve" approved="no">
<source>A few more things</source>
<target state="translated">อีกสองสามอย่าง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Contacts" xml:space="preserve" approved="no">
<source>Contacts</source>
<target state="translated">ติดต่อ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Disable for all" xml:space="preserve" approved="no">
<source>Disable for all</source>
<target state="translated">ปิดการใช้งานสำหรับทุกคน</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error enabling delivery receipts!" xml:space="preserve" approved="no">
<source>Error enabling delivery receipts!</source>
<target state="translated">เกิดข้อผิดพลาดในการเปิดใช้ใบเสร็จการจัดส่ง!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Find chats faster" xml:space="preserve" approved="no">
<source>Find chats faster</source>
<target state="translated">ค้นหาแชทได้เร็วขึ้น</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Filter unread and favorite chats." xml:space="preserve" approved="no">
<source>Filter unread and favorite chats.</source>
<target state="translated">กรองแชทที่ยังไม่อ่านและแชทโปรด</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix" xml:space="preserve" approved="no">
<source>Fix</source>
<target state="translated">แก้ไข</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can enable later via Settings" xml:space="preserve" approved="no">
<source>You can enable later via Settings</source>
<target state="translated">คุณสามารถเปิดใช้งานในภายหลังผ่านการตั้งค่า</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You can enable them later via app Privacy &amp; Security settings." xml:space="preserve" approved="no">
<source>You can enable them later via app Privacy &amp; Security settings.</source>
<target state="translated">คุณสามารถเปิดใช้งานได้ในภายหลังผ่านการตั้งค่าความเป็นส่วนตัวและความปลอดภัยของแอป</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="changing address for %@…" xml:space="preserve" approved="no">
<source>changing address for %@…</source>
<target state="translated">เปลี่ยนที่อยู่สำหรับ %@…</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="changing address…" xml:space="preserve" approved="no">
<source>changing address…</source>
<target state="translated">กำลังเปลี่ยนที่อยู่…</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="encryption ok" xml:space="preserve" approved="no">
<source>encryption ok</source>
<target state="translated">encryptionใช้ได้</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="encryption re-negotiation required" xml:space="preserve" approved="no">
<source>encryption re-negotiation required</source>
<target state="translated">จำเป็นต้องมีการเจรจา encryption อีกครั้ง</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="encryption re-negotiation required for %@" xml:space="preserve" approved="no">
<source>encryption re-negotiation required for %@</source>
<target state="translated">จำเป็นต้องมีการเจรจา encryption อีกครั้งสําหรับ %@</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="security code changed" xml:space="preserve" approved="no">
<source>security code changed</source>
<target state="translated">เปลี่ยนรหัสความปลอดภัยแล้ว</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="Disable (keep overrides)" xml:space="preserve" approved="no">
<source>Disable (keep overrides)</source>
<target state="translated">ปิดใช้งาน (เก็บการแทนที่)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix connection" xml:space="preserve" approved="no">
<source>Fix connection</source>
<target state="translated">แก้ไขการเชื่อมต่อ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="- more stable message delivery.&#10;- a bit better groups.&#10;- and more!" xml:space="preserve" approved="no">
<source>- more stable message delivery.
- a bit better groups.
- and more!</source>
<target state="translated">- การส่งข้อความมีเสถียรภาพมากขึ้น
- กลุ่มที่ดีขึ้นเล็กน้อย
- และอื่น ๆ!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Don't enable" xml:space="preserve" approved="no">
<source>Don't enable</source>
<target state="translated">อย่าเปิดใช้งาน</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Even when disabled in the conversation." xml:space="preserve" approved="no">
<source>Even when disabled in the conversation.</source>
<target state="translated">แม้ในขณะที่ปิดใช้งานในการสนทนา</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable (keep overrides)" xml:space="preserve" approved="no">
<source>Enable (keep overrides)</source>
<target state="translated">เปิดใช้งาน (เก็บการแทนที่)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Enable for all" xml:space="preserve" approved="no">
<source>Enable for all</source>
<target state="translated">เปิดใช้งานสําหรับทุกคน</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error setting delivery receipts!" xml:space="preserve" approved="no">
<source>Error setting delivery receipts!</source>
<target state="translated">เกิดข้อผิดพลาดในการตั้งค่าใบตอบรับการจัดส่ง!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix encryption after restoring backups." xml:space="preserve" approved="no">
<source>Fix encryption after restoring backups.</source>
<target state="translated">แก้ไข encryption หลังจากกู้คืนข้อมูลสำรอง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="encryption re-negotiation allowed for %@" xml:space="preserve" approved="no">
<source>encryption re-negotiation allowed for %@</source>
<target state="translated">อนุญาตให้มีการเจรจา encryption อีกครั้งสําหรับ %@</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="Exporting database archive…" xml:space="preserve" approved="no">
<source>Exporting database archive…</source>
<target state="translated">กำลังส่งออกที่เก็บถาวรฐานข้อมูล…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix connection?" xml:space="preserve" approved="no">
<source>Fix connection?</source>
<target state="translated">แก้ไขการเชื่อมต่อ?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix not supported by contact" xml:space="preserve" approved="no">
<source>Fix not supported by contact</source>
<target state="translated">การแก้ไขไม่รองรับโดยผู้ติดต่อ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Fix not supported by group member" xml:space="preserve" approved="no">
<source>Fix not supported by group member</source>
<target state="translated">การแก้ไขไม่สนับสนุนโดยสมาชิกกลุ่ม</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="In reply to" xml:space="preserve" approved="no">
<source>In reply to</source>
<target state="translated">ในการตอบกลับถึง</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Keep your connections" xml:space="preserve" approved="no">
<source>Keep your connections</source>
<target state="translated">รักษาการเชื่อมต่อของคุณ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve" approved="no">
<source>Message delivery receipts!</source>
<target state="translated">ใบเสร็จการส่งข้อความ!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Renegotiate" xml:space="preserve" approved="no">
<source>Renegotiate</source>
<target state="translated">เจรจาใหม่</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Migrating database archive…" xml:space="preserve" approved="no">
<source>Migrating database archive…</source>
<target state="translated">กำลังย้ายข้อมูลที่เก็บถาวรของฐานข้อมูล…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No history" xml:space="preserve" approved="no">
<source>No history</source>
<target state="translated">ไม่มีประวัติ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Protocol timeout per KB" xml:space="preserve" approved="no">
<source>Protocol timeout per KB</source>
<target state="translated">การหมดเวลาของโปรโตคอลต่อ KB</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="agreeing encryption for %@…" xml:space="preserve" approved="no">
<source>agreeing encryption for %@…</source>
<target state="translated">ยอมรับ encryption สำหรับ %@…</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="agreeing encryption…" xml:space="preserve" approved="no">
<source>agreeing encryption…</source>
<target state="translated">เห็นด้วยกับการ encryption…</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="Reconnect servers?" xml:space="preserve" approved="no">
<source>Reconnect servers?</source>
<target state="translated">เชื่อมต่อเซิร์ฟเวอร์อีกครั้งหรือไม่?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Renegotiate encryption" xml:space="preserve" approved="no">
<source>Renegotiate encryption</source>
<target state="translated">เจรจา encryption อีกครั้ง</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Renegotiate encryption?" xml:space="preserve" approved="no">
<source>Renegotiate encryption?</source>
<target state="translated">เจรจา enryption ใหม่หรือไม่?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending delivery receipts will be enabled for all contacts in all visible chat profiles." xml:space="preserve" approved="no">
<source>Sending delivery receipts will be enabled for all contacts in all visible chat profiles.</source>
<target state="translated">การส่งใบเสร็จรับการจัดส่งข้อความจะถูกเปิดในโปรไฟล์แชทที่มองเห็นได้ทั้งหมด</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="default (yes)" xml:space="preserve" approved="no">
<source>default (yes)</source>
<target state="translated">ค่าเริ่มต้น (ใช่)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="encryption agreed for %@" xml:space="preserve" approved="no">
<source>encryption agreed for %@</source>
<target state="translated">ตกลง encryption สําหรับ % @</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="encryption re-negotiation allowed" xml:space="preserve" approved="no">
<source>encryption re-negotiation allowed</source>
<target state="translated">อนุญาตให้มีการเจรจา encryption อีกครั้ง</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="Sending delivery receipts will be enabled for all contacts." xml:space="preserve" approved="no">
<source>Sending delivery receipts will be enabled for all contacts.</source>
<target state="translated">การส่งใบเสร็จรับการจัดส่งข้อความจะถูกเปิด</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld contacts" xml:space="preserve" approved="no">
<source>Sending receipts is disabled for %lld contacts</source>
<target state="translated">การส่งใบเสร็จถูกปิดใช้งานสำหรับผู้ติดต่อ %lld</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="These settings are for your current profile **%@**." xml:space="preserve" approved="no">
<source>These settings are for your current profile **%@**.</source>
<target state="translated">การตั้งค่าเหล่านี้ใช้สำหรับโปรไฟล์ปัจจุบันของคุณ **%@**</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="default (no)" xml:space="preserve" approved="no">
<source>default (no)</source>
<target state="translated">ค่าเริ่มต้น (ไม่)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve" approved="no">
<source>They can be overridden in contact settings</source>
<target state="translated">สามารถลบล้างได้ในการตั้งค่าผู้ติดต่อ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="encryption agreed" xml:space="preserve" approved="no">
<source>encryption agreed</source>
<target state="translated">ตกลง encryption</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="encryption ok for %@" xml:space="preserve" approved="no">
<source>encryption ok for %@</source>
<target state="translated">encryptionใช้ได้สําหรับ %@</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve" approved="no">
<source>%1$@ at %2$@:</source>
<target state="translated">%1$@ ที่ %2$@:</target>
<note>copied message info, &lt;sender&gt; at &lt;time&gt;</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve" approved="no">
<source>Delivery receipts are disabled!</source>
<target state="translated">ใบตอบรับการจัดส่งถูกปิดใช้งาน!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts!" xml:space="preserve" approved="no">
<source>Delivery receipts!</source>
<target state="translated">ใบตอบรับการจัดส่ง!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error synchronizing connection" xml:space="preserve" approved="no">
<source>Error synchronizing connection</source>
<target state="translated">เกิดข้อผิดพลาดในการซิงโครไนซ์การเชื่อมต่อ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
</body>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="th" datatype="plaintext">
@@ -26,176 +26,218 @@
<source> (</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=" (can be copied)" xml:space="preserve">
<trans-unit id=" (can be copied)" xml:space="preserve" approved="no">
<source> (can be copied)</source>
<target state="translated"> (kopyalanabilir)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="!1 colored!" xml:space="preserve">
<trans-unit id="!1 colored!" xml:space="preserve" approved="no">
<source>!1 colored!</source>
<target state="translated">!1 renkli!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<trans-unit id="#secret#" xml:space="preserve" approved="no">
<source>#secret#</source>
<target state="translated">#gizli#</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@" xml:space="preserve">
<trans-unit id="%@" xml:space="preserve" approved="no">
<source>%@</source>
<target state="translated">%@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ %@" xml:space="preserve">
<trans-unit id="%@ %@" xml:space="preserve" approved="no">
<source>%@ %@</source>
<target state="translated">%@ %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ (current)" xml:space="preserve">
<trans-unit id="%@ (current)" xml:space="preserve" approved="no">
<source>%@ (current)</source>
<target state="translated">%@ (güncel)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ (current):" xml:space="preserve">
<trans-unit id="%@ (current):" xml:space="preserve" approved="no">
<source>%@ (current):</source>
<target state="translated">%@ (güncel):</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%@ / %@" xml:space="preserve">
<trans-unit id="%@ / %@" xml:space="preserve" approved="no">
<source>%@ / %@</source>
<target state="translated">%@ / %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ at %@:" xml:space="preserve">
<source>%1$@ at %2$@:</source>
<note>copied message info, &lt;sender&gt; at &lt;time&gt;</note>
</trans-unit>
<trans-unit id="%@ is connected!" xml:space="preserve">
<trans-unit id="%@ is connected!" xml:space="preserve" approved="no">
<source>%@ is connected!</source>
<target state="translated">%@ bağlandı!</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="%@ is not verified" xml:space="preserve">
<trans-unit id="%@ is not verified" xml:space="preserve" approved="no">
<source>%@ is not verified</source>
<target state="translated">%@ onaylanmadı</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ is verified" xml:space="preserve">
<trans-unit id="%@ is verified" xml:space="preserve" approved="no">
<source>%@ is verified</source>
<target state="translated">%@ onaylandı</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ servers" xml:space="preserve">
<trans-unit id="%@ servers" xml:space="preserve" approved="no">
<source>%@ servers</source>
<target state="translated">%@ sunucuları</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%@ wants to connect!" xml:space="preserve">
<trans-unit id="%@ wants to connect!" xml:space="preserve" approved="no">
<source>%@ wants to connect!</source>
<target state="translated">%@ bağlanmak istiyor!</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="%@:" xml:space="preserve">
<trans-unit id="%@:" xml:space="preserve" approved="no">
<source>%@:</source>
<target state="translated">%@:</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="%d days" xml:space="preserve">
<trans-unit id="%d days" xml:space="preserve" approved="no">
<source>%d days</source>
<target state="translated">%d gün</target>
<note>time interval</note>
</trans-unit>
<trans-unit id="%d hours" xml:space="preserve">
<trans-unit id="%d hours" xml:space="preserve" approved="no">
<source>%d hours</source>
<target state="translated">%d saat</target>
<note>time interval</note>
</trans-unit>
<trans-unit id="%d min" xml:space="preserve">
<trans-unit id="%d min" xml:space="preserve" approved="no">
<source>%d min</source>
<target state="translated">%d dakika</target>
<note>time interval</note>
</trans-unit>
<trans-unit id="%d months" xml:space="preserve">
<trans-unit id="%d months" xml:space="preserve" approved="no">
<source>%d months</source>
<target state="translated">%d ay</target>
<note>time interval</note>
</trans-unit>
<trans-unit id="%d sec" xml:space="preserve">
<trans-unit id="%d sec" xml:space="preserve" approved="no">
<source>%d sec</source>
<target state="translated">%d saniye</target>
<note>time interval</note>
</trans-unit>
<trans-unit id="%d skipped message(s)" xml:space="preserve">
<trans-unit id="%d skipped message(s)" xml:space="preserve" approved="no">
<source>%d skipped message(s)</source>
<target state="translated">%d okunmamış mesaj(lar)</target>
<note>integrity error chat item</note>
</trans-unit>
<trans-unit id="%d weeks" xml:space="preserve">
<trans-unit id="%d weeks" xml:space="preserve" approved="no">
<source>%d weeks</source>
<target state="translated">%d hafta</target>
<note>time interval</note>
</trans-unit>
<trans-unit id="%lld" xml:space="preserve">
<trans-unit id="%lld" xml:space="preserve" approved="no">
<source>%lld</source>
<target state="translated">%lld</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld %@" xml:space="preserve">
<trans-unit id="%lld %@" xml:space="preserve" approved="no">
<source>%lld %@</source>
<target state="translated">%lld %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld contact(s) selected" xml:space="preserve">
<trans-unit id="%lld contact(s) selected" xml:space="preserve" approved="no">
<source>%lld contact(s) selected</source>
<target state="translated">%lld kişi seçildi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld file(s) with total size of %@" xml:space="preserve">
<trans-unit id="%lld file(s) with total size of %@" xml:space="preserve" approved="no">
<source>%lld file(s) with total size of %@</source>
<target state="translated">%lld dosya , toplam büyüklüğü %@</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld members" xml:space="preserve">
<trans-unit id="%lld members" xml:space="preserve" approved="no">
<source>%lld members</source>
<target state="translated">%lld üyeler</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
<trans-unit id="%lld minutes" xml:space="preserve" approved="no">
<source>%lld minutes</source>
<target state="translated">%lld dakika</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld second(s)" xml:space="preserve">
<trans-unit id="%lld second(s)" xml:space="preserve" approved="no">
<source>%lld second(s)</source>
<target state="translated">%lld saniye</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld seconds" xml:space="preserve">
<trans-unit id="%lld seconds" xml:space="preserve" approved="no">
<source>%lld seconds</source>
<target state="translated">%lld saniye</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lldd" xml:space="preserve">
<trans-unit id="%lldd" xml:space="preserve" approved="no">
<source>%lldd</source>
<target state="translated">%lldd</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lldh" xml:space="preserve">
<trans-unit id="%lldh" xml:space="preserve" approved="no">
<source>%lldh</source>
<target state="translated">%lldh</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lldk" xml:space="preserve">
<trans-unit id="%lldk" xml:space="preserve" approved="no">
<source>%lldk</source>
<target state="translated">%lldk</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lldm" xml:space="preserve">
<trans-unit id="%lldm" xml:space="preserve" approved="no">
<source>%lldm</source>
<target state="translated">%lldm</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lldmth" xml:space="preserve">
<trans-unit id="%lldmth" xml:space="preserve" approved="no">
<source>%lldmth</source>
<target state="translated">%lldmth</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%llds" xml:space="preserve">
<trans-unit id="%llds" xml:space="preserve" approved="no">
<source>%llds</source>
<target state="translated">%llds</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lldw" xml:space="preserve">
<trans-unit id="%lldw" xml:space="preserve" approved="no">
<source>%lldw</source>
<target state="translated">%lldw</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%u messages failed to decrypt." xml:space="preserve">
<trans-unit id="%u messages failed to decrypt." xml:space="preserve" approved="no">
<source>%u messages failed to decrypt.</source>
<target state="translated">%u mesaj deşifrelenememektedir.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%u messages skipped." xml:space="preserve">
<trans-unit id="%u messages skipped." xml:space="preserve" approved="no">
<source>%u messages skipped.</source>
<target state="translated">%u mesaj atlandı</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="(" xml:space="preserve">
<trans-unit id="(" xml:space="preserve" approved="no">
<source>(</source>
<target state="translated">(</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id=")" xml:space="preserve">
<trans-unit id=")" xml:space="preserve" approved="no">
<source>)</source>
<target state="translated">)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve">
<trans-unit id="**Add new contact**: to create your one-time QR Code for your contact." xml:space="preserve" approved="no">
<source>**Add new contact**: to create your one-time QR Code or link for your contact.</source>
<target state="translated">**Yeni kişi ekleyin**: tek seferlik QR Kodunuzu oluşturmak veya kişisel ulaşım bilgileri bağlantısı için.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve">
<trans-unit id="**Create link / QR code** for your contact to use." xml:space="preserve" approved="no">
<source>**Create link / QR code** for your contact to use.</source>
<target state="translated">Kişisel kullanım için **Bağlantı / QR Kodu**.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="**More private**: check new messages every 20 minutes. Device token is shared with SimpleX Chat server, but not how many contacts or messages you have." xml:space="preserve">
@@ -437,8 +479,9 @@
<source>All data is erased when it is entered.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All group members will remain connected." xml:space="preserve">
<trans-unit id="All group members will remain connected." xml:space="preserve" approved="no">
<source>All group members will remain connected.</source>
<target state="translated">Tüm grup üyeleri bağlı kalacaktır.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All messages will be deleted - this cannot be undone! The messages will be deleted ONLY for you." xml:space="preserve">
@@ -477,8 +520,9 @@
<source>Allow message reactions.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow sending direct messages to members." xml:space="preserve">
<trans-unit id="Allow sending direct messages to members." xml:space="preserve" approved="no">
<source>Allow sending direct messages to members.</source>
<target state="translated">Üyelere direkt mesaj göndermeye izin ver.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow sending disappearing messages." xml:space="preserve">
@@ -1286,8 +1330,9 @@
<source>Direct messages</source>
<note>chat feature</note>
</trans-unit>
<trans-unit id="Direct messages between members are prohibited in this group." xml:space="preserve">
<trans-unit id="Direct messages between members are prohibited in this group." xml:space="preserve" approved="no">
<source>Direct messages between members are prohibited in this group.</source>
<target state="translated">Bu grupta üyeler arasında direkt mesajlaşma yasaktır.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Disable SimpleX Lock" xml:space="preserve">
@@ -2174,12 +2219,14 @@
<source>Learn more</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave" xml:space="preserve">
<trans-unit id="Leave" xml:space="preserve" approved="no">
<source>Leave</source>
<target state="translated">Ayrıl</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave group" xml:space="preserve">
<trans-unit id="Leave group" xml:space="preserve" approved="no">
<source>Leave group</source>
<target state="translated">Gruptan ayrıl</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Leave group?" xml:space="preserve">
@@ -4582,28 +4629,34 @@ SimpleX servers cannot see your profile.</source>
<source>connected</source>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="message received" xml:space="preserve">
<trans-unit id="message received" xml:space="preserve" approved="no">
<source>message received</source>
<target state="translated">mesaj alındı</target>
<note>notification</note>
</trans-unit>
<trans-unit id="minutes" xml:space="preserve">
<trans-unit id="minutes" xml:space="preserve" approved="no">
<source>minutes</source>
<target state="translated">dakikalar</target>
<note>time unit</note>
</trans-unit>
<trans-unit id="missed call" xml:space="preserve">
<trans-unit id="missed call" xml:space="preserve" approved="no">
<source>missed call</source>
<target state="translated">cevapsız arama</target>
<note>call status</note>
</trans-unit>
<trans-unit id="moderated" xml:space="preserve">
<trans-unit id="moderated" xml:space="preserve" approved="no">
<source>moderated</source>
<target state="needs-translation">moderated</target>
<note>moderated chat item</note>
</trans-unit>
<trans-unit id="moderated by %@" xml:space="preserve">
<trans-unit id="moderated by %@" xml:space="preserve" approved="no">
<source>moderated by %@</source>
<target state="translated">%@ tarafından yönetilmekte</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="months" xml:space="preserve">
<trans-unit id="months" xml:space="preserve" approved="no">
<source>months</source>
<target state="translated">aylar</target>
<note>time unit</note>
</trans-unit>
<trans-unit id="never" xml:space="preserve">
@@ -4695,120 +4748,149 @@ SimpleX servers cannot see your profile.</source>
<source>secret</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="security code changed" xml:space="preserve">
<trans-unit id="security code changed" xml:space="preserve" approved="no">
<source>security code changed</source>
<target state="translated">güvenlik kodu değiştirildi</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="starting…" xml:space="preserve">
<trans-unit id="starting…" xml:space="preserve" approved="no">
<source>starting…</source>
<target state="translated">başlıyor…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="strike" xml:space="preserve">
<trans-unit id="strike" xml:space="preserve" approved="no">
<source>strike</source>
<target state="needs-translation">strike</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="this contact" xml:space="preserve">
<trans-unit id="this contact" xml:space="preserve" approved="no">
<source>this contact</source>
<target state="translated">Bu kişi</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
<trans-unit id="unknown" xml:space="preserve" approved="no">
<source>unknown</source>
<target state="translated">bilinmeyen</target>
<note>connection info</note>
</trans-unit>
<trans-unit id="updated group profile" xml:space="preserve">
<trans-unit id="updated group profile" xml:space="preserve" approved="no">
<source>updated group profile</source>
<target state="translated">grup profili güncellendi</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="v%@ (%@)" xml:space="preserve">
<trans-unit id="v%@ (%@)" xml:space="preserve" approved="no">
<source>v%@ (%@)</source>
<target state="translated">v%@ (%@)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="via contact address link" xml:space="preserve">
<trans-unit id="via contact address link" xml:space="preserve" approved="no">
<source>via contact address link</source>
<target state="translated">bağlantı adres uzantısı ile</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via group link" xml:space="preserve">
<trans-unit id="via group link" xml:space="preserve" approved="no">
<source>via group link</source>
<target state="translated">grup bağlantısı ile</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via one-time link" xml:space="preserve">
<trans-unit id="via one-time link" xml:space="preserve" approved="no">
<source>via one-time link</source>
<target state="translated">tek kullanımlık bağlantısı ile</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="via relay" xml:space="preserve">
<trans-unit id="via relay" xml:space="preserve" approved="no">
<source>via relay</source>
<target state="needs-translation">via relay</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="video call (not e2e encrypted)" xml:space="preserve">
<trans-unit id="video call (not e2e encrypted)" xml:space="preserve" approved="no">
<source>video call (not e2e encrypted)</source>
<target state="translated">Görüntülü arama (şifrelenmiş değil)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="waiting for answer…" xml:space="preserve">
<trans-unit id="waiting for answer…" xml:space="preserve" approved="no">
<source>waiting for answer…</source>
<target state="translated">cevap bekleniyor…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="waiting for confirmation…" xml:space="preserve">
<trans-unit id="waiting for confirmation…" xml:space="preserve" approved="no">
<source>waiting for confirmation…</source>
<target state="translated">onay bekleniyor…</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="wants to connect to you!" xml:space="preserve">
<trans-unit id="wants to connect to you!" xml:space="preserve" approved="no">
<source>wants to connect to you!</source>
<target state="translated">bağlanmak istiyor!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="weeks" xml:space="preserve">
<trans-unit id="weeks" xml:space="preserve" approved="no">
<source>weeks</source>
<target state="translated">haftalar</target>
<note>time unit</note>
</trans-unit>
<trans-unit id="yes" xml:space="preserve">
<trans-unit id="yes" xml:space="preserve" approved="no">
<source>yes</source>
<target state="translated">evet</target>
<note>pref value</note>
</trans-unit>
<trans-unit id="you are invited to group" xml:space="preserve">
<trans-unit id="you are invited to group" xml:space="preserve" approved="no">
<source>you are invited to group</source>
<target state="translated">gruba davet edildiniz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="you are observer" xml:space="preserve">
<trans-unit id="you are observer" xml:space="preserve" approved="no">
<source>you are observer</source>
<target state="translated">gözlemcisiniz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
<trans-unit id="you changed address" xml:space="preserve" approved="no">
<source>you changed address</source>
<target state="translated">adresinizi değiştirdiniz</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="you changed address for %@" xml:space="preserve">
<trans-unit id="you changed address for %@" xml:space="preserve" approved="no">
<source>you changed address for %@</source>
<target state="translated">adresinizi %@ ile değiştirdiniz</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="you changed role for yourself to %@" xml:space="preserve">
<trans-unit id="you changed role for yourself to %@" xml:space="preserve" approved="no">
<source>you changed role for yourself to %@</source>
<target state="translated">kişisel yetkinizi %@ olarak değiştirdiniz</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed role of %@ to %@" xml:space="preserve">
<trans-unit id="you changed role of %@ to %@" xml:space="preserve" approved="no">
<source>you changed role of %1$@ to %2$@</source>
<target state="translated">%1$@'in yetkisini %2$@ olarak değiştirdiniz</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you left" xml:space="preserve">
<trans-unit id="you left" xml:space="preserve" approved="no">
<source>you left</source>
<target state="translated">terk ettiniz</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you removed %@" xml:space="preserve">
<trans-unit id="you removed %@" xml:space="preserve" approved="no">
<source>you removed %@</source>
<target state="translated">%@'yi çıkarttınız</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you shared one-time link" xml:space="preserve">
<trans-unit id="you shared one-time link" xml:space="preserve" approved="no">
<source>you shared one-time link</source>
<target state="translated">tek kullanımlık bağlantınızı paylaştınız</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="you shared one-time link incognito" xml:space="preserve">
<trans-unit id="you shared one-time link incognito" xml:space="preserve" approved="no">
<source>you shared one-time link incognito</source>
<target state="translated">tek kullanımlık link paylaştınız gizli</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">
<trans-unit id="you: " xml:space="preserve" approved="no">
<source>you: </source>
<target state="translated">sen: </target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="~strike~" xml:space="preserve">
<trans-unit id="~strike~" xml:space="preserve" approved="no">
<source>\~strike~</source>
<target state="needs-translation">\~strike~</target>
<note>No comment provided by engineer.</note>
</trans-unit>
</body>
@@ -4818,8 +4900,9 @@ SimpleX servers cannot see your profile.</source>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
<trans-unit id="CFBundleName" xml:space="preserve" approved="no">
<source>SimpleX</source>
<target state="translated">SimpleX</target>
<note>Bundle name</note>
</trans-unit>
<trans-unit id="NSCameraUsageDescription" xml:space="preserve">
@@ -2,7 +2,7 @@
<xliff xmlns="urn:oasis:names:tc:xliff:document:1.2" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" version="1.2" xsi:schemaLocation="urn:oasis:names:tc:xliff:document:1.2 http://docs.oasis-open.org/xliff/v1.2/os/xliff-core-1.2-strict.xsd">
<file original="en.lproj/Localizable.strings" source-language="en" target-language="zh-Hans" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="&#10;" xml:space="preserve">
@@ -42,6 +42,18 @@
<target>!1 种彩色!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="# %@" xml:space="preserve">
<source># %@</source>
<note>copied message info title, # &lt;title&gt;</note>
</trans-unit>
<trans-unit id="## History" xml:space="preserve">
<source>## History</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="## In reply to" xml:space="preserve">
<source>## In reply to</source>
<note>copied message info</note>
</trans-unit>
<trans-unit id="#secret#" xml:space="preserve">
<source>#secret#</source>
<target>#秘密#</target>
@@ -392,14 +404,8 @@
<target>新联系人</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="A random profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>A random profile will be sent to the contact that you received this link from</source>
<target>一个随机个人资料将被发送至给予您链接的联系人那里</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A random profile will be sent to your contact" xml:space="preserve">
<source>A random profile will be sent to your contact</source>
<target>一个随机资料将发送给您的联系人</target>
<trans-unit id="A new random profile will be shared." xml:space="preserve">
<source>A new random profile will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="A separate TCP connection will be used **for each chat profile you have in the app**." xml:space="preserve">
@@ -455,8 +461,8 @@
<note>accept contact request via notification
accept incoming call via notification</note>
</trans-unit>
<trans-unit id="Accept contact" xml:space="preserve">
<source>Accept contact</source>
<trans-unit id="Accept connection request?" xml:space="preserve">
<source>Accept connection request?</source>
<target>接受联系人</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -468,7 +474,7 @@
<trans-unit id="Accept incognito" xml:space="preserve">
<source>Accept incognito</source>
<target>接受隐身聊天</target>
<note>No comment provided by engineer.</note>
<note>accept contact request via notification</note>
</trans-unit>
<trans-unit id="Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts." xml:space="preserve">
<source>Add address to your profile, so that your contacts can share it with other people. Profile update will be sent to your contacts.</source>
@@ -1041,8 +1047,16 @@
<target>连接</target>
<note>server test step</note>
</trans-unit>
<trans-unit id="Connect via contact link?" xml:space="preserve">
<source>Connect via contact link?</source>
<trans-unit id="Connect directly" xml:space="preserve">
<source>Connect directly</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect incognito" xml:space="preserve">
<source>Connect incognito</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via contact link" xml:space="preserve">
<source>Connect via contact link</source>
<target>通过联系人链接进行连接?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1061,8 +1075,8 @@
<target>通过群组链接/二维码连接</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connect via one-time link?" xml:space="preserve">
<source>Connect via one-time link?</source>
<trans-unit id="Connect via one-time link" xml:space="preserve">
<source>Connect via one-time link</source>
<target>通过一次性链接连接?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -1091,11 +1105,6 @@
<target>连接错误(AUTH</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request" xml:space="preserve">
<source>Connection request</source>
<target>连接请求</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Connection request sent!" xml:space="preserve">
<source>Connection request sent!</source>
<target>已发送连接请求!</target>
@@ -1543,6 +1552,10 @@
<target>已删除于:%@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Delivery" xml:space="preserve">
<source>Delivery</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delivery receipts are disabled!" xml:space="preserve">
<source>Delivery receipts are disabled!</source>
<note>No comment provided by engineer.</note>
@@ -2412,7 +2425,7 @@
<trans-unit id="History" xml:space="preserve">
<source>History</source>
<target>历史记录</target>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
<source>How SimpleX works</source>
@@ -2521,7 +2534,7 @@
</trans-unit>
<trans-unit id="In reply to" xml:space="preserve">
<source>In reply to</source>
<note>copied message info</note>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito" xml:space="preserve">
<source>Incognito</source>
@@ -2533,14 +2546,8 @@
<target>隐身模式</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode is not supported here - your main profile will be sent to group members" xml:space="preserve">
<source>Incognito mode is not supported here - your main profile will be sent to group members</source>
<target>此处不支持隐身模式——您的主要个人资料将发送给群组成员</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." xml:space="preserve">
<source>Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created.</source>
<target>隐身模式可以保护你的主要个人资料名称和图像的隐私——对于每个新的联系人,都会创建一个新的随机个人资料。</target>
<trans-unit id="Incognito mode protects your privacy by using a new random profile for each contact." xml:space="preserve">
<source>Incognito mode protects your privacy by using a new random profile for each contact.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Incoming audio call" xml:space="preserve">
@@ -2615,6 +2622,10 @@
<target>无效的服务器地址!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid status" xml:space="preserve">
<source>Invalid status</source>
<note>item status text</note>
</trans-unit>
<trans-unit id="Invitation expired!" xml:space="preserve">
<source>Invitation expired!</source>
<target>邀请已过期!</target>
@@ -2872,7 +2883,7 @@
<trans-unit id="Message delivery error" xml:space="preserve">
<source>Message delivery error</source>
<target>消息传递错误</target>
<note>No comment provided by engineer.</note>
<note>item status text</note>
</trans-unit>
<trans-unit id="Message delivery receipts!" xml:space="preserve">
<source>Message delivery receipts!</source>
@@ -2958,6 +2969,10 @@
<target>更多改进即将推出!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Most likely this connection is deleted." xml:space="preserve">
<source>Most likely this connection is deleted.</source>
<note>item status description</note>
</trans-unit>
<trans-unit id="Most likely this contact has deleted the connection with you." xml:space="preserve">
<source>Most likely this contact has deleted the connection with you.</source>
<target>很可能此联系人已经删除了与您的联系。</target>
@@ -3063,6 +3078,10 @@
<target>没有联系人可添加</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No delivery information" xml:space="preserve">
<source>No delivery information</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="No device token!" xml:space="preserve">
<source>No device token!</source>
<target>无设备令牌!</target>
@@ -3316,10 +3335,10 @@
<target>粘贴收到的链接</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received into the box below to connect with your contact." xml:space="preserve">
<source>Paste the link you received into the box below to connect with your contact.</source>
<trans-unit id="Paste the link you received to connect with your contact." xml:space="preserve">
<source>Paste the link you received to connect with your contact.</source>
<target>将您收到的链接粘贴到下面的框中以与您的联系人联系。</target>
<note>No comment provided by engineer.</note>
<note>placeholder</note>
</trans-unit>
<trans-unit id="People can connect to you only via the links you share." xml:space="preserve">
<source>People can connect to you only via the links you share.</source>
@@ -3564,6 +3583,10 @@
<target>在我们的 [GitHub 仓库](https://github.com/simplex-chat/simplex-chat#readme) 中阅读更多信息。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Receipts are disabled" xml:space="preserve">
<source>Receipts are disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Received at" xml:space="preserve">
<source>Received at</source>
<target>已收到于</target>
@@ -3632,8 +3655,8 @@
<target>拒绝</target>
<note>reject incoming call via notification</note>
</trans-unit>
<trans-unit id="Reject contact (sender NOT notified)" xml:space="preserve">
<source>Reject contact (sender NOT notified)</source>
<trans-unit id="Reject (sender NOT notified)" xml:space="preserve">
<source>Reject (sender NOT notified)</source>
<target>拒绝联系人(发送者不会被通知)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -4014,10 +4037,18 @@
<source>Sending receipts is disabled for %lld contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is disabled for %lld groups" xml:space="preserve">
<source>Sending receipts is disabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld contacts" xml:space="preserve">
<source>Sending receipts is enabled for %lld contacts</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending receipts is enabled for %lld groups" xml:space="preserve">
<source>Sending receipts is enabled for %lld groups</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sending via" xml:space="preserve">
<source>Sending via</source>
<target>发送通过</target>
@@ -4238,6 +4269,10 @@
<target>已跳过消息</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Small groups (max 20)" xml:space="preserve">
<source>Small groups (max 20)</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Some non-fatal errors occurred during import - you may see Chat console for more details." xml:space="preserve">
<source>Some non-fatal errors occurred during import - you may see Chat console for more details.</source>
<target>导入过程中发生了一些非致命错误——您可以查看聊天控制台了解更多详细信息。</target>
@@ -4527,8 +4562,8 @@ It can happen because of some bug or when the connection is compromised.</source
<source>These settings are for your current profile **%@**.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="They can be overridden in contact settings" xml:space="preserve">
<source>They can be overridden in contact settings</source>
<trans-unit id="They can be overridden in contact and group settings." xml:space="preserve">
<source>They can be overridden in contact and group settings.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." xml:space="preserve">
@@ -4546,6 +4581,10 @@ It can happen because of some bug or when the connection is compromised.</source
<target>此操作无法撤消——您的个人资料、联系人、消息和文件将不可撤回地丢失。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group has over %lld members, delivery receipts are not sent." xml:space="preserve">
<source>This group has over %lld members, delivery receipts are not sent.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This group no longer exists." xml:space="preserve">
<source>This group no longer exists.</source>
<target>该群组已不存在。</target>
@@ -4566,11 +4605,6 @@ It can happen because of some bug or when the connection is compromised.</source
<target>您的联系人可以扫描二维码或使用应用程序中的链接来建立连接。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To find the profile used for an incognito connection, tap the contact or group name on top of the chat." xml:space="preserve">
<source>To find the profile used for an incognito connection, tap the contact or group name on top of the chat.</source>
<target>要查找用于隐身聊天连接的资料,点击聊天顶部的联系人或群组名。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="To make a new connection" xml:space="preserve">
<source>To make a new connection</source>
<target>建立新连接</target>
@@ -4651,7 +4685,7 @@ You will be prompted to complete authentication before this feature is enabled.<
<trans-unit id="Unexpected error: %@" xml:space="preserve">
<source>Unexpected error: %@</source>
<target>意外错误: @</target>
<note>No comment provided by engineer.</note>
<note>item status description</note>
</trans-unit>
<trans-unit id="Unexpected migration state" xml:space="preserve">
<source>Unexpected migration state</source>
@@ -4790,6 +4824,10 @@ To connect, please ask your contact to create another connection link and check
<target>使用聊天</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use current profile" xml:space="preserve">
<source>Use current profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use for new connections" xml:space="preserve">
<source>Use for new connections</source>
<target>用于新连接</target>
@@ -4800,6 +4838,10 @@ To connect, please ask your contact to create another connection link and check
<target>使用 iOS 通话界面</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use new incognito profile" xml:space="preserve">
<source>Use new incognito profile</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Use server" xml:space="preserve">
<source>Use server</source>
<target>使用服务器</target>
@@ -5088,8 +5130,8 @@ To connect, please ask your contact to create another connection link and check
<target>您必须在每次应用程序启动时输入密码——它不存储在设备上。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="You invited your contact" xml:space="preserve">
<source>You invited your contact</source>
<trans-unit id="You invited a contact" xml:space="preserve">
<source>You invited a contact</source>
<target>您邀请了您的联系人</target>
<note>No comment provided by engineer.</note>
</trans-unit>
@@ -5218,11 +5260,6 @@ To connect, please ask your contact to create another connection link and check
<target>您的聊天资料将被发送给群组成员</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profile will be sent to your contact" xml:space="preserve">
<source>Your chat profile will be sent to your contact</source>
<target>您的聊天资料将被发送给您的联系人</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your chat profiles" xml:space="preserve">
<source>Your chat profiles</source>
<target>您的聊天资料</target>
@@ -5277,6 +5314,10 @@ You can change it in Settings.</source>
<target>您的隐私设置</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<source>Your profile **%@** will be shared.</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile is stored on your device and shared only with your contacts.&#10;SimpleX servers cannot see your profile." xml:space="preserve">
<source>Your profile is stored on your device and shared only with your contacts.
SimpleX servers cannot see your profile.</source>
@@ -5284,11 +5325,6 @@ SimpleX servers cannot see your profile.</source>
SimpleX 服务器无法看到您的资料。</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile will be sent to the contact that you received this link from" xml:space="preserve">
<source>Your profile will be sent to the contact that you received this link from</source>
<target>您的个人资料将发送给您收到此链接的联系人</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile, contacts and delivered messages are stored on your device." xml:space="preserve">
<source>Your profile, contacts and delivered messages are stored on your device.</source>
<target>您的资料、联系人和发送的消息存储在您的设备上。</target>
@@ -5558,6 +5594,10 @@ SimpleX 服务器无法看到您的资料。</target>
<target>直接</target>
<note>connection level description</note>
</trans-unit>
<trans-unit id="disabled" xml:space="preserve">
<source>disabled</source>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="duplicate message" xml:space="preserve">
<source>duplicate message</source>
<target>重复的消息</target>
@@ -6034,7 +6074,7 @@ SimpleX 服务器无法看到您的资料。</target>
</file>
<file original="en.lproj/SimpleX--iOS--InfoPlist.strings" source-language="en" target-language="zh-Hans" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleName" xml:space="preserve">
@@ -6066,7 +6106,7 @@ SimpleX 服务器无法看到您的资料。</target>
</file>
<file original="SimpleX NSE/en.lproj/InfoPlist.strings" source-language="en" target-language="zh-Hans" datatype="plaintext">
<header>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="14.3.1" build-num="14E300c"/>
<tool tool-id="com.apple.dt.xcode" tool-name="Xcode" tool-version="15.0" build-num="15A5219j"/>
</header>
<body>
<trans-unit id="CFBundleDisplayName" xml:space="preserve">
@@ -3,10 +3,10 @@
"project" : "SimpleX.xcodeproj",
"targetLocale" : "zh-Hans",
"toolInfo" : {
"toolBuildNumber" : "14E300c",
"toolBuildNumber" : "15A5219j",
"toolID" : "com.apple.dt.xcode",
"toolName" : "Xcode",
"toolVersion" : "14.3.1"
"toolVersion" : "15.0"
},
"version" : "1.0"
}
@@ -219,7 +219,6 @@ func startChat() -> DBMigrationResult? {
let justStarted = try apiStartChat()
chatStarted = true
if justStarted {
try apiSetIncognito(incognito: incognitoGroupDefault.get())
chatLastStartGroupDefault.set(Date.now)
Task { await receiveMessages() }
}
@@ -352,12 +351,6 @@ func setXFTPConfig(_ cfg: XFTPFileConfig?) throws {
throw r
}
func apiSetIncognito(incognito: Bool) throws {
let r = sendSimpleXCmd(.setIncognito(incognito: incognito))
if case .cmdOk = r { return }
throw r
}
func apiGetNtfMessage(nonce: String, encNtfInfo: String) -> NtfMessages? {
guard apiGetActiveUser() != nil else {
logger.debug("no active user")
+30 -30
View File
@@ -24,6 +24,11 @@
5C00168128C4FE760094D739 /* KeyChain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C00168028C4FE760094D739 /* KeyChain.swift */; };
5C029EA82837DBB3004A9677 /* CICallItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C029EA72837DBB3004A9677 /* CICallItemView.swift */; };
5C029EAA283942EA004A9677 /* CallController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C029EA9283942EA004A9677 /* CallController.swift */; };
5C0403922A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C04038D2A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5-ghc8.10.7.a */; };
5C0403932A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C04038E2A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5.a */; };
5C0403942A7EAA41006ACFE8 /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C04038F2A7EAA41006ACFE8 /* libffi.a */; };
5C0403952A7EAA41006ACFE8 /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C0403902A7EAA41006ACFE8 /* libgmp.a */; };
5C0403962A7EAA41006ACFE8 /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C0403912A7EAA41006ACFE8 /* libgmpxx.a */; };
5C05DF532840AA1D00C683F9 /* CallSettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C05DF522840AA1D00C683F9 /* CallSettings.swift */; };
5C063D2727A4564100AEC577 /* ChatPreviewView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C063D2627A4564100AEC577 /* ChatPreviewView.swift */; };
5C10D88828EED12E00E58BF0 /* ContactConnectionInfo.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */; };
@@ -43,11 +48,6 @@
5C3F1D562842B68D00EC8A82 /* IntegrityErrorItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C3F1D552842B68D00EC8A82 /* IntegrityErrorItemView.swift */; };
5C3F1D58284363C400EC8A82 /* PrivacySettings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */; };
5C4B3B0A285FB130003915F2 /* DatabaseView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C4B3B09285FB130003915F2 /* DatabaseView.swift */; };
5C4E794D2A8175E0006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU-ghc8.10.7.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E79482A8175DF006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU-ghc8.10.7.a */; };
5C4E794E2A8175E0006253CA /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E79492A8175E0006253CA /* libgmp.a */; };
5C4E794F2A8175E0006253CA /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E794A2A8175E0006253CA /* libgmpxx.a */; };
5C4E79502A8175E0006253CA /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E794B2A8175E0006253CA /* libffi.a */; };
5C4E79512A8175E0006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C4E794C2A8175E0006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU.a */; };
5C5346A827B59A6A004DF848 /* ChatHelp.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C5346A727B59A6A004DF848 /* ChatHelp.swift */; };
5C55A91F283AD0E400C4E99E /* CallManager.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C55A91E283AD0E400C4E99E /* CallManager.swift */; };
5C55A921283CCCB700C4E99E /* IncomingCallView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C55A920283CCCB700C4E99E /* IncomingCallView.swift */; };
@@ -263,6 +263,11 @@
5C00168028C4FE760094D739 /* KeyChain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = KeyChain.swift; sourceTree = "<group>"; };
5C029EA72837DBB3004A9677 /* CICallItemView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CICallItemView.swift; sourceTree = "<group>"; };
5C029EA9283942EA004A9677 /* CallController.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallController.swift; sourceTree = "<group>"; };
5C04038D2A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5-ghc8.10.7.a"; sourceTree = "<group>"; };
5C04038E2A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5.a"; sourceTree = "<group>"; };
5C04038F2A7EAA41006ACFE8 /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5C0403902A7EAA41006ACFE8 /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5C0403912A7EAA41006ACFE8 /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5C05DF522840AA1D00C683F9 /* CallSettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallSettings.swift; sourceTree = "<group>"; };
5C063D2627A4564100AEC577 /* ChatPreviewView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatPreviewView.swift; sourceTree = "<group>"; };
5C10D88728EED12E00E58BF0 /* ContactConnectionInfo.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ContactConnectionInfo.swift; sourceTree = "<group>"; };
@@ -284,11 +289,6 @@
5C3F1D57284363C400EC8A82 /* PrivacySettings.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = PrivacySettings.swift; sourceTree = "<group>"; };
5C422A7C27A9A6FA0097A1E1 /* SimpleX (iOS).entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = "SimpleX (iOS).entitlements"; sourceTree = "<group>"; };
5C4B3B09285FB130003915F2 /* DatabaseView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DatabaseView.swift; sourceTree = "<group>"; };
5C4E79482A8175DF006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU-ghc8.10.7.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU-ghc8.10.7.a"; sourceTree = "<group>"; };
5C4E79492A8175E0006253CA /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5C4E794A2A8175E0006253CA /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5C4E794B2A8175E0006253CA /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5C4E794C2A8175E0006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU.a"; sourceTree = "<group>"; };
5C5346A727B59A6A004DF848 /* ChatHelp.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatHelp.swift; sourceTree = "<group>"; };
5C55A91E283AD0E400C4E99E /* CallManager.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CallManager.swift; sourceTree = "<group>"; };
5C55A920283CCCB700C4E99E /* IncomingCallView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IncomingCallView.swift; sourceTree = "<group>"; };
@@ -501,13 +501,13 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5C0403932A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5.a in Frameworks */,
5C0403922A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5-ghc8.10.7.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
5C4E79502A8175E0006253CA /* libffi.a in Frameworks */,
5C4E794F2A8175E0006253CA /* libgmpxx.a in Frameworks */,
5C4E79512A8175E0006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU.a in Frameworks */,
5C0403942A7EAA41006ACFE8 /* libffi.a in Frameworks */,
5C0403952A7EAA41006ACFE8 /* libgmp.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
5C4E794E2A8175E0006253CA /* libgmp.a in Frameworks */,
5C4E794D2A8175E0006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU-ghc8.10.7.a in Frameworks */,
5C0403962A7EAA41006ACFE8 /* libgmpxx.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -568,11 +568,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
5C4E794B2A8175E0006253CA /* libffi.a */,
5C4E79492A8175E0006253CA /* libgmp.a */,
5C4E794A2A8175E0006253CA /* libgmpxx.a */,
5C4E79482A8175DF006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU-ghc8.10.7.a */,
5C4E794C2A8175E0006253CA /* libHSsimplex-chat-5.2.2.0-JPeoRyrCW7JAvXL7HFn3iU.a */,
5C04038F2A7EAA41006ACFE8 /* libffi.a */,
5C0403902A7EAA41006ACFE8 /* libgmp.a */,
5C0403912A7EAA41006ACFE8 /* libgmpxx.a */,
5C04038D2A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5-ghc8.10.7.a */,
5C04038E2A7EAA41006ACFE8 /* libHSsimplex-chat-5.3.0.2-57EsBXX08D1H5qwhz1zMA5.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -1478,7 +1478,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 165;
CURRENT_PROJECT_VERSION = 164;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1499,7 +1499,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.2.2;
MARKETING_VERSION = 5.3;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1520,7 +1520,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 165;
CURRENT_PROJECT_VERSION = 164;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1541,7 +1541,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.2.2;
MARKETING_VERSION = 5.3;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1600,7 +1600,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 165;
CURRENT_PROJECT_VERSION = 164;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1613,7 +1613,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.2.2;
MARKETING_VERSION = 5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1632,7 +1632,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 165;
CURRENT_PROJECT_VERSION = 164;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1645,7 +1645,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.2.2;
MARKETING_VERSION = 5.3;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1664,7 +1664,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 165;
CURRENT_PROJECT_VERSION = 164;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1710,7 +1710,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 165;
CURRENT_PROJECT_VERSION = 164;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
+1 -1
View File
@@ -206,7 +206,7 @@ public func responseError(_ err: Error) -> String {
switch r {
case let .chatCmdError(_, chatError): return chatErrorString(chatError)
case let .chatError(_, chatError): return chatErrorString(chatError)
default: return String(describing: r)
default: return "\(String(describing: r.responseType)), details: \(String(describing: r.details))"
}
} else {
return String(describing: err)
+106 -19
View File
@@ -19,6 +19,7 @@ public enum ChatCommand {
case apiSetActiveUser(userId: Int64, viewPwd: String?)
case setAllContactReceipts(enable: Bool)
case apiSetUserContactReceipts(userId: Int64, userMsgReceiptSettings: UserMsgReceiptSettings)
case apiSetUserGroupReceipts(userId: Int64, userMsgReceiptSettings: UserMsgReceiptSettings)
case apiHideUser(userId: Int64, viewPwd: String)
case apiUnhideUser(userId: Int64, viewPwd: String)
case apiMuteUser(userId: Int64)
@@ -31,7 +32,6 @@ public enum ChatCommand {
case setTempFolder(tempFolder: String)
case setFilesFolder(filesFolder: String)
case apiSetXFTPConfig(config: XFTPFileConfig?)
case setIncognito(incognito: Bool)
case apiExportArchive(config: ArchiveConfig)
case apiImportArchive(config: ArchiveConfig)
case apiDeleteStorage
@@ -82,8 +82,9 @@ public enum ChatCommand {
case apiGetGroupMemberCode(groupId: Int64, groupMemberId: Int64)
case apiVerifyContact(contactId: Int64, connectionCode: String?)
case apiVerifyGroupMember(groupId: Int64, groupMemberId: Int64, connectionCode: String?)
case apiAddContact(userId: Int64)
case apiConnect(userId: Int64, connReq: String)
case apiAddContact(userId: Int64, incognito: Bool)
case apiSetConnectionIncognito(connId: Int64, incognito: Bool)
case apiConnect(userId: Int64, incognito: Bool, connReq: String)
case apiDeleteChat(type: ChatType, id: Int64)
case apiClearChat(type: ChatType, id: Int64)
case apiListContacts(userId: Int64)
@@ -96,7 +97,7 @@ public enum ChatCommand {
case apiShowMyAddress(userId: Int64)
case apiSetProfileAddress(userId: Int64, on: Bool)
case apiAddressAutoAccept(userId: Int64, autoAccept: AutoAccept?)
case apiAcceptContact(contactReqId: Int64)
case apiAcceptContact(incognito: Bool, contactReqId: Int64)
case apiRejectContact(contactReqId: Int64)
// WebRTC calls
case apiSendCallInvitation(contact: Contact, callType: CallType)
@@ -127,7 +128,10 @@ public enum ChatCommand {
case let .setAllContactReceipts(enable): return "/set receipts all \(onOff(enable))"
case let .apiSetUserContactReceipts(userId, userMsgReceiptSettings):
let umrs = userMsgReceiptSettings
return "/_set receipts \(userId) \(onOff(umrs.enable)) clear_overrides=\(onOff(umrs.clearOverrides))"
return "/_set receipts contacts \(userId) \(onOff(umrs.enable)) clear_overrides=\(onOff(umrs.clearOverrides))"
case let .apiSetUserGroupReceipts(userId, userMsgReceiptSettings):
let umrs = userMsgReceiptSettings
return "/_set receipts groups \(userId) \(onOff(umrs.enable)) clear_overrides=\(onOff(umrs.clearOverrides))"
case let .apiHideUser(userId, viewPwd): return "/_hide user \(userId) \(encodeJSON(viewPwd))"
case let .apiUnhideUser(userId, viewPwd): return "/_unhide user \(userId) \(encodeJSON(viewPwd))"
case let .apiMuteUser(userId): return "/_mute user \(userId)"
@@ -144,7 +148,6 @@ public enum ChatCommand {
} else {
return "/_xftp off"
}
case let .setIncognito(incognito): return "/incognito \(onOff(incognito))"
case let .apiExportArchive(cfg): return "/_db export \(encodeJSON(cfg))"
case let .apiImportArchive(cfg): return "/_db import \(encodeJSON(cfg))"
case .apiDeleteStorage: return "/_db delete"
@@ -209,8 +212,9 @@ public enum ChatCommand {
case let .apiVerifyContact(contactId, .none): return "/_verify code @\(contactId)"
case let .apiVerifyGroupMember(groupId, groupMemberId, .some(connectionCode)): return "/_verify code #\(groupId) \(groupMemberId) \(connectionCode)"
case let .apiVerifyGroupMember(groupId, groupMemberId, .none): return "/_verify code #\(groupId) \(groupMemberId)"
case let .apiAddContact(userId): return "/_connect \(userId)"
case let .apiConnect(userId, connReq): return "/_connect \(userId) \(connReq)"
case let .apiAddContact(userId, incognito): return "/_connect \(userId) incognito=\(onOff(incognito))"
case let .apiSetConnectionIncognito(connId, incognito): return "/_set incognito :\(connId) \(onOff(incognito))"
case let .apiConnect(userId, incognito, connReq): return "/_connect \(userId) incognito=\(onOff(incognito)) \(connReq)"
case let .apiDeleteChat(type, id): return "/_delete \(ref(type, id))"
case let .apiClearChat(type, id): return "/_clear chat \(ref(type, id))"
case let .apiListContacts(userId): return "/_contacts \(userId)"
@@ -223,7 +227,7 @@ public enum ChatCommand {
case let .apiShowMyAddress(userId): return "/_show_address \(userId)"
case let .apiSetProfileAddress(userId, on): return "/_profile_address \(userId) \(onOff(on))"
case let .apiAddressAutoAccept(userId, autoAccept): return "/_auto_accept \(userId) \(AutoAccept.cmdString(autoAccept))"
case let .apiAcceptContact(contactReqId): return "/_accept \(contactReqId)"
case let .apiAcceptContact(incognito, contactReqId): return "/_accept incognito=\(onOff(incognito)) \(contactReqId)"
case let .apiRejectContact(contactReqId): return "/_reject \(contactReqId)"
case let .apiSendCallInvitation(contact, callType): return "/_call invite @\(contact.apiId) \(encodeJSON(callType))"
case let .apiRejectCall(contact): return "/_call reject @\(contact.apiId)"
@@ -257,6 +261,7 @@ public enum ChatCommand {
case .apiSetActiveUser: return "apiSetActiveUser"
case .setAllContactReceipts: return "setAllContactReceipts"
case .apiSetUserContactReceipts: return "apiSetUserContactReceipts"
case .apiSetUserGroupReceipts: return "apiSetUserGroupReceipts"
case .apiHideUser: return "apiHideUser"
case .apiUnhideUser: return "apiUnhideUser"
case .apiMuteUser: return "apiMuteUser"
@@ -269,7 +274,6 @@ public enum ChatCommand {
case .setTempFolder: return "setTempFolder"
case .setFilesFolder: return "setFilesFolder"
case .apiSetXFTPConfig: return "apiSetXFTPConfig"
case .setIncognito: return "setIncognito"
case .apiExportArchive: return "apiExportArchive"
case .apiImportArchive: return "apiImportArchive"
case .apiDeleteStorage: return "apiDeleteStorage"
@@ -321,6 +325,7 @@ public enum ChatCommand {
case .apiVerifyContact: return "apiVerifyContact"
case .apiVerifyGroupMember: return "apiVerifyGroupMember"
case .apiAddContact: return "apiAddContact"
case .apiSetConnectionIncognito: return "apiSetConnectionIncognito"
case .apiConnect: return "apiConnect"
case .apiDeleteChat: return "apiDeleteChat"
case .apiClearChat: return "apiClearChat"
@@ -443,10 +448,12 @@ public enum ChatResponse: Decodable, Error {
case contactCode(user: User, contact: Contact, connectionCode: String)
case groupMemberCode(user: User, groupInfo: GroupInfo, member: GroupMember, connectionCode: String)
case connectionVerified(user: User, verified: Bool, expectedCode: String)
case invitation(user: User, connReqInvitation: String)
case invitation(user: User, connReqInvitation: String, connection: PendingContactConnection)
case connectionIncognitoUpdated(user: User, toConnection: PendingContactConnection)
case sentConfirmation(user: User)
case sentInvitation(user: User)
case contactAlreadyExists(user: User, contact: Contact)
case contactRequestAlreadyAccepted(user: User, contact: Contact)
case contactDeleted(user: User, contact: Contact)
case chatCleared(user: User, chatInfo: ChatInfo)
case userProfileNoChange(user: User)
@@ -476,6 +483,7 @@ public enum ChatResponse: Decodable, Error {
case newChatItem(user: User, chatItem: AChatItem)
case chatItemStatusUpdated(user: User, chatItem: AChatItem)
case chatItemUpdated(user: User, chatItem: AChatItem)
case chatItemNotChanged(user: User, chatItem: AChatItem)
case chatItemReaction(user: User, added: Bool, reaction: ACIReaction)
case chatItemDeleted(user: User, deletedChatItem: AChatItem, toChatItem: AChatItem?, byUser: Bool)
case contactsList(user: User, contacts: [Contact])
@@ -575,9 +583,11 @@ public enum ChatResponse: Decodable, Error {
case .groupMemberCode: return "groupMemberCode"
case .connectionVerified: return "connectionVerified"
case .invitation: return "invitation"
case .connectionIncognitoUpdated: return "connectionIncognitoUpdated"
case .sentConfirmation: return "sentConfirmation"
case .sentInvitation: return "sentInvitation"
case .contactAlreadyExists: return "contactAlreadyExists"
case .contactRequestAlreadyAccepted: return "contactRequestAlreadyAccepted"
case .contactDeleted: return "contactDeleted"
case .chatCleared: return "chatCleared"
case .userProfileNoChange: return "userProfileNoChange"
@@ -607,6 +617,7 @@ public enum ChatResponse: Decodable, Error {
case .newChatItem: return "newChatItem"
case .chatItemStatusUpdated: return "chatItemStatusUpdated"
case .chatItemUpdated: return "chatItemUpdated"
case .chatItemNotChanged: return "chatItemNotChanged"
case .chatItemReaction: return "chatItemReaction"
case .chatItemDeleted: return "chatItemDeleted"
case .contactsList: return "contactsList"
@@ -704,10 +715,12 @@ public enum ChatResponse: Decodable, Error {
case let .contactCode(u, contact, connectionCode): return withUser(u, "contact: \(String(describing: contact))\nconnectionCode: \(connectionCode)")
case let .groupMemberCode(u, groupInfo, member, connectionCode): return withUser(u, "groupInfo: \(String(describing: groupInfo))\nmember: \(String(describing: member))\nconnectionCode: \(connectionCode)")
case let .connectionVerified(u, verified, expectedCode): return withUser(u, "verified: \(verified)\nconnectionCode: \(expectedCode)")
case let .invitation(u, connReqInvitation): return withUser(u, connReqInvitation)
case let .invitation(u, connReqInvitation, _): return withUser(u, connReqInvitation)
case let .connectionIncognitoUpdated(u, toConnection): return withUser(u, String(describing: toConnection))
case .sentConfirmation: return noDetails
case .sentInvitation: return noDetails
case let .contactAlreadyExists(u, contact): return withUser(u, String(describing: contact))
case let .contactRequestAlreadyAccepted(u, contact): return withUser(u, String(describing: contact))
case let .contactDeleted(u, contact): return withUser(u, String(describing: contact))
case let .chatCleared(u, chatInfo): return withUser(u, String(describing: chatInfo))
case .userProfileNoChange: return noDetails
@@ -737,6 +750,7 @@ public enum ChatResponse: Decodable, Error {
case let .newChatItem(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemStatusUpdated(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemUpdated(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemNotChanged(u, chatItem): return withUser(u, String(describing: chatItem))
case let .chatItemReaction(u, added, reaction): return withUser(u, "added: \(added)\n\(String(describing: reaction))")
case let .chatItemDeleted(u, deletedChatItem, toChatItem, byUser): return withUser(u, "deletedChatItem:\n\(String(describing: deletedChatItem))\ntoChatItem:\n\(String(describing: toChatItem))\nbyUser: \(byUser)")
case let .contactsList(u, contacts): return withUser(u, String(describing: contacts))
@@ -810,6 +824,14 @@ public enum ChatResponse: Decodable, Error {
}
}
public func chatError(_ chatResponse: ChatResponse) -> ChatErrorType? {
switch chatResponse {
case let .chatCmdError(_, .error(error)): return error
case let .chatError(_, .error(error)): return error
default: return nil
}
}
struct NewUser: Encodable {
var profile: Profile?
var sameServers: Bool
@@ -1362,14 +1384,32 @@ public enum ChatError: Decodable {
public enum ChatErrorType: Decodable {
case noActiveUser
case noConnectionUser(agentConnId: String)
case noSndFileUser(agentSndFileId: String)
case noRcvFileUser(agentRcvFileId: String)
case userUnknown
case activeUserExists
case userExists
case differentActiveUser
case differentActiveUser(commandUserId: Int64, activeUserId: Int64)
case cantDeleteActiveUser(userId: Int64)
case cantDeleteLastUser(userId: Int64)
case cantHideLastUser(userId: Int64)
case hiddenUserAlwaysMuted(userId: Int64)
case emptyUserPassword(userId: Int64)
case userAlreadyHidden(userId: Int64)
case userNotHidden(userId: Int64)
case chatNotStarted
case chatNotStopped
case chatStoreChanged
case invalidConnReq
case invalidChatMessage(message: String)
case invalidChatMessage(connection: Connection, message: String)
case contactNotReady(contact: Contact)
case groupUserRole
case contactDisabled(contact: Contact)
case connectionDisabled(connection: Connection)
case groupUserRole(groupInfo: GroupInfo, requiredRole: GroupMemberRole)
case groupMemberInitialRole(groupInfo: GroupInfo, initialRole: GroupMemberRole)
case contactIncognitoCantInvite
case groupIncognitoCantInvite
case groupContactRole(contactName: ContactName)
case groupDuplicateMember(contactName: ContactName)
case groupDuplicateMemberId
@@ -1381,23 +1421,50 @@ public enum ChatErrorType: Decodable {
case groupCantResendInvitation(groupInfo: GroupInfo, contactName: ContactName)
case groupInternal(message: String)
case fileNotFound(message: String)
case fileSize(filePath: String)
case fileAlreadyReceiving(message: String)
case fileCancelled(message: String)
case fileCancel(fileId: Int64, message: String)
case fileAlreadyExists(filePath: String)
case fileRead(filePath: String, message: String)
case fileWrite(filePath: String, message: String)
case fileSend(fileId: Int64, agentError: String)
case fileRcvChunk(message: String)
case fileInternal(message: String)
case fileImageType(filePath: String)
case fileImageSize(filePath: String)
case fileNotReceived(fileId: Int64)
// case xFTPRcvFile
// case xFTPSndFile
case fallbackToSMPProhibited(fileId: Int64)
case inlineFileProhibited(fileId: Int64)
case invalidQuote
case invalidChatItemUpdate
case invalidChatItemDelete
case hasCurrentCall
case noCurrentCall
case callContact(contactId: Int64)
case callState
case directMessagesProhibited(contact: Contact)
case agentVersion
case agentNoSubResult(agentConnId: String)
case commandError(message: String)
case serverProtocol
case agentCommandError(message: String)
case invalidFileDescription(message: String)
case connectionIncognitoChangeProhibited
case internalError(message: String)
case exception(message: String)
}
public enum StoreError: Decodable {
case duplicateName
case userNotFound(userId: Int64)
case userNotFoundByName(contactName: ContactName)
case userNotFoundByContactId(contactId: Int64)
case userNotFoundByGroupId(groupId: Int64)
case userNotFoundByFileId(fileId: Int64)
case userNotFoundByContactRequestId(contactRequestId: Int64)
case contactNotFound(contactId: Int64)
case contactNotFoundByName(contactName: ContactName)
case contactNotReady(contactName: ContactName)
@@ -1407,6 +1474,9 @@ public enum StoreError: Decodable {
case contactRequestNotFoundByName(contactName: ContactName)
case groupNotFound(groupId: Int64)
case groupNotFoundByName(groupName: GroupName)
case groupMemberNameNotFound(groupId: Int64, groupMemberName: ContactName)
case groupMemberNotFound(groupMemberId: Int64)
case groupMemberNotFoundByMemberId(memberId: String)
case groupWithoutUser
case duplicateGroupMember
case groupAlreadyJoined
@@ -1414,9 +1484,16 @@ public enum StoreError: Decodable {
case sndFileNotFound(fileId: Int64)
case sndFileInvalid(fileId: Int64)
case rcvFileNotFound(fileId: Int64)
case rcvFileDescrNotFound(fileId: Int64)
case fileNotFound(fileId: Int64)
case rcvFileInvalid(fileId: Int64)
case rcvFileInvalidDescrPart
case sharedMsgIdNotFoundByFileId(fileId: Int64)
case fileIdNotFoundBySharedMsgId(sharedMsgId: String)
case sndFileNotFoundXFTP(agentSndFileId: String)
case rcvFileNotFoundXFTP(agentRcvFileId: String)
case connectionNotFound(agentConnId: String)
case connectionNotFoundById(connId: Int64)
case pendingConnectionNotFound(connId: Int64)
case introNotFound
case uniqueID
@@ -1424,11 +1501,16 @@ public enum StoreError: Decodable {
case noMsgDelivery(connId: Int64, agentMsgId: String)
case badChatItem(itemId: Int64)
case chatItemNotFound(itemId: Int64)
case quotedChatItemNotFound
case chatItemNotFoundByText(text: String)
case chatItemSharedMsgIdNotFound(sharedMsgId: String)
case chatItemNotFoundByFileId(fileId: Int64)
case chatItemNotFoundByGroupId(groupId: Int64)
case profileNotFound(profileId: Int64)
case duplicateGroupLink(groupInfo: GroupInfo)
case groupLinkNotFound(groupInfo: GroupInfo)
case hostMemberIdNotFound(groupId: Int64)
case contactNotFoundByFileId(fileId: Int64)
case noGroupSndStatus(itemId: Int64, groupMemberId: Int64)
}
public enum DatabaseError: Decodable {
@@ -1448,11 +1530,12 @@ public enum AgentErrorType: Decodable {
case CMD(cmdErr: CommandErrorType)
case CONN(connErr: ConnectionErrorType)
case SMP(smpErr: ProtocolErrorType)
case XFTP(xftpErr: XFTPErrorType)
case NTF(ntfErr: ProtocolErrorType)
case XFTP(xftpErr: XFTPErrorType)
case BROKER(brokerAddress: String, brokerErr: BrokerErrorType)
case AGENT(agentErr: SMPAgentError)
case INTERNAL(internalErr: String)
case INACTIVE
}
public enum CommandErrorType: Decodable {
@@ -1472,9 +1555,10 @@ public enum ConnectionErrorType: Decodable {
}
public enum BrokerErrorType: Decodable {
case RESPONSE(smpErr: ProtocolErrorType)
case RESPONSE(smpErr: String)
case UNEXPECTED
case NETWORK
case HOST
case TRANSPORT(transportErr: ProtocolTransportError)
case TIMEOUT
}
@@ -1508,6 +1592,7 @@ public enum XFTPErrorType: Decodable {
public enum ProtocolCommandError: Decodable {
case UNKNOWN
case SYNTAX
case PROHIBITED
case NO_AUTH
case HAS_AUTH
case NO_ENTITY
@@ -1530,7 +1615,9 @@ public enum SMPAgentError: Decodable {
case A_MESSAGE
case A_PROHIBITED
case A_VERSION
case A_ENCRYPTION
case A_CRYPTO
case A_DUPLICATE
case A_QUEUE(queueErr: String)
}
public enum ArchiveError: Decodable {
+1 -1
View File
@@ -29,7 +29,7 @@ let GROUP_DEFAULT_NETWORK_ENABLE_KEEP_ALIVE = "networkEnableKeepAlive"
let GROUP_DEFAULT_NETWORK_TCP_KEEP_IDLE = "networkTCPKeepIdle"
let GROUP_DEFAULT_NETWORK_TCP_KEEP_INTVL = "networkTCPKeepIntvl"
let GROUP_DEFAULT_NETWORK_TCP_KEEP_CNT = "networkTCPKeepCnt"
let GROUP_DEFAULT_INCOGNITO = "incognito"
public let GROUP_DEFAULT_INCOGNITO = "incognito"
let GROUP_DEFAULT_STORE_DB_PASSPHRASE = "storeDBPassphrase"
let GROUP_DEFAULT_INITIAL_RANDOM_DB_PASSPHRASE = "initialRandomDBPassphrase"
public let GROUP_DEFAULT_CONFIRM_DB_UPGRADES = "confirmDBUpgrades"
+60 -15
View File
@@ -1200,6 +1200,13 @@ public enum ChatInfo: Identifiable, Decodable, NamedChat {
}
}
public var groupInfo: GroupInfo? {
switch self {
case let .group(groupInfo): return groupInfo
default: return nil
}
}
// this works for features that are common for contacts and groups
public func featureEnabled(_ feature: ChatFeature) -> Bool {
switch self {
@@ -2263,19 +2270,7 @@ public struct CIMeta: Decodable {
}
public func statusIcon(_ metaColor: Color = .secondary) -> (String, Color)? {
switch itemStatus {
case .sndSent: return ("checkmark", metaColor)
case let .sndRcvd(msgRcptStatus):
switch msgRcptStatus {
case .ok: return ("checkmark", metaColor) // ("checkmark.circle", metaColor)
case .badMsgHash: return ("checkmark", .red) // ("checkmark.circle", .red)
}
case .sndErrorAuth: return ("multiply", .red)
case .sndError: return ("exclamationmark.triangle.fill", .yellow)
case .rcvNew: return ("circlebadge.fill", Color.accentColor)
case .invalid: return ("questionmark", metaColor)
default: return nil
}
itemStatus.statusIcon(metaColor)
}
public static func getSample(_ id: Int64, _ ts: Date, _ text: String, _ status: CIStatus = .sndNew, itemDeleted: CIDeleted? = nil, itemEdited: Bool = false, itemLive: Bool = false, editable: Bool = true) -> CIMeta {
@@ -2338,8 +2333,8 @@ private func recent(_ date: Date) -> Bool {
public enum CIStatus: Decodable {
case sndNew
case sndSent
case sndRcvd(msgRcptStatus: MsgReceiptStatus)
case sndSent(sndProgress: SndCIStatusProgress)
case sndRcvd(msgRcptStatus: MsgReceiptStatus, sndProgress: SndCIStatusProgress)
case sndErrorAuth
case sndError(agentError: String)
case rcvNew
@@ -2358,6 +2353,45 @@ public enum CIStatus: Decodable {
case .invalid: return "invalid"
}
}
public func statusIcon(_ metaColor: Color = .secondary) -> (String, Color)? {
switch self {
case .sndNew: return nil
case .sndSent: return ("checkmark", metaColor)
case let .sndRcvd(msgRcptStatus, _):
switch msgRcptStatus {
case .ok: return ("checkmark", metaColor)
case .badMsgHash: return ("checkmark", .red)
}
case .sndErrorAuth: return ("multiply", .red)
case .sndError: return ("exclamationmark.triangle.fill", .yellow)
case .rcvNew: return ("circlebadge.fill", Color.accentColor)
case .rcvRead: return nil
case .invalid: return ("questionmark", metaColor)
}
}
public var statusInfo: (String, String)? {
switch self {
case .sndNew: return nil
case .sndSent: return nil
case .sndRcvd: return nil
case .sndErrorAuth: return (
NSLocalizedString("Message delivery error", comment: "item status text"),
NSLocalizedString("Most likely this connection is deleted.", comment: "item status description")
)
case let .sndError(agentError): return (
NSLocalizedString("Message delivery error", comment: "item status text"),
String.localizedStringWithFormat(NSLocalizedString("Unexpected error: %@", comment: "item status description"), agentError)
)
case .rcvNew: return nil
case .rcvRead: return nil
case let .invalid(text): return (
NSLocalizedString("Invalid status", comment: "item status text"),
text
)
}
}
}
public enum MsgReceiptStatus: String, Decodable {
@@ -2365,6 +2399,11 @@ public enum MsgReceiptStatus: String, Decodable {
case badMsgHash
}
public enum SndCIStatusProgress: String, Decodable {
case partial
case complete
}
public enum CIDeleted: Decodable {
case deleted(deletedTs: Date?)
case moderated(deletedTs: Date?, byGroupMember: GroupMember)
@@ -3212,6 +3251,7 @@ public enum ChatItemTTL: Hashable, Identifiable, Comparable {
public struct ChatItemInfo: Decodable {
public var itemVersions: [ChatItemVersion]
public var memberDeliveryStatuses: [MemberDeliveryStatus]?
}
public struct ChatItemVersion: Decodable {
@@ -3221,3 +3261,8 @@ public struct ChatItemVersion: Decodable {
public var itemVersionTs: Date
public var createdAt: Date
}
public struct MemberDeliveryStatus: Decodable {
public var groupMemberId: Int64
public var memberDeliveryStatus: CIStatus
}
+44 -38
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Nový kontakt";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Náhodný profil bude zaslán kontaktu, od kterého jste obdrželi tento odkaz";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Vašemu kontaktu bude zaslán náhodný profil";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Samostatné připojení TCP bude použito **pro každý chat profil, který máte v aplikaci**.";
@@ -285,12 +279,12 @@
"Accept" = "Přijmout";
/* No comment provided by engineer. */
"Accept contact" = "Přijmout kontakt";
"Accept connection request?" = "Přijmout kontakt";
/* notification body */
"Accept contact request from %@?" = "Přijmout žádost o kontakt od %@?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Přijmout inkognito";
/* call status */
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "připojit se k vývojářům SimpleX Chat.";
/* No comment provided by engineer. */
"Connect via contact link?" = "Připojit se přes kontaktní odkaz?";
"Connect via contact link" = "Připojit se přes kontaktní odkaz?";
/* No comment provided by engineer. */
"Connect via group link?" = "Připojit se přes odkaz skupiny?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Připojit se prostřednictvím odkazu / QR kódu";
/* No comment provided by engineer. */
"Connect via one-time link?" = "Připojit se jednorázovým odkazem?";
"Connect via one-time link" = "Připojit se jednorázovým odkazem?";
/* No comment provided by engineer. */
"connected" = "připojeno";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "spojení navázáno";
/* No comment provided by engineer. */
"Connection request" = "Žádost o připojení";
/* No comment provided by engineer. */
"Connection request sent!" = "Požadavek na připojení byl odeslán!";
@@ -936,6 +927,12 @@
/* pref value */
"default (%@)" = "výchozí (%@)";
/* No comment provided by engineer. */
"default (no)" = "výchozí (ne)";
/* No comment provided by engineer. */
"default (yes)" = "výchozí (ano)";
/* chat item action */
"Delete" = "Smazat";
@@ -1404,6 +1401,9 @@
/* No comment provided by engineer. */
"Error sending message" = "Chyba při odesílání zprávy";
/* No comment provided by engineer. */
"Error setting delivery receipts!" = "Chyba nastavování potvrzení o doručení!";
/* No comment provided by engineer. */
"Error starting chat" = "Chyba při spuštění chatu";
@@ -1528,7 +1528,7 @@
"Full link" = "Úplný odkaz";
/* No comment provided by engineer. */
"Full name (optional)" = "Celé jméno (volitelné)";
"Full name (optional)" = "Celé jméno (volitelně)";
/* No comment provided by engineer. */
"Full name:" = "Celé jméno:";
@@ -1641,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Skrýt:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "Historie";
/* time unit */
@@ -1710,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Vylepšená konfigurace serveru";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "V odpovědi na";
/* No comment provided by engineer. */
@@ -1719,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Režim inkognito";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "Zde není podporován režim inkognito - členům skupiny bude zaslán váš hlavní profil";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "Režim inkognito chrání soukromí vašeho hlavního profilového jména a obrázku - pro každý nový kontakt je vytvořen nový náhodný profil.";
/* chat list item description */
"incognito via contact address link" = "inkognito přes odkaz na kontaktní adresu";
@@ -1977,7 +1971,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Člen bude odstraněn ze skupiny - toto nelze vzít zpět!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Chyba doručení zprávy";
/* No comment provided by engineer. */
@@ -2293,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Vložení přijatého odkazu";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Vložte odkaz, který jste obdrželi, do pole níže a spojte se se svým kontaktem.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Vložte odkaz, který jste obdrželi, do pole níže a spojte se se svým kontaktem.";
/* No comment provided by engineer. */
"peer-to-peer" = "peer-to-peer";
@@ -2422,12 +2416,18 @@
/* No comment provided by engineer. */
"Protocol timeout" = "Časový limit protokolu";
/* No comment provided by engineer. */
"Protocol timeout per KB" = "Časový limit protokolu na KB";
/* No comment provided by engineer. */
"Push notifications" = "Nabízená oznámení";
/* No comment provided by engineer. */
"Rate the app" = "Ohodnoťte aplikaci";
/* chat item menu */
"React…" = "Reagovat…";
/* No comment provided by engineer. */
"Read" = "Číst";
@@ -2464,6 +2464,9 @@
/* message info title */
"Received message" = "Přijatá zpráva";
/* No comment provided by engineer. */
"Receiving address will be changed to a different server. Address change will complete after sender comes online." = "Přijímací adresa bude změněna na jiný server. Změna adresy bude dokončena po připojení odesílatele.";
/* No comment provided by engineer. */
"Receiving file will be stopped." = "Příjem souboru bude zastaven.";
@@ -2473,6 +2476,12 @@
/* No comment provided by engineer. */
"Recipients see updates as you type them." = "Příjemci uvidí aktualizace během jejich psaní.";
/* No comment provided by engineer. */
"Reconnect all connected servers to force message delivery. It uses additional traffic." = "Znovu připojte všechny připojené servery a vynuťte doručení zprávy. Využívá další provoz.";
/* No comment provided by engineer. */
"Reconnect servers?" = "Znovu připojit servery?";
/* No comment provided by engineer. */
"Record updated at" = "Záznam aktualizován v";
@@ -2486,7 +2495,7 @@
"Reject" = "Odmítnout";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Odmítnout kontakt (odesílatel NEBUDE upozorněn)";
"Reject (sender NOT notified)" = "Odmítnout kontakt (odesílatel NEBUDE upozorněn)";
/* No comment provided by engineer. */
"Reject contact request" = "Odmítnout žádost o kontakt";
@@ -2692,6 +2701,9 @@
/* No comment provided by engineer. */
"Send a live message - it will update for the recipient(s) as you type it" = "Poslat živou zprávu - zpráva se bude aktualizovat pro příjemce během psaní";
/* No comment provided by engineer. */
"Send delivery receipts to" = "Potvrzení o doručení zasílat na";
/* No comment provided by engineer. */
"Send direct message" = "Odeslat přímou zprávu";
@@ -3034,6 +3046,9 @@
/* No comment provided by engineer. */
"The profile is only shared with your contacts." = "Profil je sdílen pouze s vašimi kontakty.";
/* No comment provided by engineer. */
"The second tick we missed! ✅" = "Druhé zaškrtnutí jsme přehlédli! ✅";
/* No comment provided by engineer. */
"The sender will NOT be notified" = "Odesílatel NEBUDE informován";
@@ -3053,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Toto nastavení je pro váš aktuální profil **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Mohou být přepsány v nastavení kontaktů";
"They can be overridden in contact and group settings." = "Mohou být přepsány v nastavení kontaktů";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Tuto akci nelze vrátit zpět - všechny přijaté a odeslané soubory a média budou smazány. Obrázky s nízkým rozlišením zůstanou zachovány.";
@@ -3079,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Pro připojení může váš kontakt naskenovat QR kód, nebo použít odkaz v aplikaci.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Chcete-li najít profil použitý pro inkognito připojení, klepněte na název kontaktu nebo skupiny v horní části chatu.";
/* No comment provided by engineer. */
"To make a new connection" = "Vytvoření nového připojení";
@@ -3127,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Nelze nahrát hlasovou zprávu";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Neočekávaná chyba: %@";
/* No comment provided by engineer. */
@@ -3449,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "Musíte zadat přístupovou frázi při každém spuštění aplikace - není uložena v zařízení.";
/* No comment provided by engineer. */
"You invited your contact" = "Pozvali jste svůj kontakt";
"You invited a contact" = "Pozvali jste svůj kontakt";
/* No comment provided by engineer. */
"You joined this group" = "Připojili jste se k této skupině";
@@ -3529,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Váš chat profil bude zaslán členům skupiny";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Váš chat profil bude odeslán vašemu kontaktu";
/* No comment provided by engineer. */
"Your chat profiles" = "Vaše chat profily";
@@ -3568,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Váš profil je uložen ve vašem zařízení a sdílen pouze s vašimi kontakty.\nServery SimpleX nevidí váš profil.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Váš profil bude zaslán kontaktu, od kterého jste obdrželi tento odkaz";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Váš profil, kontakty a doručené zprávy jsou uloženy ve vašem zařízení.";
+22 -46
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Ein neuer Kontakt";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Ein zufälliges Profil wird an den Kontakt gesendet, von dem Sie diesen Link erhalten haben";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Ein zufälliges Profil wird an Ihren Kontakt gesendet";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "**Für jedes von Ihnen in der App genutzte Chat-Profil** wird eine separate TCP-Verbindung genutzt.";
@@ -285,12 +279,12 @@
"Accept" = "Annehmen";
/* No comment provided by engineer. */
"Accept contact" = "Kontakt annehmen";
"Accept connection request?" = "Kontakt annehmen";
/* notification body */
"Accept contact request from %@?" = "Die Kontaktanfrage von %@ annehmen?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Inkognito akzeptieren";
/* call status */
@@ -345,7 +339,7 @@
"All chats and messages will be deleted - this cannot be undone!" = "Alle Chats und Nachrichten werden gelöscht! Dies kann nicht rückgängig gemacht werden!";
/* No comment provided by engineer. */
"All data is erased when it is entered." = "Alle Daten werden gelöscht, sobald diese eingegeben wird.";
"All data is erased when it is entered." = "Alle Daten werden gelöscht, sobald dieser eingegeben wird.";
/* No comment provided by engineer. */
"All group members will remain connected." = "Alle Gruppenmitglieder bleiben verbunden.";
@@ -363,16 +357,16 @@
"Allow" = "Erlauben";
/* No comment provided by engineer. */
"Allow calls only if your contact allows them." = "Anrufe sind nur erlaubt, wenn Ihr Kontakt das ebenfalls erlaubt.";
"Allow calls only if your contact allows them." = "Erlauben Sie Anrufe nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.";
/* No comment provided by engineer. */
"Allow disappearing messages only if your contact allows it to you." = "Verschwindende Nachrichten nur erlauben, wenn Ihr Kontakt das ebenfalls erlaubt.";
"Allow disappearing messages only if your contact allows it to you." = "Erlauben Sie verschwindende Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt.";
/* No comment provided by engineer. */
"Allow irreversible message deletion only if your contact allows it to you." = "Erlauben Sie das unwiederbringliche Löschen von Nachrichten nur dann, wenn es Ihnen Ihr Kontakt ebenfalls erlaubt.";
/* No comment provided by engineer. */
"Allow message reactions only if your contact allows them." = "Reaktionen auf Nachrichten sind nur möglich, falls Ihr Kontakt dies erlaubt.";
"Allow message reactions only if your contact allows them." = "Erlauben Sie Reaktionen auf Nachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.";
/* No comment provided by engineer. */
"Allow message reactions." = "Reaktionen auf Nachrichten erlauben.";
@@ -393,7 +387,7 @@
"Allow to send voice messages." = "Das Senden von Sprachnachrichten erlauben.";
/* No comment provided by engineer. */
"Allow voice messages only if your contact allows them." = "Erlauben Sie Sprachnachrichten nur dann, wenn Ihr Kontakt diese ebenfalls erlaubt.";
"Allow voice messages only if your contact allows them." = "Erlauben Sie Sprachnachrichten nur dann, wenn es Ihr Kontakt ebenfalls erlaubt.";
/* No comment provided by engineer. */
"Allow voice messages?" = "Sprachnachricht erlauben?";
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "Mit den SimpleX Chat Entwicklern verbinden.";
/* No comment provided by engineer. */
"Connect via contact link?" = "Über den Kontakt-Link verbinden?";
"Connect via contact link" = "Über den Kontakt-Link verbinden?";
/* No comment provided by engineer. */
"Connect via group link?" = "Über den Gruppen-Link verbinden?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Über einen Link / QR-Code verbinden";
/* No comment provided by engineer. */
"Connect via one-time link?" = "Über einen Einmal-Link verbinden?";
"Connect via one-time link" = "Über einen Einmal-Link verbinden?";
/* No comment provided by engineer. */
"connected" = "Verbunden";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "Verbindung hergestellt";
/* No comment provided by engineer. */
"Connection request" = "Verbindungsanfrage";
/* No comment provided by engineer. */
"Connection request sent!" = "Verbindungsanfrage wurde gesendet!";
@@ -1060,10 +1051,10 @@
"deleted group" = "Gruppe gelöscht";
/* No comment provided by engineer. */
"Delivery receipts are disabled!" = "Zustellungs-Quittierungen sind deaktiviert!";
"Delivery receipts are disabled!" = "Empfangsbestätigungen sind deaktiviert!";
/* No comment provided by engineer. */
"Delivery receipts!" = "Zustellungs-Quittierungen!";
"Delivery receipts!" = "Empfangsbestätigungen!";
/* No comment provided by engineer. */
"Description" = "Beschreibung";
@@ -1650,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Verberge:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "Vergangenheit";
/* time unit */
@@ -1719,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Verbesserte Serverkonfiguration";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "Als Antwort auf";
/* No comment provided by engineer. */
@@ -1728,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Inkognito Modus";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "Der Inkognito-Modus wird hier nicht unterstützt - Ihr Hauptprofil wird an die Gruppenmitglieder gesendet";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "Der Inkognito-Modus schützt die Privatsphäre Ihres Hauptprofilnamens und -bildes für jeden neuen Kontakt wird ein neues Zufallsprofil erstellt.";
/* chat list item description */
"incognito via contact address link" = "Inkognito über einen Kontaktadressen-Link";
@@ -1986,7 +1971,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Das Mitglied wird aus der Gruppe entfernt - dies kann nicht rückgängig gemacht werden!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Fehler bei der Nachrichtenzustellung";
/* No comment provided by engineer. */
@@ -2302,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Fügen Sie den erhaltenen Link ein";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Um sich mit Ihrem Kontakt zu verbinden, fügen Sie den erhaltenen Link in das Feld unten ein.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Um sich mit Ihrem Kontakt zu verbinden, fügen Sie den erhaltenen Link in das Feld unten ein.";
/* No comment provided by engineer. */
"peer-to-peer" = "Peer-to-Peer";
@@ -2510,7 +2495,7 @@
"Reject" = "Ablehnen";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Kontakt ablehnen (der Absender wird NICHT benachrichtigt)";
"Reject (sender NOT notified)" = "Kontakt ablehnen (der Absender wird NICHT benachrichtigt)";
/* No comment provided by engineer. */
"Reject contact request" = "Kontaktanfrage ablehnen";
@@ -2717,7 +2702,7 @@
"Send a live message - it will update for the recipient(s) as you type it" = "Eine Live Nachricht senden - der/die Empfänger sieht/sehen Nachrichtenaktualisierungen, während Sie sie eingeben";
/* No comment provided by engineer. */
"Send delivery receipts to" = "Zustellungs-Quittierungen versenden an";
"Send delivery receipts to" = "Empfangsbestätigungen senden an";
/* No comment provided by engineer. */
"Send direct message" = "Direktnachricht senden";
@@ -3062,7 +3047,7 @@
"The profile is only shared with your contacts." = "Das Profil wird nur mit Ihren Kontakten geteilt.";
/* No comment provided by engineer. */
"The second tick we missed! ✅" = "Das zweite Häkchen, welches wir vermisst haben! ✅";
"The second tick we missed! ✅" = "Wir haben das zweite Häkchen vermisst! ✅";
/* No comment provided by engineer. */
"The sender will NOT be notified" = "Der Absender wird NICHT benachrichtigt";
@@ -3083,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Diese Einstellungen betreffen Ihr aktuelles Profil **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Diese können in den Kontakteinstellungen überschrieben werden";
"They can be overridden in contact and group settings." = "Sie können in den Kontakteinstellungen überschrieben werden.";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Diese Aktion kann nicht rückgängig gemacht werden! Alle empfangenen und gesendeten Dateien und Medien werden gelöscht. Bilder mit niedriger Auflösung bleiben erhalten.";
@@ -3109,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Um eine Verbindung herzustellen, kann Ihr Kontakt den QR-Code scannen oder den Link in der App verwenden.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Um das für eine Inkognito-Verbindung verwendete Profil zu finden, tippen Sie oben im Chat auf den Kontakt- oder Gruppennamen.";
/* No comment provided by engineer. */
"To make a new connection" = "Um eine Verbindung mit einem neuen Kontakt zu erstellen";
@@ -3157,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Die Aufnahme einer Sprachnachricht ist nicht möglich";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Unerwarteter Fehler: %@";
/* No comment provided by engineer. */
@@ -3479,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "Sie müssen das Passwort jedes Mal eingeben, wenn die App startet. Es wird nicht auf dem Gerät gespeichert.";
/* No comment provided by engineer. */
"You invited your contact" = "Sie haben Ihren Kontakt eingeladen";
"You invited a contact" = "Sie haben Ihren Kontakt eingeladen";
/* No comment provided by engineer. */
"You joined this group" = "Sie sind dieser Gruppe beigetreten";
@@ -3559,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Ihr Chat-Profil wird an Gruppenmitglieder gesendet";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Ihr Chat-Profil wird an Ihren Kontakt gesendet";
/* No comment provided by engineer. */
"Your chat profiles" = "Meine Chat-Profile";
@@ -3598,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Ihr Profil wird auf Ihrem Gerät gespeichert und nur mit Ihren Kontakten geteilt.\nSimpleX-Server können Ihr Profil nicht einsehen.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Ihr Profil wird an den Kontakt gesendet, von dem Sie diesen Link erhalten haben";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Ihr Profil, Ihre Kontakte und zugestellten Nachrichten werden auf Ihrem Gerät gespeichert.";
+31 -55
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Contacto nuevo";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Se enviará un perfil aleatorio al contacto del que recibió este enlace";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Se enviará un perfil aleatorio a tu contacto";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Se usará una conexión TCP independiente **por cada perfil que tengas en la aplicación**.";
@@ -285,12 +279,12 @@
"Accept" = "Aceptar";
/* No comment provided by engineer. */
"Accept contact" = "Aceptar contacto";
"Accept connection request?" = "Aceptar contacto";
/* notification body */
"Accept contact request from %@?" = "¿Aceptar solicitud de contacto de %@?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Aceptar incógnito";
/* call status */
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "contacta con los desarrolladores de SimpleX Chat.";
/* No comment provided by engineer. */
"Connect via contact link?" = "¿Conectar mediante enlace de contacto?";
"Connect via contact link" = "¿Conectar mediante enlace de contacto?";
/* No comment provided by engineer. */
"Connect via group link?" = "¿Conectar mediante enlace de grupo?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Conecta vía enlace / Código QR";
/* No comment provided by engineer. */
"Connect via one-time link?" = "¿Conectar mediante enlace de un uso?";
"Connect via one-time link" = "¿Conectar mediante enlace de un uso?";
/* No comment provided by engineer. */
"connected" = "conectado";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "conexión establecida";
/* No comment provided by engineer. */
"Connection request" = "Solicitud de conexión";
/* No comment provided by engineer. */
"Connection request sent!" = "¡Solicitud de conexión enviada!";
@@ -1501,13 +1492,13 @@
"Files and media prohibited!" = "¡Archivos y multimedia no permitidos!";
/* No comment provided by engineer. */
"Filter unread and favorite chats." = "Filtrar chats no leídos y favoritos.";
"Filter unread and favorite chats." = "Filtra chats no leídos y favoritos.";
/* No comment provided by engineer. */
"Finally, we have them! 🚀" = "¡Por fin los tenemos! 🚀";
/* No comment provided by engineer. */
"Find chats faster" = "Encontrar chats mas rápido";
"Find chats faster" = "Encuentra chats mas rápido";
/* No comment provided by engineer. */
"Fix" = "Reparar";
@@ -1519,7 +1510,7 @@
"Fix connection?" = "¿Reparar conexión?";
/* No comment provided by engineer. */
"Fix encryption after restoring backups." = "Reparar el cifrado tras restaurar copias de seguridad.";
"Fix encryption after restoring backups." = "Repara el cifrado tras restaurar copias de seguridad.";
/* No comment provided by engineer. */
"Fix not supported by contact" = "Corrección no compatible con el contacto";
@@ -1650,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Ocultar:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "Historial";
/* time unit */
@@ -1719,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Configuración del servidor mejorada";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "En respuesta a";
/* No comment provided by engineer. */
@@ -1728,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Modo incógnito";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "El modo incógnito no se admite aquí, tu perfil principal aparecerá en miembros del grupo";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "La función del modo incógnito es proteger la identidad del perfil principal: por cada contacto nuevo se genera un perfil aleatorio.";
/* chat list item description */
"incognito via contact address link" = "en modo incógnito mediante enlace de dirección del contacto";
@@ -1986,7 +1971,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "El miembro será expulsado del grupo. ¡No podrá deshacerse!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Error en la entrega del mensaje";
/* No comment provided by engineer. */
@@ -2302,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Pegar enlace recibido";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Pega el enlace que has recibido en el recuadro para conectar con tu contacto.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Pega el enlace que has recibido en el recuadro para conectar con tu contacto.";
/* No comment provided by engineer. */
"peer-to-peer" = "p2p";
@@ -2399,34 +2384,34 @@
"Profile update will be sent to your contacts." = "La actualización del perfil se enviará a tus contactos.";
/* No comment provided by engineer. */
"Prohibit audio/video calls." = "Prohibir las llamadas y videollamadas.";
"Prohibit audio/video calls." = "No se permiten llamadas y videollamadas.";
/* No comment provided by engineer. */
"Prohibit irreversible message deletion." = "Prohibir la eliminación irreversible de mensajes.";
"Prohibit irreversible message deletion." = "No se permite la eliminación irreversible de mensajes.";
/* No comment provided by engineer. */
"Prohibit message reactions." = "Prohibir reacciones a mensajes.";
"Prohibit message reactions." = "No se permiten reacciones a los mensajes.";
/* No comment provided by engineer. */
"Prohibit messages reactions." = "Prohibir reacciones a mensajes.";
"Prohibit messages reactions." = "No se permiten reacciones a los mensajes.";
/* No comment provided by engineer. */
"Prohibit sending direct messages to members." = "Prohibir mensajes directos a miembros.";
"Prohibit sending direct messages to members." = "No se permiten mensajes directos entre miembros.";
/* No comment provided by engineer. */
"Prohibit sending disappearing messages." = "Prohibir envío de mensajes temporales.";
"Prohibit sending disappearing messages." = "No se permiten mensajes temporales.";
/* No comment provided by engineer. */
"Prohibit sending files and media." = "No permitir el envío de archivos y multimedia.";
/* No comment provided by engineer. */
"Prohibit sending voice messages." = "Prohibir el envío de mensajes de voz.";
"Prohibit sending voice messages." = "No se permiten mensajes de voz.";
/* No comment provided by engineer. */
"Protect app screen" = "Proteger la pantalla de la aplicación";
/* No comment provided by engineer. */
"Protect your chat profiles with a password!" = "¡Protege tus perfiles de chat con contraseña!";
"Protect your chat profiles with a password!" = "¡Protege tus perfiles con contraseña!";
/* No comment provided by engineer. */
"Protocol timeout" = "Tiempo de espera del protocolo";
@@ -2435,7 +2420,7 @@
"Protocol timeout per KB" = "Límite de espera del protocolo por KB";
/* No comment provided by engineer. */
"Push notifications" = "Notificaciones push";
"Push notifications" = "Notificaciones automáticas";
/* No comment provided by engineer. */
"Rate the app" = "Valora la aplicación";
@@ -2489,7 +2474,7 @@
"Receiving via" = "Recibiendo vía";
/* No comment provided by engineer. */
"Recipients see updates as you type them." = "Los destinatarios ven actualizaciones mientras les escribes.";
"Recipients see updates as you type them." = "Los destinatarios ven actualizarse mientras escribes.";
/* No comment provided by engineer. */
"Reconnect all connected servers to force message delivery. It uses additional traffic." = "Reconectar todos los servidores conectados para forzar la entrega del mensaje. Se usa tráfico adicional.";
@@ -2498,19 +2483,19 @@
"Reconnect servers?" = "¿Reconectar servidores?";
/* No comment provided by engineer. */
"Record updated at" = "Registro actualizado a las";
"Record updated at" = "Registro actualiz.";
/* copied message info */
"Record updated at: %@" = "Registro actualizado a las: %@";
"Record updated at: %@" = "Registro actualiz: %@";
/* No comment provided by engineer. */
"Reduced battery usage" = "Uso de la batería reducido";
"Reduced battery usage" = "Reducción del uso de batería";
/* reject incoming call via notification */
"Reject" = "Rechazar";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Rechazar contacto (NO se notifica al remitente)";
"Reject (sender NOT notified)" = "Rechazar contacto (NO se notifica al remitente)";
/* No comment provided by engineer. */
"Reject contact request" = "Rechazar solicitud de contacto";
@@ -2534,7 +2519,7 @@
"Remove member?" = "¿Expulsar miembro?";
/* No comment provided by engineer. */
"Remove passphrase from keychain?" = "¿Eliminar la contraseña del llavero?";
"Remove passphrase from keychain?" = "¿Eliminar contraseña de Keychain?";
/* No comment provided by engineer. */
"removed" = "expulsado";
@@ -2627,7 +2612,7 @@
"Save archive" = "Guardar archivo";
/* No comment provided by engineer. */
"Save auto-accept settings" = "Guardar configuración de aceptación automática (auto-accept)";
"Save auto-accept settings" = "Guardar configuración de auto aceptar";
/* No comment provided by engineer. */
"Save group profile" = "Guardar perfil de grupo";
@@ -3083,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Esta configuración afecta a tu perfil actual **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Se pueden anular en la configuración de contactos";
"They can be overridden in contact and group settings." = "Se pueden anular en la configuración de contactos";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Esta acción no se puede deshacer. Se eliminarán todos los archivos y multimedia recibidos y enviados. Las imágenes de baja resolución permanecerán.";
@@ -3109,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Para conectarse, tu contacto puede escanear el código QR o usar el enlace en la aplicación.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Para conocer el perfil usado en una conexión en modo incógnito, pulsa el nombre del contacto o del grupo en la parte superior del chat.";
/* No comment provided by engineer. */
"To make a new connection" = "Para hacer una conexión nueva";
@@ -3157,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "No se puede grabar mensaje de voz";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Error inesperado: %@";
/* No comment provided by engineer. */
@@ -3479,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "La contraseña no se almacena en el dispositivo, tienes que introducirla cada vez que inicies la aplicación.";
/* No comment provided by engineer. */
"You invited your contact" = "Has invitado a tu contacto";
"You invited a contact" = "Has invitado a tu contacto";
/* No comment provided by engineer. */
"You joined this group" = "Te has unido a este grupo";
@@ -3559,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Tu perfil Chat será enviado a los miembros del grupo";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Tu perfil Chat será enviado a tu contacto";
/* No comment provided by engineer. */
"Your chat profiles" = "Mis perfiles";
@@ -3598,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Tu perfil se almacena en tu dispositivo y sólo se comparte con tus contactos.\nLos servidores de SimpleX no pueden ver tu perfil.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Tu perfil se enviará al contacto del que has recibido este enlace";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Tu perfil, contactos y mensajes entregados se almacenan en tu dispositivo.";
+20 -44
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Un nouveau contact";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Un profil aléatoire sera envoyé au contact qui vous a envoyé ce lien";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Un profil aléatoire sera envoyé à votre contact";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Une connexion TCP distincte sera utilisée **pour chaque profil de chat que vous avez dans l'application**.";
@@ -285,12 +279,12 @@
"Accept" = "Accepter";
/* No comment provided by engineer. */
"Accept contact" = "Accepter le contact";
"Accept connection request?" = "Accepter le contact";
/* notification body */
"Accept contact request from %@?" = "Accepter la demande de contact de %@?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Accepter en incognito";
/* call status */
@@ -480,7 +474,7 @@
"Authentication unavailable" = "Authentification indisponible";
/* No comment provided by engineer. */
"Auto-accept" = "Auto-acceptation";
"Auto-accept" = "Auto-accepter";
/* No comment provided by engineer. */
"Auto-accept contact requests" = "Demandes de contact auto-acceptées";
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "se connecter aux developpeurs de SimpleX Chat.";
/* No comment provided by engineer. */
"Connect via contact link?" = "Se connecter via le lien du contact?";
"Connect via contact link" = "Se connecter via le lien du contact?";
/* No comment provided by engineer. */
"Connect via group link?" = "Se connecter via le lien du groupe ?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Se connecter via un lien / code QR";
/* No comment provided by engineer. */
"Connect via one-time link?" = "Se connecter via un lien unique?";
"Connect via one-time link" = "Se connecter via le lien du contact?";
/* No comment provided by engineer. */
"connected" = "connecté";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "connexion établie";
/* No comment provided by engineer. */
"Connection request" = "Demande de connexion";
/* No comment provided by engineer. */
"Connection request sent!" = "Demande de connexion envoyée !";
@@ -889,7 +880,7 @@
"Database ID: %d" = "ID de base de données : %d";
/* No comment provided by engineer. */
"Database IDs and Transport isolation option." = "IDs de base de données et option d'isolation du transport.";
"Database IDs and Transport isolation option." = "IDs de base de données et option d'isolement du transport.";
/* No comment provided by engineer. */
"Database is encrypted using a random passphrase, you can change it." = "La base de données est chiffrée à l'aide d'une phrase secrète aléatoire, que vous pouvez modifier.";
@@ -1087,7 +1078,7 @@
"different migration in the app/database: %@ / %@" = "migration différente dans l'app/la base de données : %@ / %@";
/* No comment provided by engineer. */
"Different names, avatars and transport isolation." = "Différents noms, avatars et mode d'isolation de transport.";
"Different names, avatars and transport isolation." = "Différents noms, avatars et modes d'isolement de transport.";
/* connection level description */
"direct" = "direct";
@@ -1650,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Cacher :";
/* copied message info */
/* No comment provided by engineer. */
"History" = "Historique";
/* time unit */
@@ -1719,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Configuration de serveur améliorée";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "En réponse à";
/* No comment provided by engineer. */
@@ -1728,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Mode Incognito";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "Le mode Incognito n'est pas supporté ici - votre profil principal sera envoyé aux membres du groupe";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "Le mode Incognito protège la confidentialité de votre profil principal — pour chaque nouveau contact un nouveau profil aléatoire est créé.";
/* chat list item description */
"incognito via contact address link" = "mode incognito via le lien d'adresse du contact";
@@ -1986,7 +1971,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Ce membre sera retiré du groupe - impossible de revenir en arrière!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Erreur de distribution du message";
/* No comment provided by engineer. */
@@ -2302,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Coller le lien reçu";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Collez le lien que vous avez reçu dans le cadre ci-dessous pour vous connecter avec votre contact.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Collez le lien que vous avez reçu dans le cadre ci-dessous pour vous connecter avec votre contact.";
/* No comment provided by engineer. */
"peer-to-peer" = "pair-à-pair";
@@ -2510,7 +2495,7 @@
"Reject" = "Rejeter";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Rejeter le contact (l'expéditeur N'en est PAS informé)";
"Reject (sender NOT notified)" = "Rejeter le contact (l'expéditeur N'en est PAS informé)";
/* No comment provided by engineer. */
"Reject contact request" = "Rejeter la demande de contact";
@@ -2672,7 +2657,7 @@
"Scan server QR code" = "Scanner un code QR de serveur";
/* No comment provided by engineer. */
"Search" = "Chercher";
"Search" = "Recherche";
/* network option */
"sec" = "sec";
@@ -2972,7 +2957,7 @@
"Tap button " = "Appuyez sur le bouton ";
/* No comment provided by engineer. */
"Tap to activate profile." = "Appuyez pour activer le profil.";
"Tap to activate profile." = "Appuyez pour activer un profil.";
/* No comment provided by engineer. */
"Tap to join" = "Appuyez pour rejoindre";
@@ -3083,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Ces paramètres s'appliquent à votre profil actuel **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Ils peuvent être remplacés dans les paramètres des contacts";
"They can be overridden in contact and group settings." = "Ils peuvent être remplacés dans les paramètres des contacts";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Cette action ne peut être annulée - tous les fichiers et médias reçus et envoyés seront supprimés. Les photos à faible résolution seront conservées.";
@@ -3109,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Pour se connecter, votre contact peut scanner le code QR ou utiliser le lien dans l'application.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Pour trouver le profil utilisé lors d'une connexion incognito, appuyez sur le nom du contact ou du groupe en haut du chat.";
/* No comment provided by engineer. */
"To make a new connection" = "Pour établir une nouvelle connexion";
@@ -3137,7 +3119,7 @@
"To verify end-to-end encryption with your contact compare (or scan) the code on your devices." = "Pour vérifier le chiffrement de bout en bout avec votre contact, comparez (ou scannez) le code sur vos appareils.";
/* No comment provided by engineer. */
"Transport isolation" = "Isolement du transport";
"Transport isolation" = "Transport isolé";
/* No comment provided by engineer. */
"Trying to connect to the server used to receive messages from this contact (error: %@)." = "Tentative de connexion au serveur utilisé pour recevoir les messages de ce contact (erreur : %@).";
@@ -3157,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Impossible d'enregistrer un message vocal";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Erreur inattendue: %@";
/* No comment provided by engineer. */
@@ -3221,7 +3203,7 @@
"Update network settings?" = "Mettre à jour les paramètres réseau ?";
/* No comment provided by engineer. */
"Update transport isolation mode?" = "Mettre à jour le mode d'isolation du transport ?";
"Update transport isolation mode?" = "Mettre à jour le mode d'isolement du transport ?";
/* rcv group event chat item */
"updated group profile" = "mise à jour du profil de groupe";
@@ -3479,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "Vous devez saisir la phrase secrète à chaque fois que l'application démarre - elle n'est pas stockée sur l'appareil.";
/* No comment provided by engineer. */
"You invited your contact" = "Vous avez invité votre contact";
"You invited a contact" = "Vous avez invité votre contact";
/* No comment provided by engineer. */
"You joined this group" = "Vous avez rejoint ce groupe";
@@ -3559,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Votre profil de chat sera envoyé aux membres du groupe";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Votre profil de chat sera envoyé à votre contact";
/* No comment provided by engineer. */
"Your chat profiles" = "Vos profils de chat";
@@ -3598,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Votre profil est stocké sur votre appareil et est seulement partagé avec vos contacts.\nLes serveurs SimpleX ne peuvent pas voir votre profil.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Votre profil sera envoyé au contact qui vous a envoyé ce lien";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Votre profil, vos contacts et les messages reçus sont stockés sur votre appareil.";
+13 -37
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Un contatto nuovo";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Verrà inviato un profilo casuale al contatto da cui hai ricevuto questo link";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Verrà inviato un profilo casuale al tuo contatto";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Verrà usata una connessione TCP separata **per ogni profilo di chat presente nell'app**.";
@@ -285,12 +279,12 @@
"Accept" = "Accetta";
/* No comment provided by engineer. */
"Accept contact" = "Accetta il contatto";
"Accept connection request?" = "Accetta il contatto";
/* notification body */
"Accept contact request from %@?" = "Accettare la richiesta di contatto da %@?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Accetta in incognito";
/* call status */
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "connettiti agli sviluppatori di SimpleX Chat.";
/* No comment provided by engineer. */
"Connect via contact link?" = "Connettere via link del contatto?";
"Connect via contact link" = "Connettere via link del contatto?";
/* No comment provided by engineer. */
"Connect via group link?" = "Connettere via link del gruppo?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Connetti via link / codice QR";
/* No comment provided by engineer. */
"Connect via one-time link?" = "Connettere via link una tantum?";
"Connect via one-time link" = "Connettere via link una tantum?";
/* No comment provided by engineer. */
"connected" = "connesso/a";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "connessione stabilita";
/* No comment provided by engineer. */
"Connection request" = "Richiesta di connessione";
/* No comment provided by engineer. */
"Connection request sent!" = "Richiesta di connessione inviata!";
@@ -1650,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Nascondi:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "Cronologia";
/* time unit */
@@ -1719,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Configurazione del server migliorata";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "In risposta a";
/* No comment provided by engineer. */
@@ -1728,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Modalità incognito";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "La modalità in incognito non è supportata qui: il tuo profilo principale verrà inviato ai membri del gruppo";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "La modalità in incognito protegge la privacy del nome e dell'immagine del tuo profilo principale: per ogni nuovo contatto viene creato un nuovo profilo casuale.";
/* chat list item description */
"incognito via contact address link" = "incognito via link indirizzo del contatto";
@@ -1986,7 +1971,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Il membro verrà rimosso dal gruppo, non è reversibile!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Errore di recapito del messaggio";
/* No comment provided by engineer. */
@@ -2302,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Incolla il link ricevuto";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Incolla il link che hai ricevuto nella casella sottostante per connetterti con il tuo contatto.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Incolla il link che hai ricevuto nella casella sottostante per connetterti con il tuo contatto.";
/* No comment provided by engineer. */
"peer-to-peer" = "peer-to-peer";
@@ -2510,7 +2495,7 @@
"Reject" = "Rifiuta";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Rifiuta contatto (mittente NON avvisato)";
"Reject (sender NOT notified)" = "Rifiuta contatto (mittente NON avvisato)";
/* No comment provided by engineer. */
"Reject contact request" = "Rifiuta la richiesta di contatto";
@@ -3083,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Queste impostazioni sono per il tuo profilo attuale **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Possono essere sovrascritte nelle impostazioni dei contatti";
"They can be overridden in contact and group settings." = "Possono essere sovrascritte nelle impostazioni dei contatti";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Questa azione non può essere annullata: tutti i file e i media ricevuti e inviati verranno eliminati. Rimarranno le immagini a bassa risoluzione.";
@@ -3109,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Per connettervi, il tuo contatto può scansionare il codice QR o usare il link nell'app.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Per trovare il profilo usato per una connessione in incognito, tocca il nome del contatto o del gruppo in cima alla chat.";
/* No comment provided by engineer. */
"To make a new connection" = "Per creare una nuova connessione";
@@ -3157,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Impossibile registrare il messaggio vocale";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Errore imprevisto: % @";
/* No comment provided by engineer. */
@@ -3479,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "Devi inserire la password ogni volta che si avvia l'app: non viene memorizzata sul dispositivo.";
/* No comment provided by engineer. */
"You invited your contact" = "Hai invitato il contatto";
"You invited a contact" = "Hai invitato il contatto";
/* No comment provided by engineer. */
"You joined this group" = "Sei entrato/a in questo gruppo";
@@ -3559,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Il tuo profilo di chat verrà inviato ai membri del gruppo";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Il tuo profilo di chat verrà inviato al tuo contatto";
/* No comment provided by engineer. */
"Your chat profiles" = "I tuoi profili di chat";
@@ -3598,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Il tuo profilo è memorizzato sul tuo dispositivo e condiviso solo con i tuoi contatti.\nI server di SimpleX non possono vedere il tuo profilo.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Il tuo profilo verrà inviato al contatto da cui hai ricevuto questo link";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Il tuo profilo, i contatti e i messaggi recapitati sono memorizzati sul tuo dispositivo.";
+11 -35
View File
@@ -235,12 +235,6 @@
/* notification title */
"A new contact" = "新しい連絡先";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "このリンクの送信元にランダムなプロフィール(ダミー)が送られます";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "連絡先にランダムなプロフィール(ダミー)が送られます";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "**アプリ内のチャット プロフィールごとに**、個別の TCP 接続が使用されます。";
@@ -267,12 +261,12 @@
"Accept" = "承諾";
/* No comment provided by engineer. */
"Accept contact" = "連絡を受け入れる";
"Accept connection request?" = "連絡を受け入れる";
/* notification body */
"Accept contact request from %@?" = "%@ からの連絡要求を受け入れますか?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "シークレットモードで承諾";
/* call status */
@@ -661,7 +655,7 @@
"connect to SimpleX Chat developers." = "SimpleX Chat 開発者に接続します。";
/* No comment provided by engineer. */
"Connect via contact link?" = "連絡先リンク経由で接続しますか?";
"Connect via contact link" = "連絡先リンク経由で接続しますか?";
/* No comment provided by engineer. */
"Connect via group link?" = "グループリンク経由で接続しますか?";
@@ -673,7 +667,7 @@
"Connect via link / QR code" = "リンク・QRコード経由で接続";
/* No comment provided by engineer. */
"Connect via one-time link?" = "使い捨てリンク経由で接続しますか?";
"Connect via one-time link" = "使い捨てリンク経由で接続しますか?";
/* No comment provided by engineer. */
"connected" = "接続中";
@@ -717,9 +711,6 @@
/* chat list item title (it should not be shown */
"connection established" = "接続済み";
/* No comment provided by engineer. */
"Connection request" = "接続のリクエスト";
/* No comment provided by engineer. */
"Connection request sent!" = "接続リクエストを送信しました!";
@@ -1500,7 +1491,7 @@
/* No comment provided by engineer. */
"Hide:" = "隠す:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "履歴";
/* time unit */
@@ -1575,12 +1566,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "シークレットモード";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "ここではシークレットモードが無効です。メインのプロフィールがグループのメンバーに送られます";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "シークレットモードとは、メインのプロフィールとプロフィール画像を守るために、新しい連絡先を追加する時に、その連絡先に対してランダムなプロフィールが作成されます。";
/* chat list item description */
"incognito via contact address link" = "連絡先リンク経由でシークレットモード";
@@ -1827,7 +1812,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "メンバーをグループから除名する (※元に戻せません※)!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "メッセージ送信エラー";
/* No comment provided by engineer. */
@@ -2128,8 +2113,8 @@
/* No comment provided by engineer. */
"Paste received link" = "頂いたリンクを貼り付ける";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "連絡相手から頂いたリンクを以下の入力欄に貼り付けて繋がります。";
/* placeholder */
"Paste the link you received to connect with your contact." = "連絡相手から頂いたリンクを以下の入力欄に貼り付けて繋がります。";
/* No comment provided by engineer. */
"peer-to-peer" = "P2P";
@@ -2318,7 +2303,7 @@
"Reject" = "拒否";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "連絡を拒否(送信者には通知されません)";
"Reject (sender NOT notified)" = "連絡を拒否(送信者には通知されません)";
/* No comment provided by engineer. */
"Reject contact request" = "連絡要求を拒否する";
@@ -2872,9 +2857,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "接続するにはQRコードを読み込むか、アプリ内のリンクを使用する必要があります。";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "シークレットモード接続のプロフィールを確認するには、チャットの上部の連絡先、またはグループ名をタップします。";
/* No comment provided by engineer. */
"To make a new connection" = "新規に接続する場合";
@@ -2920,7 +2902,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "音声メッセージを録音できません";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "予期しないエラー: %@";
/* No comment provided by engineer. */
@@ -3233,7 +3215,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "アプリ起動時にパスフレーズを入力しなければなりません。端末に保存されてません。";
/* No comment provided by engineer. */
"You invited your contact" = "連絡先に招待を送りました";
"You invited a contact" = "連絡先に招待を送りました";
/* No comment provided by engineer. */
"You joined this group" = "グループに参加しました";
@@ -3313,9 +3295,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "あなたのチャットプロフィールが他のグループメンバーに送られます";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "あなたのチャットプロフィールが連絡相手に送られます";
/* No comment provided by engineer. */
"Your chat profiles" = "あなたのチャットプロフィール";
@@ -3352,9 +3331,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "プロフィールはデバイスに保存され、連絡先とのみ共有されます。\nSimpleX サーバーはあなたのプロファイルを参照できません。";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "あなたのプロフィールは、このリンクを受け取った連絡先に送信されます";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "あなたのプロフィール、連絡先、送信したメッセージがご自分の端末に保存されます。";
+25 -49
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Een nieuw contact";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Er wordt een willekeurig profiel verzonden naar het contact van wie je deze link hebt ontvangen";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Er wordt een willekeurig profiel naar uw contactpersoon verzonden";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Er wordt een aparte TCP-verbinding gebruikt **voor elk chat profiel dat je in de app hebt**.";
@@ -285,12 +279,12 @@
"Accept" = "Accepteer";
/* No comment provided by engineer. */
"Accept contact" = "Accepteer contactpersoon";
"Accept connection request?" = "Accepteer contactpersoon";
/* notification body */
"Accept contact request from %@?" = "Accepteer contactverzoek van %@?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Accepteer incognito";
/* call status */
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "maak verbinding met SimpleX Chat-ontwikkelaars.";
/* No comment provided by engineer. */
"Connect via contact link?" = "Verbinden via contact link?";
"Connect via contact link" = "Verbinden via contact link?";
/* No comment provided by engineer. */
"Connect via group link?" = "Verbinden via groep link?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Maak verbinding via link / QR-code";
/* No comment provided by engineer. */
"Connect via one-time link?" = "Verbinden via een eenmalige link?";
"Connect via one-time link" = "Verbinden via een eenmalige link?";
/* No comment provided by engineer. */
"connected" = "verbonden";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "verbinding gemaakt";
/* No comment provided by engineer. */
"Connection request" = "Verbindingsverzoek";
/* No comment provided by engineer. */
"Connection request sent!" = "Verbindingsverzoek verzonden!";
@@ -1120,10 +1111,10 @@
"Disappearing messages are prohibited in this group." = "Verdwijnende berichten zijn verboden in deze groep.";
/* No comment provided by engineer. */
"Disappears at" = "Verdwijnt om";
"Disappears at" = "Verdwijnt op";
/* copied message info */
"Disappears at: %@" = "Verdwijnt om: %@";
"Disappears at: %@" = "Verdwijnt op: %@";
/* server test step */
"Disconnect" = "verbinding verbreken";
@@ -1360,7 +1351,7 @@
"Error deleting user profile" = "Fout bij het verwijderen van gebruikers profiel";
/* No comment provided by engineer. */
"Error enabling delivery receipts!" = "Fout bij het inschakelen van ontvangstbevestiging!";
"Error enabling delivery receipts!" = "Fout bij het inschakelen van ontvangst bevestiging!";
/* No comment provided by engineer. */
"Error enabling notifications" = "Fout bij inschakelen van meldingen";
@@ -1411,7 +1402,7 @@
"Error sending message" = "Fout bij verzenden van bericht";
/* No comment provided by engineer. */
"Error setting delivery receipts!" = "Fout bij het instellen van ontvangstbevestiging!";
"Error setting delivery receipts!" = "Fout bij het instellen van ontvangst bevestiging!";
/* No comment provided by engineer. */
"Error starting chat" = "Fout bij het starten van de chat";
@@ -1480,7 +1471,7 @@
"File will be deleted from servers." = "Het bestand wordt van de servers verwijderd.";
/* No comment provided by engineer. */
"File will be received when your contact completes uploading it." = "Het bestand wordt ontvangen wanneer uw contactpersoon het uploaden heeft voltooid.";
"File will be received when your contact completes uploading it." = "Het bestand wordt gedownload wanneer uw contactpersoon het uploaden heeft voltooid.";
/* No comment provided by engineer. */
"File will be received when your contact is online, please wait or check later!" = "Het bestand wordt ontvangen wanneer uw contact persoon online is, even geduld a.u.b. of controleer later!";
@@ -1650,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Verbergen:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "Geschiedenis";
/* time unit */
@@ -1693,7 +1684,7 @@
"Ignore" = "Negeren";
/* No comment provided by engineer. */
"Image will be received when your contact completes uploading it." = "De afbeelding wordt ontvangen wanneer uw contactpersoon het uploaden heeft voltooid.";
"Image will be received when your contact completes uploading it." = "De afbeelding wordt gedownload wanneer uw contactpersoon het uploaden heeft voltooid.";
/* No comment provided by engineer. */
"Image will be received when your contact is online, please wait or check later!" = "De afbeelding wordt ontvangen wanneer uw contact online is, even geduld a.u.b. of kijk later!";
@@ -1719,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Verbeterde serverconfiguratie";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "In antwoord op";
/* No comment provided by engineer. */
@@ -1728,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Incognito modus";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "Incognito modus wordt hier niet ondersteund, uw hoofdprofiel wordt naar groepsleden verzonden";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "De incognito modus beschermt de privacy van uw hoofdprofielnaam en afbeelding, voor elk nieuw contact wordt een nieuw willekeurig profiel gemaakt.";
/* chat list item description */
"incognito via contact address link" = "incognito via contact adres link";
@@ -1986,11 +1971,11 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Gebruiker wordt uit de groep verwijderd, dit kan niet ongedaan worden gemaakt!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Fout bij bezorging van bericht";
/* No comment provided by engineer. */
"Message delivery receipts!" = "Ontvangstbevestiging voor berichten!";
"Message delivery receipts!" = "Ontvangst bevestiging voor berichten!";
/* No comment provided by engineer. */
"Message draft" = "Concept bericht";
@@ -2302,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Plak de ontvangen link";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Plak de link die je hebt ontvangen in het vak hieronder om verbinding te maken met je contactpersoon.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Plak de link die je hebt ontvangen in het vak hieronder om verbinding te maken met je contactpersoon.";
/* No comment provided by engineer. */
"peer-to-peer" = "peer-to-peer";
@@ -2510,7 +2495,7 @@
"Reject" = "Afwijzen";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Contact afwijzen (afzender NIET op de hoogte)";
"Reject (sender NOT notified)" = "Contact afwijzen (afzender NIET op de hoogte)";
/* No comment provided by engineer. */
"Reject contact request" = "Contactverzoek afwijzen";
@@ -2753,19 +2738,19 @@
"Sender may have deleted the connection request." = "De afzender heeft mogelijk het verbindingsverzoek verwijderd.";
/* No comment provided by engineer. */
"Sending delivery receipts will be enabled for all contacts in all visible chat profiles." = "Het verzenden van ontvangstbevestiging wordt ingeschakeld voor alle contacten in alle zichtbare chatprofielen.";
"Sending delivery receipts will be enabled for all contacts in all visible chat profiles." = "Het verzenden van ontvangst bevestiging wordt ingeschakeld voor alle contacten in alle zichtbare chatprofielen.";
/* No comment provided by engineer. */
"Sending delivery receipts will be enabled for all contacts." = "Het verzenden van ontvangstbevestiging wordt ingeschakeld voor alle contactpersonen.";
"Sending delivery receipts will be enabled for all contacts." = "Het verzenden van ontvangst bevestiging wordt ingeschakeld voor alle contactpersonen.";
/* No comment provided by engineer. */
"Sending file will be stopped." = "Het verzenden van het bestand wordt gestopt.";
/* No comment provided by engineer. */
"Sending receipts is disabled for %lld contacts" = "Het verzenden van ontvangstbevestiging is uitgeschakeld voor %lld-contactpersonen";
"Sending receipts is disabled for %lld contacts" = "Het verzenden van ontvangst bevestiging is uitgeschakeld voor %lld-contactpersonen";
/* No comment provided by engineer. */
"Sending receipts is enabled for %lld contacts" = "Het verzenden van ontvangstbevestiging is ingeschakeld voor %lld-contactpersonen";
"Sending receipts is enabled for %lld contacts" = "Het verzenden van ontvangst bevestiging is ingeschakeld voor %lld-contactpersonen";
/* No comment provided by engineer. */
"Sending via" = "Verzenden via";
@@ -3083,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Deze instellingen zijn voor uw huidige profiel **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Ze kunnen worden overschreven in contactinstellingen";
"They can be overridden in contact and group settings." = "Ze kunnen worden overschreven in contactinstellingen";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Deze actie kan niet ongedaan worden gemaakt, alle ontvangen en verzonden bestanden en media worden verwijderd. Foto's met een lage resolutie blijven behouden.";
@@ -3109,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Om verbinding te maken, kan uw contact persoon de QR-code scannen of de link in de app gebruiken.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Om het profiel te vinden dat wordt gebruikt voor een incognito verbinding, tikt u op de naam van het contact of de groep bovenaan de chat.";
/* No comment provided by engineer. */
"To make a new connection" = "Om een nieuwe verbinding te maken";
@@ -3157,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Kan spraakbericht niet opnemen";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Onverwachte fout: %@";
/* No comment provided by engineer. */
@@ -3296,7 +3278,7 @@
"video call (not e2e encrypted)" = "video gesprek (niet e2e versleuteld)";
/* No comment provided by engineer. */
"Video will be received when your contact completes uploading it." = "De video wordt ontvangen wanneer uw contactpersoon het uploaden heeft voltooid.";
"Video will be received when your contact completes uploading it." = "De video wordt gedownload wanneer uw contactpersoon het uploaden heeft voltooid.";
/* No comment provided by engineer. */
"Video will be received when your contact is online, please wait or check later!" = "De video wordt ontvangen wanneer uw contact online is, even geduld a.u.b. of kijk later!";
@@ -3479,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "U moet elke keer dat de app start het wachtwoord invoeren, deze wordt niet op het apparaat opgeslagen.";
/* No comment provided by engineer. */
"You invited your contact" = "Je hebt je contactpersoon uitgenodigd";
"You invited a contact" = "Je hebt je contactpersoon uitgenodigd";
/* No comment provided by engineer. */
"You joined this group" = "Je bent lid geworden van deze groep";
@@ -3559,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Uw chat profiel wordt verzonden naar de groepsleden";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Uw chat profiel wordt naar uw contactpersoon verzonden";
/* No comment provided by engineer. */
"Your chat profiles" = "Uw chat profielen";
@@ -3598,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Uw profiel wordt op uw apparaat opgeslagen en alleen gedeeld met uw contacten.\nSimpleX servers kunnen uw profiel niet zien.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Je profiel wordt verzonden naar het contact van wie je deze link hebt ontvangen";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Uw profiel, contacten en afgeleverde berichten worden op uw apparaat opgeslagen.";
+13 -37
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Nowy kontakt";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Losowy profil zostanie wysłany do kontaktu, od którego otrzymałeś ten link";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Losowy profil zostanie wysłany do Twojego kontaktu";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Oddzielne połączenie TCP będzie używane **dla każdego profilu czatu, który masz w aplikacji**.";
@@ -285,12 +279,12 @@
"Accept" = "Akceptuj";
/* No comment provided by engineer. */
"Accept contact" = "Akceptuj kontakt";
"Accept connection request?" = "Akceptuj kontakt";
/* notification body */
"Accept contact request from %@?" = "Zaakceptuj prośbę o kontakt od %@?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Akceptuj incognito";
/* call status */
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "połącz się z deweloperami SimpleX Chat.";
/* No comment provided by engineer. */
"Connect via contact link?" = "Połączyć się przez link kontaktowy?";
"Connect via contact link" = "Połączyć się przez link kontaktowy?";
/* No comment provided by engineer. */
"Connect via group link?" = "Połącz się przez link grupowy?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Połącz się przez link / kod QR";
/* No comment provided by engineer. */
"Connect via one-time link?" = "Połączyć się przez jednorazowy link?";
"Connect via one-time link" = "Połączyć się przez jednorazowy link?";
/* No comment provided by engineer. */
"connected" = "połączony";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "połączenie ustanowione";
/* No comment provided by engineer. */
"Connection request" = "Prośba o połączenie";
/* No comment provided by engineer. */
"Connection request sent!" = "Prośba o połączenie wysłana!";
@@ -1650,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Ukryj:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "Historia";
/* time unit */
@@ -1719,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Ulepszona konfiguracja serwera";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "W odpowiedzi na";
/* No comment provided by engineer. */
@@ -1728,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Tryb incognito";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "Tryb Incognito nie jest tutaj obsługiwany - główny profil zostanie wysłany do członków grupy";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "Tryb incognito chroni prywatność nazwy i obrazu głównego profilu — dla każdego nowego kontaktu tworzony jest nowy losowy profil.";
/* chat list item description */
"incognito via contact address link" = "incognito poprzez link adresu kontaktowego";
@@ -1986,7 +1971,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Członek zostanie usunięty z grupy - nie można tego cofnąć!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Błąd dostarczenia wiadomości";
/* No comment provided by engineer. */
@@ -2302,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Wklej otrzymany link";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Wklej otrzymany link w pole poniżej, aby połączyć się z kontaktem.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Wklej otrzymany link w pole poniżej, aby połączyć się z kontaktem.";
/* No comment provided by engineer. */
"peer-to-peer" = "peer-to-peer";
@@ -2510,7 +2495,7 @@
"Reject" = "Odrzuć";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Odrzuć kontakt (nadawca NIE został powiadomiony)";
"Reject (sender NOT notified)" = "Odrzuć kontakt (nadawca NIE został powiadomiony)";
/* No comment provided by engineer. */
"Reject contact request" = "Odrzuć prośbę kontaktu";
@@ -3083,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Te ustawienia dotyczą Twojego bieżącego profilu **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Można je nadpisać w ustawieniach kontaktu";
"They can be overridden in contact and group settings." = "Można je nadpisać w ustawieniach kontaktu";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Tego działania nie można cofnąć - wszystkie odebrane i wysłane pliki oraz media zostaną usunięte. Obrazy o niskiej rozdzielczości pozostaną.";
@@ -3109,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Aby się połączyć, Twój kontakt może zeskanować kod QR lub skorzystać z linku w aplikacji.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Aby znaleźć profil używany do połączenia incognito, dotknij nazwę kontaktu lub grupy w górnej części czatu.";
/* No comment provided by engineer. */
"To make a new connection" = "Aby nawiązać nowe połączenie";
@@ -3157,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Nie można nagrać wiadomości głosowej";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Nieoczekiwany błąd: %@";
/* No comment provided by engineer. */
@@ -3479,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "Musisz wprowadzić hasło przy każdym uruchomieniu aplikacji - nie jest one przechowywane na urządzeniu.";
/* No comment provided by engineer. */
"You invited your contact" = "Zaprosiłeś swój kontakt";
"You invited a contact" = "Zaprosiłeś swój kontakt";
/* No comment provided by engineer. */
"You joined this group" = "Dołączyłeś do tej grupy";
@@ -3559,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Twój profil czatu zostanie wysłany do członków grupy";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Twój profil czatu zostanie wysłany do Twojego kontaktu";
/* No comment provided by engineer. */
"Your chat profiles" = "Twoje profile czatu";
@@ -3598,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Twój profil jest przechowywany na urządzeniu i udostępniany tylko Twoim kontaktom.\nSerwery SimpleX nie mogą zobaczyć Twojego profilu.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Twój profil zostanie wysłany do kontaktu, od którego otrzymałeś ten link";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Twój profil, kontakty i dostarczone wiadomości są przechowywane na Twoim urządzeniu.";
+13 -37
View File
@@ -244,12 +244,6 @@
/* notification title */
"A new contact" = "Новый контакт";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "Контакту, от которого Вы получили эту ссылку, будет отправлен случайный профиль";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "Вашему контакту будет отправлен случайный профиль";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "Отдельное TCP-соединение будет использоваться **для каждого профиля чата, который Вы имеете в приложении**.";
@@ -285,12 +279,12 @@
"Accept" = "Принять";
/* No comment provided by engineer. */
"Accept contact" = "Принять запрос";
"Accept connection request?" = "Принять запрос?";
/* notification body */
"Accept contact request from %@?" = "Принять запрос на соединение от %@?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "Принять инкогнито";
/* call status */
@@ -700,7 +694,7 @@
"connect to SimpleX Chat developers." = "соединитесь с разработчиками.";
/* No comment provided by engineer. */
"Connect via contact link?" = "Соединиться через ссылку-контакт?";
"Connect via contact link" = "Соединиться через ссылку-контакт";
/* No comment provided by engineer. */
"Connect via group link?" = "Соединиться через ссылку группы?";
@@ -712,7 +706,7 @@
"Connect via link / QR code" = "Соединиться через ссылку / QR код";
/* No comment provided by engineer. */
"Connect via one-time link?" = "Соединиться через одноразовую ссылку?";
"Connect via one-time link" = "Соединиться через одноразовую ссылку?";
/* No comment provided by engineer. */
"connected" = "соединение установлено";
@@ -756,9 +750,6 @@
/* chat list item title (it should not be shown */
"connection established" = "соединение установлено";
/* No comment provided by engineer. */
"Connection request" = "Запрос на соединение";
/* No comment provided by engineer. */
"Connection request sent!" = "Запрос на соединение отправлен!";
@@ -1650,7 +1641,7 @@
/* No comment provided by engineer. */
"Hide:" = "Скрыть:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "История";
/* time unit */
@@ -1719,7 +1710,7 @@
/* No comment provided by engineer. */
"Improved server configuration" = "Улучшенная конфигурация серверов";
/* copied message info */
/* No comment provided by engineer. */
"In reply to" = "В ответ на";
/* No comment provided by engineer. */
@@ -1728,12 +1719,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "Режим Инкогнито";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "Режим Инкогнито здесь не поддерживается - Ваш основной профиль будет отправлен членам группы";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "Режим Инкогнито защищает конфиденциальность имени и изображения Вашего основного профиля — для каждого нового контакта создается новый случайный профиль.";
/* chat list item description */
"incognito via contact address link" = "инкогнито через ссылку-контакт";
@@ -1986,7 +1971,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "Член группы будет удален - это действие нельзя отменить!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "Ошибка доставки сообщения";
/* No comment provided by engineer. */
@@ -2302,8 +2287,8 @@
/* No comment provided by engineer. */
"Paste received link" = "Вставить полученную ссылку";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "Чтобы соединиться, вставьте ссылку, полученную от Вашего контакта.";
/* placeholder */
"Paste the link you received to connect with your contact." = "Чтобы соединиться, вставьте ссылку, полученную от Вашего контакта.";
/* No comment provided by engineer. */
"peer-to-peer" = "peer-to-peer";
@@ -2510,7 +2495,7 @@
"Reject" = "Отклонить";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "Отклонить (не уведомляя отправителя)";
"Reject (sender NOT notified)" = "Отклонить (не уведомляя отправителя)";
/* No comment provided by engineer. */
"Reject contact request" = "Отклонить запрос";
@@ -3083,7 +3068,7 @@
"These settings are for your current profile **%@**." = "Установки для Вашего активного профиля **%@**.";
/* No comment provided by engineer. */
"They can be overridden in contact settings" = "Они могут быть переопределены в настройках контактов";
"They can be overridden in contact and group settings." = "Они могут быть переопределены в настройках контактов и групп.";
/* No comment provided by engineer. */
"This action cannot be undone - all received and sent files and media will be deleted. Low resolution pictures will remain." = "Это действие нельзя отменить — все полученные и отправленные файлы будут удалены. Изображения останутся в низком разрешении.";
@@ -3109,9 +3094,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "Чтобы соединиться с Вами, Ваш контакт может отсканировать QR-код или использовать ссылку в приложении.";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "Чтобы найти инкогнито профиль, используемый в разговоре, нажмите на имя контакта или группы в верхней части чата.";
/* No comment provided by engineer. */
"To make a new connection" = "Чтобы соединиться";
@@ -3157,7 +3139,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "Невозможно записать голосовое сообщение";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "Неожиданная ошибка: %@";
/* No comment provided by engineer. */
@@ -3479,7 +3461,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "Пароль не сохранен на устройстве — Вы будете должны ввести его при каждом запуске чата.";
/* No comment provided by engineer. */
"You invited your contact" = "Вы пригласили Ваш контакт";
"You invited a contact" = "Вы пригласили контакт";
/* No comment provided by engineer. */
"You joined this group" = "Вы вступили в эту группу";
@@ -3559,9 +3541,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "Ваш профиль чата будет отправлен членам группы";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "Ваш профиль будет отправлен Вашему контакту";
/* No comment provided by engineer. */
"Your chat profiles" = "Ваши профили чата";
@@ -3598,9 +3577,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "Ваш профиль хранится на Вашем устройстве и отправляется только Вашим контактам.\nSimpleX серверы не могут получить доступ к Вашему профилю.";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "Ваш профиль будет отправлен Вашему контакту.";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "Ваш профиль, контакты и доставленные сообщения хранятся на Вашем устройстве.";
+11 -35
View File
@@ -235,12 +235,6 @@
/* notification title */
"A new contact" = "新联系人";
/* No comment provided by engineer. */
"A random profile will be sent to the contact that you received this link from" = "一个随机个人资料将被发送至给予您链接的联系人那里";
/* No comment provided by engineer. */
"A random profile will be sent to your contact" = "一个随机资料将发送给您的联系人";
/* No comment provided by engineer. */
"A separate TCP connection will be used **for each chat profile you have in the app**." = "一个单独的 TCP 连接将被用于**您在应用程序中的每个聊天资料**。";
@@ -276,12 +270,12 @@
"Accept" = "接受";
/* No comment provided by engineer. */
"Accept contact" = "接受联系人";
"Accept connection request?" = "接受联系人";
/* notification body */
"Accept contact request from %@?" = "接受来自 %@ 的联系人请求?";
/* No comment provided by engineer. */
/* accept contact request via notification */
"Accept incognito" = "接受隐身聊天";
/* call status */
@@ -679,7 +673,7 @@
"connect to SimpleX Chat developers." = "连接到 SimpleX Chat 开发者。";
/* No comment provided by engineer. */
"Connect via contact link?" = "通过联系人链接进行连接?";
"Connect via contact link" = "通过联系人链接进行连接?";
/* No comment provided by engineer. */
"Connect via group link?" = "通过群组链接连接?";
@@ -691,7 +685,7 @@
"Connect via link / QR code" = "通过群组链接/二维码连接";
/* No comment provided by engineer. */
"Connect via one-time link?" = "通过一次性链接连接?";
"Connect via one-time link" = "通过一次性链接连接?";
/* No comment provided by engineer. */
"connected" = "已连接";
@@ -735,9 +729,6 @@
/* chat list item title (it should not be shown */
"connection established" = "连接已建立";
/* No comment provided by engineer. */
"Connection request" = "连接请求";
/* No comment provided by engineer. */
"Connection request sent!" = "已发送连接请求!";
@@ -1539,7 +1530,7 @@
/* No comment provided by engineer. */
"Hide:" = "隐藏:";
/* copied message info */
/* No comment provided by engineer. */
"History" = "历史记录";
/* time unit */
@@ -1614,12 +1605,6 @@
/* No comment provided by engineer. */
"Incognito mode" = "隐身模式";
/* No comment provided by engineer. */
"Incognito mode is not supported here - your main profile will be sent to group members" = "此处不支持隐身模式——您的主要个人资料将发送给群组成员";
/* No comment provided by engineer. */
"Incognito mode protects the privacy of your main profile name and image — for each new contact a new random profile is created." = "隐身模式可以保护你的主要个人资料名称和图像的隐私——对于每个新的联系人,都会创建一个新的随机个人资料。";
/* chat list item description */
"incognito via contact address link" = "通过联系人地址链接隐身聊天";
@@ -1866,7 +1851,7 @@
/* No comment provided by engineer. */
"Member will be removed from group - this cannot be undone!" = "成员将被移出群组——此操作无法撤消!";
/* No comment provided by engineer. */
/* item status text */
"Message delivery error" = "消息传递错误";
/* No comment provided by engineer. */
@@ -2176,8 +2161,8 @@
/* No comment provided by engineer. */
"Paste received link" = "粘贴收到的链接";
/* No comment provided by engineer. */
"Paste the link you received into the box below to connect with your contact." = "将您收到的链接粘贴到下面的框中以与您的联系人联系。";
/* placeholder */
"Paste the link you received to connect with your contact." = "将您收到的链接粘贴到下面的框中以与您的联系人联系。";
/* No comment provided by engineer. */
"peer-to-peer" = "点对点";
@@ -2372,7 +2357,7 @@
"Reject" = "拒绝";
/* No comment provided by engineer. */
"Reject contact (sender NOT notified)" = "拒绝联系人(发送者不会被通知)";
"Reject (sender NOT notified)" = "拒绝联系人(发送者不会被通知)";
/* No comment provided by engineer. */
"Reject contact request" = "拒绝联系人请求";
@@ -2929,9 +2914,6 @@
/* No comment provided by engineer. */
"To connect, your contact can scan QR code or use the link in the app." = "您的联系人可以扫描二维码或使用应用程序中的链接来建立连接。";
/* No comment provided by engineer. */
"To find the profile used for an incognito connection, tap the contact or group name on top of the chat." = "要查找用于隐身聊天连接的资料,点击聊天顶部的联系人或群组名。";
/* No comment provided by engineer. */
"To make a new connection" = "建立新连接";
@@ -2977,7 +2959,7 @@
/* No comment provided by engineer. */
"Unable to record voice message" = "无法录制语音消息";
/* No comment provided by engineer. */
/* item status description */
"Unexpected error: %@" = "意外错误: @";
/* No comment provided by engineer. */
@@ -3293,7 +3275,7 @@
"You have to enter passphrase every time the app starts - it is not stored on the device." = "您必须在每次应用程序启动时输入密码——它不存储在设备上。";
/* No comment provided by engineer. */
"You invited your contact" = "您邀请了您的联系人";
"You invited a contact" = "您邀请了您的联系人";
/* No comment provided by engineer. */
"You joined this group" = "您已加入此群组";
@@ -3373,9 +3355,6 @@
/* No comment provided by engineer. */
"Your chat profile will be sent to group members" = "您的聊天资料将被发送给群组成员";
/* No comment provided by engineer. */
"Your chat profile will be sent to your contact" = "您的聊天资料将被发送给您的联系人";
/* No comment provided by engineer. */
"Your chat profiles" = "您的聊天资料";
@@ -3412,9 +3391,6 @@
/* No comment provided by engineer. */
"Your profile is stored on your device and shared only with your contacts.\nSimpleX servers cannot see your profile." = "您的资料存储在您的设备上并仅与您的联系人共享。\nSimpleX 服务器无法看到您的资料。";
/* No comment provided by engineer. */
"Your profile will be sent to the contact that you received this link from" = "您的个人资料将发送给您收到此链接的联系人";
/* No comment provided by engineer. */
"Your profile, contacts and delivered messages are stored on your device." = "您的资料、联系人和发送的消息存储在您的设备上。";
+1 -1
View File
@@ -11,7 +11,7 @@
local.properties
common/src/commonMain/cpp/android/libs/
common/src/commonMain/cpp/desktop/libs/
common/src/commonMain/resources/libs/
desktop/src/jvmMain/resources/libs/
android/build
android/release
common/build
+11 -9
View File
@@ -7,17 +7,14 @@ plugins {
id("org.jetbrains.kotlin.plugin.serialization")
}
repositories {
maven("https://jitpack.io")
}
android {
compileSdkVersion(33)
namespace = "chat.simplex.app"
compileSdk = 33
defaultConfig {
applicationId = "chat.simplex.app"
minSdkVersion(26)
targetSdkVersion(32)
minSdk = 26
targetSdk = 33
// !!!
// skip version code after release to F-Droid, as it uses two version codes
versionCode = (extra["android.version_code"] as String).toInt()
@@ -60,8 +57,6 @@ android {
freeCompilerArgs += "-opt-in=androidx.compose.foundation.ExperimentalFoundationApi"
freeCompilerArgs += "-opt-in=androidx.compose.ui.text.ExperimentalTextApi"
freeCompilerArgs += "-opt-in=androidx.compose.material.ExperimentalMaterialApi"
freeCompilerArgs += "-opt-in=com.google.accompanist.insets.ExperimentalAnimatedInsets"
freeCompilerArgs += "-opt-in=com.google.accompanist.permissions.ExperimentalPermissionsApi"
freeCompilerArgs += "-opt-in=kotlinx.serialization.InternalSerializationApi"
freeCompilerArgs += "-opt-in=kotlinx.serialization.ExperimentalSerializationApi"
}
@@ -124,9 +119,16 @@ dependencies {
//implementation("androidx.compose.ui:ui:${rootProject.extra["compose.version"] as String}")
//implementation("androidx.compose.material:material:$compose_version")
//implementation("androidx.compose.ui:ui-tooling-preview:$compose_version")
implementation("androidx.appcompat:appcompat:1.5.1")
implementation("androidx.lifecycle:lifecycle-runtime-ktx:2.4.1")
implementation("androidx.lifecycle:lifecycle-process:2.4.1")
implementation("androidx.activity:activity-compose:1.5.0")
val work_version = "2.7.1"
implementation("androidx.work:work-runtime-ktx:$work_version")
implementation("androidx.work:work-multiprocess:$work_version")
implementation("com.jakewharton:process-phoenix:2.1.2")
//implementation("androidx.compose.material:material-icons-extended:$compose_version")
//implementation("androidx.compose.ui:ui-util:$compose_version")
@@ -1,7 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="chat.simplex.app">
xmlns:tools="http://schemas.android.com/tools">
<uses-feature android:name="android.hardware.camera" />
@@ -3,8 +3,8 @@ package chat.simplex.app
import android.app.backup.BackupAgentHelper
import android.app.backup.FullBackupDataOutput
import android.content.Context
import chat.simplex.app.model.AppPreferences
import chat.simplex.app.model.AppPreferences.Companion.SHARED_PREFS_PRIVACY_FULL_BACKUP
import chat.simplex.common.model.AppPreferences
import chat.simplex.common.model.AppPreferences.Companion.SHARED_PREFS_PRIVACY_FULL_BACKUP
class BackupAgent: BackupAgentHelper() {
override fun onFullBackup(data: FullBackupDataOutput?) {
@@ -1,84 +1,40 @@
package chat.simplex.app
import android.app.Application
import android.content.Intent
import android.net.Uri
import android.os.*
import android.os.SystemClock.elapsedRealtime
import android.util.Log
import android.view.WindowManager
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.animation.core.*
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import androidx.fragment.app.FragmentActivity
import androidx.lifecycle.*
import chat.simplex.app.MainActivity.Companion.enteredBackground
import chat.simplex.app.model.*
import chat.simplex.app.model.NtfManager
import chat.simplex.app.model.NtfManager.getUserIdFromIntent
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.SplashView
import chat.simplex.app.views.call.ActiveCallView
import chat.simplex.app.views.call.IncomingCallAlertView
import chat.simplex.app.views.chat.ChatView
import chat.simplex.app.views.chatlist.*
import chat.simplex.app.views.database.DatabaseErrorView
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.helpers.DatabaseUtils.ksAppPassword
import chat.simplex.app.views.helpers.DatabaseUtils.ksSelfDestructPassword
import chat.simplex.app.views.localauth.SetAppPasscodeView
import chat.simplex.app.views.newchat.*
import chat.simplex.app.views.onboarding.*
import chat.simplex.app.views.usersettings.LAMode
import chat.simplex.app.views.usersettings.SetDeliveryReceiptsView
import chat.simplex.common.*
import chat.simplex.common.helpers.*
import chat.simplex.common.model.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.chatlist.*
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.onboarding.*
import chat.simplex.common.platform.*
import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.*
import kotlinx.coroutines.flow.distinctUntilChanged
import java.lang.ref.WeakReference
class MainActivity: FragmentActivity() {
companion object {
/**
* We don't want these values to be bound to Activity lifecycle since activities are changed often, for example, when a user
* clicks on new message in notification. In this case savedInstanceState will be null (this prevents restoring the values)
* See [SimplexService.onTaskRemoved] for another part of the logic which nullifies the values when app closed by the user
* */
val userAuthorized = mutableStateOf<Boolean?>(null)
val enteredBackground = mutableStateOf<Long?>(null)
// Remember result and show it after orientation change
private val laFailed = mutableStateOf(false)
fun clearAuthState() {
userAuthorized.value = null
enteredBackground.value = null
}
}
private val vm by viewModels<SimplexViewModel>()
private val destroyedAfterBackPress = mutableStateOf(false)
override fun onCreate(savedInstanceState: Bundle?) {
applyAppLocale(ChatModel.controller.appPrefs.appLanguage)
super.onCreate(savedInstanceState)
SimplexApp.context.mainActivity = WeakReference(this)
// testJson()
val m = vm.chatModel
mainActivity = WeakReference(this)
// When call ended and orientation changes, it re-process old intent, it's unneeded.
// Only needed to be processed on first creation of activity
if (savedInstanceState == null) {
processNotificationIntent(intent, m)
processIntent(intent, m)
processExternalIntent(intent, m)
processNotificationIntent(intent)
processIntent(intent)
processExternalIntent(intent)
}
if (m.controller.appPrefs.privacyProtectScreen.get()) {
if (ChatController.appPrefs.privacyProtectScreen.get()) {
Log.d(TAG, "onCreate: set FLAG_SECURE")
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
@@ -87,17 +43,7 @@ class MainActivity: FragmentActivity() {
}
setContent {
SimpleXTheme {
Surface(color = MaterialTheme.colors.background) {
MainPage(
m,
userAuthorized,
laFailed,
destroyedAfterBackPress,
::runAuthenticate,
::setPerformLA,
showLANotice = { showLANotice(m.controller.appPrefs.laNoticeShown) }
)
}
AppScreen()
}
}
SimplexApp.context.schedulePeriodicServiceRestartWorker()
@@ -106,38 +52,29 @@ class MainActivity: FragmentActivity() {
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
processIntent(intent, vm.chatModel)
processExternalIntent(intent, vm.chatModel)
processIntent(intent)
processExternalIntent(intent)
}
override fun onResume() {
super.onResume()
val enteredBackgroundVal = enteredBackground.value
val delay = vm.chatModel.controller.appPrefs.laLockDelay.get()
if (enteredBackgroundVal == null || elapsedRealtime() - enteredBackgroundVal >= delay * 1000) {
if (userAuthorized.value != false) {
/** [runAuthenticate] will be called in [MainPage] if needed. Making like this prevents double showing of passcode on start */
setAuthState()
} else if (!vm.chatModel.activeCallViewIsVisible.value) {
runAuthenticate()
}
}
AppLock.recheckAuthState()
}
override fun onPause() {
super.onPause()
/**
* When new activity is created after a click on notification, the old one receives onPause before
* recreation but receives onStop after recreation. So using both (onPause and onStop) to prevent
* unwanted multiple auth dialogs from [runAuthenticate]
* */
enteredBackground.value = elapsedRealtime()
* When new activity is created after a click on notification, the old one receives onPause before
* recreation but receives onStop after recreation. So using both (onPause and onStop) to prevent
* unwanted multiple auth dialogs from [runAuthenticate]
* */
AppLock.appWasHidden()
}
override fun onStop() {
super.onStop()
VideoPlayer.stopAll()
enteredBackground.value = elapsedRealtime()
AppLock.appWasHidden()
}
override fun onBackPressed() {
@@ -150,481 +87,52 @@ class MainActivity: FragmentActivity() {
super.onBackPressed()
}
if (!onBackPressedDispatcher.hasEnabledCallbacks() && vm.chatModel.controller.appPrefs.performLA.get()) {
if (!onBackPressedDispatcher.hasEnabledCallbacks() && ChatController.appPrefs.performLA.get()) {
// When pressed Back and there is no one wants to process the back event, clear auth state to force re-auth on launch
clearAuthState()
laFailed.value = true
destroyedAfterBackPress.value = true
AppLock.clearAuthState()
AppLock.laFailed.value = true
AppLock.destroyedAfterBackPress.value = true
}
if (!onBackPressedDispatcher.hasEnabledCallbacks()) {
// Drop shared content
SimplexApp.context.chatModel.sharedContent.value = null
}
}
private fun setAuthState() {
userAuthorized.value = !vm.chatModel.controller.appPrefs.performLA.get()
}
private fun runAuthenticate() {
val m = vm.chatModel
setAuthState()
if (userAuthorized.value == false) {
// To make Main thread free in order to allow to Compose to show blank view that hiding content underneath of it faster on slow devices
CoroutineScope(Dispatchers.Default).launch {
delay(50)
withContext(Dispatchers.Main) {
authenticate(
if (m.controller.appPrefs.laMode.get() == LAMode.SYSTEM)
generalGetString(MR.strings.auth_unlock)
else
generalGetString(MR.strings.la_enter_app_passcode),
if (m.controller.appPrefs.laMode.get() == LAMode.SYSTEM)
generalGetString(MR.strings.auth_log_in_using_credential)
else
generalGetString(MR.strings.auth_unlock),
selfDestruct = true,
completed = { laResult ->
when (laResult) {
LAResult.Success ->
userAuthorized.value = true
is LAResult.Failed -> { /* Can be called multiple times on every failure */ }
is LAResult.Error -> {
laFailed.value = true
if (m.controller.appPrefs.laMode.get() == LAMode.PASSCODE) {
laFailedAlert()
}
}
is LAResult.Unavailable -> {
userAuthorized.value = true
m.performLA.value = false
m.controller.appPrefs.performLA.set(false)
laUnavailableTurningOffAlert()
}
}
}
)
}
}
}
}
private fun showLANotice(laNoticeShown: SharedPreference<Boolean>) {
Log.d(TAG, "showLANotice")
if (!laNoticeShown.get()) {
laNoticeShown.set(true)
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.la_notice_title_simplex_lock),
text = generalGetString(MR.strings.la_notice_to_protect_your_information_turn_on_simplex_lock_you_will_be_prompted_to_complete_authentication_before_this_feature_is_enabled),
confirmText = generalGetString(MR.strings.la_notice_turn_on),
onConfirm = {
withBGApi { // to remove this call, change ordering of onConfirm call in AlertManager
showChooseLAMode(laNoticeShown)
}
}
)
}
}
private fun showChooseLAMode(laNoticeShown: SharedPreference<Boolean>) {
Log.d(TAG, "showLANotice")
laNoticeShown.set(true)
AlertManager.shared.showAlertDialogStacked(
title = generalGetString(MR.strings.la_lock_mode),
text = null,
confirmText = generalGetString(MR.strings.la_lock_mode_passcode),
dismissText = generalGetString(MR.strings.la_lock_mode_system),
onConfirm = {
AlertManager.shared.hideAlert()
setPasscode()
},
onDismiss = {
AlertManager.shared.hideAlert()
initialEnableLA()
}
)
}
private fun initialEnableLA() {
val m = vm.chatModel
val appPrefs = m.controller.appPrefs
m.controller.appPrefs.laMode.set(LAMode.SYSTEM)
authenticate(
generalGetString(MR.strings.auth_enable_simplex_lock),
generalGetString(MR.strings.auth_confirm_credential),
completed = { laResult ->
when (laResult) {
LAResult.Success -> {
m.performLA.value = true
appPrefs.performLA.set(true)
laTurnedOnAlert()
}
is LAResult.Failed -> { /* Can be called multiple times on every failure */ }
is LAResult.Error -> {
m.performLA.value = false
appPrefs.performLA.set(false)
laFailedAlert()
}
is LAResult.Unavailable -> {
m.performLA.value = false
appPrefs.performLA.set(false)
m.showAdvertiseLAUnavailableAlert.value = true
}
}
}
)
}
private fun setPasscode() {
val chatModel = vm.chatModel
val appPrefs = chatModel.controller.appPrefs
ModalManager.shared.showCustomModal { close ->
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
SetAppPasscodeView(
submit = {
chatModel.performLA.value = true
appPrefs.performLA.set(true)
appPrefs.laMode.set(LAMode.PASSCODE)
laTurnedOnAlert()
},
cancel = {
chatModel.performLA.value = false
appPrefs.performLA.set(false)
laPasscodeNotSetAlert()
},
close = close
)
}
}
}
private fun setPerformLA(on: Boolean) {
vm.chatModel.controller.appPrefs.laNoticeShown.set(true)
if (on) {
enableLA()
} else {
disableLA()
}
}
private fun enableLA() {
val m = vm.chatModel
authenticate(
if (m.controller.appPrefs.laMode.get() == LAMode.SYSTEM)
generalGetString(MR.strings.auth_enable_simplex_lock)
else
generalGetString(MR.strings.new_passcode),
if (m.controller.appPrefs.laMode.get() == LAMode.SYSTEM)
generalGetString(MR.strings.auth_confirm_credential)
else
"",
completed = { laResult ->
val prefPerformLA = m.controller.appPrefs.performLA
when (laResult) {
LAResult.Success -> {
m.performLA.value = true
prefPerformLA.set(true)
laTurnedOnAlert()
}
is LAResult.Failed -> { /* Can be called multiple times on every failure */ }
is LAResult.Error -> {
m.performLA.value = false
prefPerformLA.set(false)
laFailedAlert()
}
is LAResult.Unavailable -> {
m.performLA.value = false
prefPerformLA.set(false)
laUnavailableInstructionAlert()
}
}
}
)
}
private fun disableLA() {
val m = vm.chatModel
authenticate(
if (m.controller.appPrefs.laMode.get() == LAMode.SYSTEM)
generalGetString(MR.strings.auth_disable_simplex_lock)
else
generalGetString(MR.strings.la_enter_app_passcode),
if (m.controller.appPrefs.laMode.get() == LAMode.SYSTEM)
generalGetString(MR.strings.auth_confirm_credential)
else
generalGetString(MR.strings.auth_disable_simplex_lock),
completed = { laResult ->
val prefPerformLA = m.controller.appPrefs.performLA
val selfDestructPref = m.controller.appPrefs.selfDestruct
when (laResult) {
LAResult.Success -> {
m.performLA.value = false
prefPerformLA.set(false)
ksAppPassword.remove()
selfDestructPref.set(false)
ksSelfDestructPassword.remove()
}
is LAResult.Failed -> { /* Can be called multiple times on every failure */ }
is LAResult.Error -> {
m.performLA.value = true
prefPerformLA.set(true)
laFailedAlert()
}
is LAResult.Unavailable -> {
m.performLA.value = false
prefPerformLA.set(false)
laUnavailableTurningOffAlert()
}
}
}
)
}
}
class SimplexViewModel(application: Application): AndroidViewModel(application) {
val app = getApplication<SimplexApp>()
val chatModel = app.chatModel
}
@Composable
fun MainPage(
chatModel: ChatModel,
userAuthorized: MutableState<Boolean?>,
laFailed: MutableState<Boolean>,
destroyedAfterBackPress: MutableState<Boolean>,
runAuthenticate: () -> Unit,
setPerformLA: (Boolean) -> Unit,
showLANotice: () -> Unit
) {
var showChatDatabaseError by rememberSaveable {
mutableStateOf(chatModel.chatDbStatus.value != DBMigrationResult.OK && chatModel.chatDbStatus.value != null)
}
LaunchedEffect(chatModel.chatDbStatus.value) {
showChatDatabaseError = chatModel.chatDbStatus.value != DBMigrationResult.OK && chatModel.chatDbStatus.value != null
}
var showAdvertiseLAAlert by remember { mutableStateOf(false) }
LaunchedEffect(showAdvertiseLAAlert) {
if (
!chatModel.controller.appPrefs.laNoticeShown.get()
&& showAdvertiseLAAlert
&& chatModel.onboardingStage.value == OnboardingStage.OnboardingComplete
&& chatModel.chats.isNotEmpty()
&& chatModel.activeCallInvitation.value == null
) {
showLANotice()
}
}
LaunchedEffect(chatModel.showAdvertiseLAUnavailableAlert.value) {
if (chatModel.showAdvertiseLAUnavailableAlert.value) {
laUnavailableInstructionAlert()
}
}
LaunchedEffect(chatModel.clearOverlays.value) {
if (chatModel.clearOverlays.value) {
ModalManager.shared.closeModals()
chatModel.clearOverlays.value = false
}
}
@Composable
fun AuthView() {
Surface(color = MaterialTheme.colors.background) {
Box(
Modifier.fillMaxSize(),
contentAlignment = Alignment.Center
) {
SimpleButton(
stringResource(MR.strings.auth_unlock),
icon = painterResource(MR.images.ic_lock),
click = {
laFailed.value = false
runAuthenticate()
}
)
}
}
}
Box {
val onboarding = chatModel.onboardingStage.value
val userCreated = chatModel.userCreated.value
var showInitializationView by remember { mutableStateOf(false) }
when {
chatModel.chatDbStatus.value == null && showInitializationView -> InitializationView()
showChatDatabaseError -> {
chatModel.chatDbStatus.value?.let {
DatabaseErrorView(chatModel.chatDbStatus, chatModel.controller.appPrefs)
}
}
onboarding == null || userCreated == null -> SplashView()
onboarding == OnboardingStage.OnboardingComplete && userCreated -> {
Box {
showAdvertiseLAAlert = true
BoxWithConstraints {
var currentChatId by rememberSaveable { mutableStateOf(chatModel.chatId.value) }
val offset = remember { Animatable(if (chatModel.chatId.value == null) 0f else maxWidth.value) }
Box(
Modifier
.graphicsLayer {
translationX = -offset.value.dp.toPx()
}
) {
if (chatModel.setDeliveryReceipts.value) {
SetDeliveryReceiptsView(chatModel)
} else {
val stopped = chatModel.chatRunning.value == false
if (chatModel.sharedContent.value == null)
ChatListView(chatModel, setPerformLA, stopped)
else
ShareListView(chatModel, stopped)
}
}
val scope = rememberCoroutineScope()
val onComposed: () -> Unit = {
scope.launch {
offset.animateTo(
if (chatModel.chatId.value == null) 0f else maxWidth.value,
chatListAnimationSpec()
)
if (offset.value == 0f) {
currentChatId = null
}
}
}
LaunchedEffect(Unit) {
launch {
snapshotFlow { chatModel.chatId.value }
.distinctUntilChanged()
.collect {
if (it != null) currentChatId = it
else onComposed()
}
}
}
Box (Modifier.graphicsLayer { translationX = maxWidth.toPx() - offset.value.dp.toPx() }) Box2@ {
currentChatId?.let {
ChatView(it, chatModel, onComposed)
}
}
}
}
}
onboarding == OnboardingStage.Step1_SimpleXInfo -> SimpleXInfo(chatModel, onboarding = true)
onboarding == OnboardingStage.Step2_CreateProfile -> CreateProfile(chatModel) {}
onboarding == OnboardingStage.Step3_CreateSimpleXAddress -> CreateSimpleXAddress(chatModel)
onboarding == OnboardingStage.Step4_SetNotificationsMode -> SetNotificationsMode(chatModel)
}
ModalManager.shared.showInView()
val unauthorized = remember { derivedStateOf { userAuthorized.value != true } }
if (unauthorized.value && !(chatModel.activeCallViewIsVisible.value && chatModel.showCallView.value)) {
LaunchedEffect(Unit) {
// With these constrains when user presses back button while on ChatList, activity destroys and shows auth request
// while the screen moves to a launcher. Detect it and prevent showing the auth
if (!(destroyedAfterBackPress.value && chatModel.controller.appPrefs.laMode.get() == LAMode.SYSTEM)) {
runAuthenticate()
}
}
if (chatModel.controller.appPrefs.performLA.get() && laFailed.value) {
AuthView()
} else {
SplashView()
}
} else if (chatModel.showCallView.value) {
ActiveCallView(chatModel)
}
ModalManager.shared.showPasscodeInView()
val invitation = chatModel.activeCallInvitation.value
if (invitation != null) IncomingCallAlertView(invitation, chatModel)
AlertManager.shared.showInView()
LaunchedEffect(Unit) {
delay(1000)
if (chatModel.chatDbStatus.value == null) {
showInitializationView = true
}
}
}
DisposableEffectOnRotate {
// When using lock delay = 0 and screen rotates, the app will be locked which is not useful.
// Let's prolong the unlocked period to 3 sec for screen rotation to take place
if (chatModel.controller.appPrefs.laLockDelay.get() == 0) {
enteredBackground.value = elapsedRealtime() + 3000
}
}
}
@Composable
private fun InitializationView() {
Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
CircularProgressIndicator(
Modifier
.padding(bottom = DEFAULT_PADDING)
.size(30.dp),
color = MaterialTheme.colors.secondary,
strokeWidth = 2.5.dp
)
Text(stringResource(MR.strings.opening_database))
}
}
}
fun processNotificationIntent(intent: Intent?, chatModel: ChatModel) {
fun processNotificationIntent(intent: Intent?) {
val userId = getUserIdFromIntent(intent)
when (intent?.action) {
NtfManager.OpenChatAction -> {
val chatId = intent.getStringExtra("chatId")
Log.d(TAG, "processNotificationIntent: OpenChatAction $chatId")
if (chatId != null) {
withBGApi {
awaitChatStartedIfNeeded(chatModel)
if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) {
chatModel.controller.changeActiveUser(userId, null)
}
val cInfo = chatModel.getChat(chatId)?.chatInfo
chatModel.clearOverlays.value = true
if (cInfo != null && (cInfo is ChatInfo.Direct || cInfo is ChatInfo.Group)) openChat(cInfo, chatModel)
}
ntfManager.openChatAction(userId, chatId)
}
}
NtfManager.ShowChatsAction -> {
Log.d(TAG, "processNotificationIntent: ShowChatsAction")
withBGApi {
awaitChatStartedIfNeeded(chatModel)
if (userId != null && userId != chatModel.currentUser.value?.userId && chatModel.currentUser.value != null) {
chatModel.controller.changeActiveUser(userId, null)
}
chatModel.chatId.value = null
chatModel.clearOverlays.value = true
}
ntfManager.showChatsAction(userId)
}
NtfManager.AcceptCallAction -> {
val chatId = intent.getStringExtra("chatId")
if (chatId == null || chatId == "") return
Log.d(TAG, "processNotificationIntent: AcceptCallAction $chatId")
chatModel.clearOverlays.value = true
val invitation = chatModel.callInvitations[chatId]
if (invitation == null) {
AlertManager.shared.showAlertMsg(generalGetString(MR.strings.call_already_ended))
} else {
chatModel.callManager.acceptIncomingCall(invitation = invitation)
}
ntfManager.acceptCallAction(chatId)
}
}
}
fun processIntent(intent: Intent?, chatModel: ChatModel) {
fun processIntent(intent: Intent?) {
when (intent?.action) {
"android.intent.action.VIEW" -> {
val uri = intent.data
if (uri != null) connectIfOpenedViaUri(uri, chatModel)
if (uri != null) connectIfOpenedViaUri(uri.toURI(), ChatModel)
}
}
}
fun processExternalIntent(intent: Intent?, chatModel: ChatModel) {
fun processExternalIntent(intent: Intent?) {
when (intent?.action) {
Intent.ACTION_SEND -> {
// Close active chat and show a list of chats
@@ -640,13 +148,13 @@ fun processExternalIntent(intent: Intent?, chatModel: ChatModel) {
isMediaIntent(intent) -> {
val uri = intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri
if (uri != null) {
chatModel.sharedContent.value = SharedContent.Media(intent.getStringExtra(Intent.EXTRA_TEXT) ?: "", listOf(uri))
chatModel.sharedContent.value = SharedContent.Media(intent.getStringExtra(Intent.EXTRA_TEXT) ?: "", listOf(uri.toURI()))
} // All other mime types
}
else -> {
val uri = intent.getParcelableExtra<Parcelable>(Intent.EXTRA_STREAM) as? Uri
if (uri != null) {
chatModel.sharedContent.value = SharedContent.File(intent.getStringExtra(Intent.EXTRA_TEXT) ?: "", uri)
chatModel.sharedContent.value = SharedContent.File(intent.getStringExtra(Intent.EXTRA_TEXT) ?: "", uri.toURI())
}
}
}
@@ -660,7 +168,7 @@ fun processExternalIntent(intent: Intent?, chatModel: ChatModel) {
isMediaIntent(intent) -> {
val uris = intent.getParcelableArrayListExtra<Parcelable>(Intent.EXTRA_STREAM) as? List<Uri>
if (uris != null) {
chatModel.sharedContent.value = SharedContent.Media(intent.getStringExtra(Intent.EXTRA_TEXT) ?: "", uris)
chatModel.sharedContent.value = SharedContent.Media(intent.getStringExtra(Intent.EXTRA_TEXT) ?: "", uris.map { it.toURI() })
} // All other mime types
}
else -> {}
@@ -672,48 +180,6 @@ fun processExternalIntent(intent: Intent?, chatModel: ChatModel) {
fun isMediaIntent(intent: Intent): Boolean =
intent.type?.startsWith("image/") == true || intent.type?.startsWith("video/") == true
fun connectIfOpenedViaUri(uri: Uri, chatModel: ChatModel) {
Log.d(TAG, "connectIfOpenedViaUri: opened via link")
if (chatModel.currentUser.value == null) {
chatModel.appOpenUrl.value = uri
} else {
withUriAction(uri) { linkType ->
val title = when (linkType) {
ConnectionLinkType.CONTACT -> generalGetString(MR.strings.connect_via_contact_link)
ConnectionLinkType.INVITATION -> generalGetString(MR.strings.connect_via_invitation_link)
ConnectionLinkType.GROUP -> generalGetString(MR.strings.connect_via_group_link)
}
AlertManager.shared.showAlertDialog(
title = title,
text = if (linkType == ConnectionLinkType.GROUP)
generalGetString(MR.strings.you_will_join_group)
else
generalGetString(MR.strings.profile_will_be_sent_to_contact_sending_link),
confirmText = generalGetString(MR.strings.connect_via_link_verb),
onConfirm = {
withApi {
Log.d(TAG, "connectIfOpenedViaUri: connecting")
connectViaUri(chatModel, linkType, uri)
}
}
)
}
}
}
suspend fun awaitChatStartedIfNeeded(chatModel: ChatModel, timeout: Long = 30_000) {
// Still decrypting database
if (chatModel.chatRunning.value == null) {
val step = 50L
for (i in 0..(timeout / step)) {
if (chatModel.chatRunning.value == true || chatModel.onboardingStage.value == OnboardingStage.Step1_SimpleXInfo) {
break
}
delay(step)
}
}
}
//fun testJson() {
// val str: String = """
// """.trimIndent()
@@ -1,10 +1,13 @@
package chat.simplex.app.views.helpers
package chat.simplex.app
import android.content.Context
import android.util.Log
import androidx.work.*
import chat.simplex.app.*
import chat.simplex.app.SimplexService.Companion.showPassphraseNotification
import chat.simplex.common.model.ChatController
import chat.simplex.common.views.helpers.DBMigrationResult
import chat.simplex.app.BuildConfig
import kotlinx.coroutines.*
import java.util.Date
import java.util.concurrent.TimeUnit
@@ -55,7 +58,7 @@ class MessagesFetcherWork(
var shouldReschedule = true
try {
withTimeout(durationSeconds * 1000L) {
val chatController = (applicationContext as SimplexApp).chatController
val chatController = ChatController
SimplexService.waitDbMigrationEnds(chatController)
val chatDbStatus = chatController.chatModel.chatDbStatus.value
if (chatDbStatus != DBMigrationResult.OK) {
@@ -1,101 +1,31 @@
package chat.simplex.app
import android.app.Application
import android.net.LocalServerSocket
import android.util.Log
import chat.simplex.common.platform.Log
import androidx.lifecycle.*
import androidx.work.*
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.DefaultTheme
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.onboarding.OnboardingStage
import chat.simplex.app.views.usersettings.NotificationsMode
import chat.simplex.app.model.NtfManager
import chat.simplex.common.helpers.APPLICATION_ID
import chat.simplex.common.helpers.requiresIgnoringBattery
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatController.appPrefs
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.onboarding.OnboardingStage
import chat.simplex.common.platform.*
import chat.simplex.common.views.call.RcvCallInvitation
import com.jakewharton.processphoenix.ProcessPhoenix
import kotlinx.coroutines.*
import kotlinx.serialization.decodeFromString
import java.io.*
import java.lang.ref.WeakReference
import java.util.*
import java.util.concurrent.Semaphore
import java.util.concurrent.TimeUnit
import kotlin.concurrent.thread
const val TAG = "SIMPLEX"
// ghc's rts
external fun initHS()
// android-support
external fun pipeStdOutToSocket(socketName: String) : Int
// SimpleX API
typealias ChatCtrl = Long
external fun chatMigrateInit(dbPath: String, dbKey: String, confirm: String): Array<Any>
external fun chatSendCmd(ctrl: ChatCtrl, msg: String): String
external fun chatRecvMsg(ctrl: ChatCtrl): String
external fun chatRecvMsgWait(ctrl: ChatCtrl, timeout: Int): String
external fun chatParseMarkdown(str: String): String
external fun chatParseServer(str: String): String
external fun chatPasswordHash(pwd: String, salt: String): String
class SimplexApp: Application(), LifecycleEventObserver {
var mainActivity: WeakReference<MainActivity> = WeakReference(null)
val chatModel: ChatModel
get() = chatController.chatModel
val appPreferences: AppPreferences
get() = chatController.appPrefs
val chatController: ChatController = ChatController
var isAppOnForeground: Boolean = false
val defaultLocale: Locale = Locale.getDefault()
suspend fun initChatController(useKey: String? = null, confirmMigrations: MigrationConfirmation? = null, startChat: Boolean = true) {
val dbKey = useKey ?: DatabaseUtils.useDatabaseKey()
val dbAbsolutePathPrefix = getFilesDirectory()
val confirm = confirmMigrations ?: if (appPreferences.confirmDBUpgrades.get()) MigrationConfirmation.Error else MigrationConfirmation.YesUp
val migrated: Array<Any> = chatMigrateInit(dbAbsolutePathPrefix, dbKey, confirm.value)
val res: DBMigrationResult = kotlin.runCatching {
json.decodeFromString<DBMigrationResult>(migrated[0] as String)
}.getOrElse { DBMigrationResult.Unknown(migrated[0] as String) }
val ctrl = if (res is DBMigrationResult.OK) {
migrated[1] as Long
} else null
chatController.ctrl = ctrl
chatModel.chatDbEncrypted.value = dbKey != ""
chatModel.chatDbStatus.value = res
if (res != DBMigrationResult.OK) {
Log.d(TAG, "Unable to migrate successfully: $res")
} else if (startChat) {
// If we migrated successfully means previous re-encryption process on database level finished successfully too
if (appPreferences.encryptionStartedAt.get() != null) appPreferences.encryptionStartedAt.set(null)
val user = chatController.apiGetActiveUser()
if (user == null) {
chatModel.controller.appPrefs.onboardingStage.set(OnboardingStage.Step1_SimpleXInfo)
chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.set(true)
chatModel.onboardingStage.value = OnboardingStage.Step1_SimpleXInfo
chatModel.currentUser.value = null
chatModel.users.clear()
} else {
val savedOnboardingStage = appPreferences.onboardingStage.get()
chatModel.onboardingStage.value = if (listOf(OnboardingStage.Step1_SimpleXInfo, OnboardingStage.Step2_CreateProfile).contains(savedOnboardingStage) && chatModel.users.size == 1) {
OnboardingStage.Step3_CreateSimpleXAddress
} else {
savedOnboardingStage
}
if (chatModel.onboardingStage.value == OnboardingStage.OnboardingComplete && !chatModel.controller.appPrefs.privacyDeliveryReceiptsSet.get()) {
chatModel.setDeliveryReceipts.value = true
}
chatController.startChat(user)
// Prevents from showing "Enable notifications" alert when onboarding wasn't complete yet
if (chatModel.onboardingStage.value == OnboardingStage.OnboardingComplete) {
SimplexService.showBackgroundServiceNoticeIfNeeded()
if (appPreferences.notificationsMode.get() == NotificationsMode.SERVICE.name)
SimplexService.start()
}
}
}
}
override fun onCreate() {
super.onCreate()
@@ -103,7 +33,11 @@ class SimplexApp: Application(), LifecycleEventObserver {
return;
}
context = this
context.getDir("temp", MODE_PRIVATE).deleteRecursively()
initHaskell()
initMultiplatform()
tmpDir.deleteRecursively()
tmpDir.mkdir()
withBGApi {
initChatController()
runMigrations()
@@ -147,7 +81,7 @@ class SimplexApp: Application(), LifecycleEventObserver {
* */
if (chatModel.chatRunning.value != false &&
chatModel.onboardingStage.value == OnboardingStage.OnboardingComplete &&
appPreferences.notificationsMode.get() == NotificationsMode.SERVICE.name
appPrefs.notificationsMode.get() == NotificationsMode.SERVICE
) {
SimplexService.start()
}
@@ -158,13 +92,13 @@ class SimplexApp: Application(), LifecycleEventObserver {
}
fun allowToStartServiceAfterAppExit() = with(chatModel.controller) {
appPrefs.notificationsMode.get() == NotificationsMode.SERVICE.name &&
(!NotificationsMode.SERVICE.requiresIgnoringBattery || SimplexService.isIgnoringBatteryOptimizations())
appPrefs.notificationsMode.get() == NotificationsMode.SERVICE &&
(!NotificationsMode.SERVICE.requiresIgnoringBattery || SimplexService.isBackgroundAllowed())
}
private fun allowToStartPeriodically() = with(chatModel.controller) {
appPrefs.notificationsMode.get() == NotificationsMode.PERIODIC.name &&
(!NotificationsMode.PERIODIC.requiresIgnoringBattery || SimplexService.isIgnoringBatteryOptimizations())
appPrefs.notificationsMode.get() == NotificationsMode.PERIODIC &&
(!NotificationsMode.PERIODIC.requiresIgnoringBattery || SimplexService.isBackgroundAllowed())
}
/*
@@ -198,75 +132,86 @@ class SimplexApp: Application(), LifecycleEventObserver {
MessagesFetcherWorker.scheduleWork()
}
private fun runMigrations() {
val lastMigration = chatModel.controller.appPrefs.lastMigratedVersionCode
if (lastMigration.get() < BuildConfig.VERSION_CODE) {
while (true) {
if (lastMigration.get() < 117) {
if (chatModel.controller.appPrefs.currentTheme.get() == DefaultTheme.DARK.name) {
chatModel.controller.appPrefs.currentTheme.set(DefaultTheme.SIMPLEX.name)
}
lastMigration.set(117)
} else {
lastMigration.set(BuildConfig.VERSION_CODE)
break
}
}
}
}
companion object {
lateinit var context: SimplexApp private set
}
init {
val socketName = BuildConfig.APPLICATION_ID + ".local.socket.address.listen.native.cmd2"
val s = Semaphore(0)
thread(name="stdout/stderr pipe") {
Log.d(TAG, "starting server")
var server: LocalServerSocket? = null
for (i in 0..100) {
try {
server = LocalServerSocket(socketName + i)
break
} catch (e: IOException) {
Log.e(TAG, e.stackTraceToString())
}
private fun initMultiplatform() {
androidAppContext = this
APPLICATION_ID = BuildConfig.APPLICATION_ID
ntfManager = object : chat.simplex.common.platform.NtfManager() {
override fun notifyCallInvitation(invitation: RcvCallInvitation) = NtfManager.notifyCallInvitation(invitation)
override fun hasNotificationsForChat(chatId: String): Boolean = NtfManager.hasNotificationsForChat(chatId)
override fun cancelNotificationsForChat(chatId: String) = NtfManager.cancelNotificationsForChat(chatId)
override fun displayNotification(user: User, chatId: String, displayName: String, msgText: String, image: String?, actions: List<Pair<NotificationAction, () -> Unit>>) = NtfManager.displayNotification(user, chatId, displayName, msgText, image, actions.map { it.first })
override fun androidCreateNtfChannelsMaybeShowAlert() = NtfManager.createNtfChannelsMaybeShowAlert()
override fun cancelCallNotification() = NtfManager.cancelCallNotification()
override fun cancelAllNotifications() = NtfManager.cancelAllNotifications()
}
platform = object : PlatformInterface {
override suspend fun androidServiceStart() {
SimplexService.start()
}
override fun androidServiceSafeStop() {
SimplexService.safeStopService()
}
override fun androidNotificationsModeChanged(mode: NotificationsMode) {
if (mode.requiresIgnoringBattery && !SimplexService.isBackgroundAllowed()) {
appPrefs.backgroundServiceNoticeShown.set(false)
}
if (server == null) {
throw Error("Unable to setup local server socket. Contact developers")
SimplexService.StartReceiver.toggleReceiver(mode == NotificationsMode.SERVICE)
CoroutineScope(Dispatchers.Default).launch {
if (mode == NotificationsMode.SERVICE)
SimplexService.start()
else
SimplexService.safeStopService()
}
Log.d(TAG, "started server")
s.release()
val receiver = server.accept()
Log.d(TAG, "started receiver")
val logbuffer = FifoQueue<String>(500)
if (receiver != null) {
val inStream = receiver.inputStream
val inStreamReader = InputStreamReader(inStream)
val input = BufferedReader(inStreamReader)
Log.d(TAG, "starting receiver loop")
while (true) {
val line = input.readLine() ?: break
Log.w("$TAG (stdout/stderr)", line)
logbuffer.add(line)
}
Log.w(TAG, "exited receiver loop")
if (mode != NotificationsMode.PERIODIC) {
MessagesFetcherWorker.cancelAll()
}
SimplexService.showBackgroundServiceNoticeIfNeeded(showOffAlert = false)
}
override fun androidChatStartedAfterBeingOff() {
SimplexService.cancelPassphraseNotification()
when (appPrefs.notificationsMode.get()) {
NotificationsMode.SERVICE -> CoroutineScope(Dispatchers.Default).launch { platform.androidServiceStart() }
NotificationsMode.PERIODIC -> SimplexApp.context.schedulePeriodicWakeUp()
NotificationsMode.OFF -> {}
}
}
System.loadLibrary("app-lib")
override fun androidChatStopped() {
SimplexService.safeStopService()
MessagesFetcherWorker.cancelAll()
}
s.acquire()
pipeStdOutToSocket(socketName)
override fun androidChatInitializedAndStarted() {
// Prevents from showing "Enable notifications" alert when onboarding wasn't complete yet
if (chatModel.onboardingStage.value == OnboardingStage.OnboardingComplete) {
SimplexService.showBackgroundServiceNoticeIfNeeded()
if (appPrefs.notificationsMode.get() == NotificationsMode.SERVICE)
withBGApi {
platform.androidServiceStart()
}
}
}
initHS()
override fun androidIsBackgroundCallAllowed(): Boolean = !SimplexService.isBackgroundRestricted()
override suspend fun androidAskToAllowBackgroundCalls(): Boolean {
if (SimplexService.isBackgroundRestricted()) {
val userChoice: CompletableDeferred<Boolean> = CompletableDeferred()
SimplexService.showBGRestrictedInCall {
userChoice.complete(it)
}
return userChoice.await()
}
return true
}
}
}
}
class FifoQueue<E>(private var capacity: Int) : LinkedList<E>() {
override fun add(element: E): Boolean {
if(size > capacity) removeFirst()
return super.add(element)
}
}
@@ -7,23 +7,26 @@ import android.content.pm.PackageManager
import android.net.Uri
import android.os.*
import android.provider.Settings
import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import chat.simplex.common.platform.Log
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import androidx.work.*
import chat.simplex.app.model.ChatController
import chat.simplex.app.model.ChatModel
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.usersettings.NotificationsMode
import chat.simplex.common.AppLock
import chat.simplex.common.helpers.requiresIgnoringBattery
import chat.simplex.common.model.ChatController
import chat.simplex.common.model.NotificationsMode
import chat.simplex.common.platform.androidAppContext
import chat.simplex.common.views.helpers.*
import kotlinx.coroutines.*
import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.*
// based on:
// https://robertohuertas.com/2019/06/29/android_foreground_services/
@@ -47,6 +50,7 @@ class SimplexService: Service() {
} else {
Log.d(TAG, "null intent. Probably restarted by the system.")
}
startForeground(SIMPLEX_SERVICE_ID, serviceNotification)
return START_STICKY // to restart if killed
}
@@ -97,7 +101,7 @@ class SimplexService: Service() {
val self = this
isStartingService = true
withApi {
val chatController = (application as SimplexApp).chatController
val chatController = ChatController
waitDbMigrationEnds(chatController)
try {
Log.w(TAG, "Starting foreground service")
@@ -105,7 +109,7 @@ class SimplexService: Service() {
if (chatDbStatus != DBMigrationResult.OK) {
Log.w(chat.simplex.app.TAG, "SimplexService: problem with the database: $chatDbStatus")
showPassphraseNotification(chatDbStatus)
safeStopService(self)
safeStopService()
return@withApi
}
saveServiceState(self, ServiceState.STARTED)
@@ -167,7 +171,7 @@ class SimplexService: Service() {
// re-schedules the task when "Clear recent apps" is pressed
override fun onTaskRemoved(rootIntent: Intent) {
// Just to make sure that after restart of the app the user will need to re-authenticate
MainActivity.clearAuthState()
AppLock.clearAuthState()
// If notification service isn't enabled or battery optimization isn't disabled, we shouldn't restart the service
if (!SimplexApp.context.allowToStartServiceAfterAppExit()) {
@@ -265,9 +269,9 @@ class SimplexService: Service() {
* If there is a need to stop the service, use this function only. It makes sure that the service will be stopped without an
* exception related to foreground services lifecycle
* */
fun safeStopService(context: Context) {
fun safeStopService() {
if (isServiceStarted) {
context.stopService(Intent(context, SimplexService::class.java))
androidAppContext.stopService(Intent(androidAppContext, SimplexService::class.java))
} else {
stopAfterStart = true
}
@@ -276,9 +280,9 @@ class SimplexService: Service() {
private suspend fun serviceAction(action: Action) {
Log.d(TAG, "SimplexService serviceAction: ${action.name}")
withContext(Dispatchers.IO) {
Intent(SimplexApp.context, SimplexService::class.java).also {
Intent(androidAppContext, SimplexService::class.java).also {
it.action = action.name
ContextCompat.startForegroundService(SimplexApp.context, it)
ContextCompat.startForegroundService(androidAppContext, it)
}
}
}
@@ -350,37 +354,37 @@ class SimplexService: Service() {
private fun getPreferences(context: Context): SharedPreferences = context.getSharedPreferences(SHARED_PREFS_ID, Context.MODE_PRIVATE)
fun showBackgroundServiceNoticeIfNeeded() {
fun showBackgroundServiceNoticeIfNeeded(showOffAlert: Boolean = true) {
val appPrefs = ChatController.appPrefs
val mode = NotificationsMode.valueOf(appPrefs.notificationsMode.get()!!)
val mode = appPrefs.notificationsMode.get()
Log.d(TAG, "showBackgroundServiceNoticeIfNeeded")
// Nothing to do if mode is OFF. Can be selected on on-boarding stage
if (mode == NotificationsMode.OFF) return
if (!appPrefs.backgroundServiceNoticeShown.get()) {
// the branch for the new users who have never seen service notice
if (!mode.requiresIgnoringBattery || isIgnoringBatteryOptimizations()) {
if (!mode.requiresIgnoringBattery || isBackgroundAllowed()) {
showBGServiceNotice(mode)
} else {
showBGServiceNoticeIgnoreOptimization(mode)
} else if (isBackgroundRestricted()) {
showBGServiceNoticeSystemRestricted(mode, showOffAlert)
} else if (!isIgnoringBatteryOptimizations()) {
showBGServiceNoticeIgnoreOptimization(mode, showOffAlert)
}
// set both flags, so that if the user doesn't allow ignoring optimizations, the service will be disabled without additional notice
appPrefs.backgroundServiceNoticeShown.set(true)
appPrefs.backgroundServiceBatteryNoticeShown.set(true)
} else if (mode.requiresIgnoringBattery && isBackgroundRestricted()) {
// the branch for users who have app installed, and have seen the service notice,
// but the service is running AND system background restriction is on OR the battery optimization for the app is in RESTRICTED state
showBGServiceNoticeSystemRestricted(mode, showOffAlert)
if (!appPrefs.backgroundServiceBatteryNoticeShown.get()) {
appPrefs.backgroundServiceBatteryNoticeShown.set(true)
}
} else if (mode.requiresIgnoringBattery && !isIgnoringBatteryOptimizations()) {
// the branch for users who have app installed, and have seen the service notice,
// but the battery optimization for the app is on (Android 12) AND the service is running
if (appPrefs.backgroundServiceBatteryNoticeShown.get()) {
// users have been presented with battery notice before - they did not allow ignoring optimizations -> disable service
showDisablingServiceNotice(mode)
appPrefs.notificationsMode.set(NotificationsMode.OFF.name)
ChatModel.notificationsMode.value = NotificationsMode.OFF
SimplexService.StartReceiver.toggleReceiver(false)
MessagesFetcherWorker.cancelAll()
SimplexService.safeStopService(SimplexApp.context)
} else {
// show battery optimization notice
showBGServiceNoticeIgnoreOptimization(mode)
// but the battery optimization for the app is in OPTIMIZED state (Android 12+) AND the service is running
showBGServiceNoticeIgnoreOptimization(mode, showOffAlert)
if (!appPrefs.backgroundServiceBatteryNoticeShown.get()) {
appPrefs.backgroundServiceBatteryNoticeShown.set(true)
}
} else {
@@ -423,13 +427,17 @@ class SimplexService: Service() {
)
}
private fun showBGServiceNoticeIgnoreOptimization(mode: NotificationsMode) = AlertManager.shared.showAlert {
private fun showBGServiceNoticeIgnoreOptimization(mode: NotificationsMode, showOffAlert: Boolean) = AlertManager.shared.showAlert {
val ignoreOptimization = {
AlertManager.shared.hideAlert()
askAboutIgnoringBatteryOptimization()
}
val disableNotifications = {
AlertManager.shared.hideAlert()
disableNotifications(mode, showOffAlert)
}
AlertDialog(
onDismissRequest = ignoreOptimization,
onDismissRequest = disableNotifications,
title = {
Row {
Icon(
@@ -452,12 +460,98 @@ class SimplexService: Service() {
Text(annotatedStringResource(MR.strings.turn_off_battery_optimization))
}
},
dismissButton = {
TextButton(onClick = disableNotifications) { Text(stringResource(MR.strings.disable_notifications_button), color = MaterialTheme.colors.error) }
},
confirmButton = {
TextButton(onClick = ignoreOptimization) { Text(stringResource(MR.strings.ok)) }
TextButton(onClick = ignoreOptimization) { Text(stringResource(MR.strings.turn_off_battery_optimization_button)) }
}
)
}
private fun showBGServiceNoticeSystemRestricted(mode: NotificationsMode, showOffAlert: Boolean) = AlertManager.shared.showAlert {
val unrestrict = {
AlertManager.shared.hideAlert()
askToUnrestrictBackground()
}
val disableNotifications = {
AlertManager.shared.hideAlert()
disableNotifications(mode, showOffAlert)
}
AlertDialog(
onDismissRequest = disableNotifications,
title = {
Row {
Icon(
painterResource(MR.images.ic_bolt),
contentDescription =
if (mode == NotificationsMode.SERVICE) stringResource(MR.strings.icon_descr_instant_notifications) else stringResource(MR.strings.periodic_notifications),
)
Text(
if (mode == NotificationsMode.SERVICE) stringResource(MR.strings.service_notifications) else stringResource(MR.strings.periodic_notifications),
fontWeight = FontWeight.Bold
)
}
},
text = {
Column {
Text(
annotatedStringResource(MR.strings.system_restricted_background_desc),
Modifier.padding(bottom = 8.dp)
)
Text(annotatedStringResource(MR.strings.system_restricted_background_warn))
}
},
dismissButton = {
TextButton(onClick = disableNotifications) { Text(stringResource(MR.strings.disable_notifications_button), color = MaterialTheme.colors.error) }
},
confirmButton = {
TextButton(onClick = unrestrict) { Text(stringResource(MR.strings.turn_off_system_restriction_button)) }
}
)
}
fun showBGRestrictedInCall(onDismiss: (allowedCall: Boolean) -> Unit) = AlertManager.shared.showAlert {
val unrestrict = {
askToUnrestrictBackground()
}
AlertDialog(
onDismissRequest = AlertManager.shared::hideAlert,
title = {
Text(
stringResource(MR.strings.system_restricted_background_in_call_title),
fontWeight = FontWeight.Bold
)
},
text = {
Column {
Text(
annotatedStringResource(MR.strings.system_restricted_background_in_call_desc),
Modifier.padding(bottom = 8.dp)
)
Text(annotatedStringResource(MR.strings.system_restricted_background_in_call_warn))
}
},
confirmButton = {
TextButton(onClick = unrestrict) { Text(stringResource(MR.strings.turn_off_system_restriction_button)) }
}
)
val scope = rememberCoroutineScope()
DisposableEffect(Unit) {
scope.launch {
repeat(10000) {
delay(200)
if (!isBackgroundRestricted()) {
AlertManager.shared.hideAlert()
}
}
}
onDispose {
onDismiss(!isBackgroundRestricted())
}
}
}
private fun showDisablingServiceNotice(mode: NotificationsMode) = AlertManager.shared.showAlert {
AlertDialog(
onDismissRequest = AlertManager.shared::hideAlert,
@@ -488,20 +582,55 @@ class SimplexService: Service() {
)
}
fun isBackgroundAllowed(): Boolean = isIgnoringBatteryOptimizations() && !isBackgroundRestricted()
fun isIgnoringBatteryOptimizations(): Boolean {
val powerManager = SimplexApp.context.getSystemService(Application.POWER_SERVICE) as PowerManager
return powerManager.isIgnoringBatteryOptimizations(SimplexApp.context.packageName)
val powerManager = androidAppContext.getSystemService(Application.POWER_SERVICE) as PowerManager
return powerManager.isIgnoringBatteryOptimizations(androidAppContext.packageName)
}
fun isBackgroundRestricted(): Boolean {
return if (Build.VERSION.SDK_INT >= 28) {
val activityService = androidAppContext.getSystemService(ACTIVITY_SERVICE) as ActivityManager
activityService.isBackgroundRestricted
} else {
false
}
}
private fun askAboutIgnoringBatteryOptimization() {
Intent().apply {
@SuppressLint("BatteryLife")
action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
data = Uri.parse("package:${SimplexApp.context.packageName}")
data = Uri.parse("package:${androidAppContext.packageName}")
// This flag is needed when you start a new activity from non-Activity context
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
SimplexApp.context.startActivity(this)
androidAppContext.startActivity(this)
}
}
private fun askToUnrestrictBackground() {
Intent().apply {
action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
data = Uri.parse("package:${androidAppContext.packageName}")
// This flag is needed when you start a new activity from non-Activity context
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
androidAppContext.startActivity(this)
} catch (e: ActivityNotFoundException) {
Log.e(TAG, e.stackTraceToString())
}
}
}
private fun disableNotifications(mode: NotificationsMode, showOffAlert: Boolean) {
if (showOffAlert) {
showDisablingServiceNotice(mode)
}
ChatController.appPrefs.notificationsMode.set(NotificationsMode.OFF)
StartReceiver.toggleReceiver(false)
MessagesFetcherWorker.cancelAll()
safeStopService()
}
}
}
@@ -1,6 +1,5 @@
package chat.simplex.app.model
import android.Manifest
import android.app.*
import android.app.TaskStackBuilder
import android.content.*
@@ -9,16 +8,20 @@ import android.graphics.BitmapFactory
import android.hardware.display.DisplayManager
import android.media.AudioAttributes
import android.net.Uri
import android.util.Log
import android.view.Display
import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.core.app.*
import chat.simplex.app.*
import chat.simplex.app.views.call.*
import chat.simplex.app.views.chatlist.acceptContactRequest
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.usersettings.NotificationPreviewMode
import chat.simplex.res.MR
import chat.simplex.app.TAG
import chat.simplex.app.views.call.IncomingCallActivity
import chat.simplex.app.views.call.getKeyguardManager
import chat.simplex.common.views.helpers.*
import chat.simplex.common.model.*
import chat.simplex.common.platform.*
import chat.simplex.common.views.call.CallMediaType
import chat.simplex.common.views.call.RcvCallInvitation
import kotlinx.datetime.Clock
import chat.simplex.res.MR
object NtfManager {
const val MessageChannel: String = "chat.simplex.app.MESSAGE_NOTIFICATION"
@@ -33,7 +36,7 @@ object NtfManager {
const val CallNotificationId: Int = -1
private const val UserIdKey: String = "userId"
private const val ChatIdKey: String = "chatId"
private val appPreferences: AppPreferences by lazy { ChatController.appPrefs }
private val appPreferences: AppPreferences = ChatController.appPrefs
private val context: Context
get() = SimplexApp.context
@@ -42,7 +45,7 @@ object NtfManager {
return if (userId == -1L || userId == null) null else userId
}
private val manager: NotificationManager = SimplexApp.context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private val manager: NotificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
private var prevNtfTime = mutableMapOf<String, Long>()
private val msgNtfTimeoutMs = 30000L
@@ -50,10 +53,6 @@ object NtfManager {
if (manager.areNotificationsEnabled()) createNtfChannelsMaybeShowAlert()
}
enum class NotificationAction {
ACCEPT_CONTACT_REQUEST
}
private fun callNotificationChannel(channelId: String, channelName: String): NotificationChannel {
val callChannel = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_HIGH)
val attrs = AudioAttributes.Builder()
@@ -82,31 +81,6 @@ object NtfManager {
}
}
fun notifyContactRequestReceived(user: User, cInfo: ChatInfo.ContactRequest) {
displayNotification(
user = user,
chatId = cInfo.id,
displayName = cInfo.displayName,
msgText = generalGetString(MR.strings.notification_new_contact_request),
image = cInfo.image,
listOf(NotificationAction.ACCEPT_CONTACT_REQUEST)
)
}
fun notifyContactConnected(user: User, contact: Contact) {
displayNotification(
user = user,
chatId = contact.id,
displayName = contact.displayName,
msgText = generalGetString(MR.strings.notification_contact_connected)
)
}
fun notifyMessageReceived(user: User, cInfo: ChatInfo, cItem: ChatItem) {
if (!cInfo.ntfsEnabled) return
displayNotification(user = user, chatId = cInfo.id, displayName = cInfo.displayName, msgText = hideSecrets(cItem))
}
fun displayNotification(user: User, chatId: String, displayName: String, msgText: String, image: String? = null, actions: List<NotificationAction> = emptyList()) {
if (!user.showNotifications) return
Log.d(TAG, "notifyMessageReceived $chatId")
@@ -119,7 +93,7 @@ object NtfManager {
val largeIcon = when {
actions.isEmpty() -> null
image == null || previewMode == NotificationPreviewMode.HIDDEN.name -> BitmapFactory.decodeResource(context.resources, R.drawable.icon)
else -> base64ToBitmap(image)
else -> base64ToBitmap(image).asAndroidBitmap()
}
val builder = NotificationCompat.Builder(context, MessageChannel)
.setContentTitle(title)
@@ -144,6 +118,7 @@ object NtfManager {
val actionPendingIntent: PendingIntent = PendingIntent.getBroadcast(SimplexApp.context, 0, actionIntent, flags)
val actionButton = when (action) {
NotificationAction.ACCEPT_CONTACT_REQUEST -> generalGetString(MR.strings.accept)
NotificationAction.ACCEPT_CONTACT_REQUEST_INCOGNITO -> generalGetString(MR.strings.accept_contact_incognito_button)
}
builder.addAction(0, actionButton, actionPendingIntent)
}
@@ -158,7 +133,7 @@ object NtfManager {
with(NotificationManagerCompat.from(context)) {
// using cInfo.id only shows one notification per chat and updates it when the message arrives
if (ActivityCompat.checkSelfPermission(SimplexApp.context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(SimplexApp.context, android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notify(chatId.hashCode(), builder.build())
notify(0, summary)
}
@@ -172,9 +147,9 @@ object NtfManager {
"notifyCallInvitation pre-requests: " +
"keyguard locked ${keyguardManager.isKeyguardLocked}, " +
"callOnLockScreen ${appPreferences.callOnLockScreen.get()}, " +
"onForeground ${SimplexApp.context.isAppOnForeground}"
"onForeground ${isAppOnForeground}"
)
if (SimplexApp.context.isAppOnForeground) return
if (isAppOnForeground) return
val contactId = invitation.contact.id
Log.d(TAG, "notifyCallInvitation $contactId")
val image = invitation.contact.image
@@ -212,7 +187,7 @@ object NtfManager {
val largeIcon = if (image == null || previewMode == NotificationPreviewMode.HIDDEN.name)
BitmapFactory.decodeResource(context.resources, R.drawable.icon)
else
base64ToBitmap(image)
base64ToBitmap(image).asAndroidBitmap()
ntfBuilder = ntfBuilder
.setContentTitle(title)
@@ -227,7 +202,7 @@ object NtfManager {
// This makes notification sound and vibration repeat endlessly
notification.flags = notification.flags or NotificationCompat.FLAG_INSISTENT
with(NotificationManagerCompat.from(context)) {
if (ActivityCompat.checkSelfPermission(SimplexApp.context, Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.checkSelfPermission(SimplexApp.context, android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
notify(CallNotificationId, notification)
}
}
@@ -243,19 +218,6 @@ object NtfManager {
fun hasNotificationsForChat(chatId: String): Boolean = manager.activeNotifications.any { it.id == chatId.hashCode() }
private fun hideSecrets(cItem: ChatItem): String {
val md = cItem.formattedText
return if (md != null) {
var res = ""
for (ft in md) {
res += if (ft.format is Format.Secret) "..." else ft.text
}
res
} else {
cItem.text
}
}
private fun chatPendingIntent(intentAction: String, userId: Long?, chatId: String? = null, broadcast: Boolean = false): PendingIntent {
Log.d(TAG, "chatPendingIntent for $intentAction")
val uniqueInt = (System.currentTimeMillis() and 0xfffffff).toInt()
@@ -299,18 +261,8 @@ object NtfManager {
val chatId = intent?.getStringExtra(ChatIdKey) ?: return
val m = SimplexApp.context.chatModel
when (intent.action) {
NotificationAction.ACCEPT_CONTACT_REQUEST.name -> {
val isCurrentUser = m.currentUser.value?.userId == userId
val cInfo: ChatInfo.ContactRequest? = if (isCurrentUser) {
(m.getChat(chatId)?.chatInfo as? ChatInfo.ContactRequest) ?: return
} else {
null
}
val apiId = chatId.replace("<@", "").toLongOrNull() ?: return
acceptContactRequest(apiId, cInfo, isCurrentUser, m)
cancelNotificationsForChat(chatId)
}
NotificationAction.ACCEPT_CONTACT_REQUEST.name -> ntfManager.acceptContactRequestAction(userId, incognito = false, chatId)
NotificationAction.ACCEPT_CONTACT_REQUEST_INCOGNITO.name -> ntfManager.acceptContactRequestAction(userId, incognito = true, chatId)
RejectCallAction -> {
val invitation = m.callInvitations[chatId]
if (invitation != null) {
@@ -4,16 +4,14 @@ import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.content.res.Configuration
import android.os.Build
import android.os.Bundle
import android.util.Log
import chat.simplex.common.platform.Log
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.viewModels
import androidx.compose.desktop.ui.tooling.preview.Preview
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.*
@@ -24,27 +22,27 @@ import androidx.compose.ui.draw.scale
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.platform.LocalContext
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.app.*
import chat.simplex.app.R
import chat.simplex.app.model.*
import chat.simplex.common.model.*
import chat.simplex.app.model.NtfManager.OpenChatAction
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.ProfileImage
import chat.simplex.common.platform.ntfManager
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.call.*
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.stringResource
import kotlinx.datetime.Clock
class IncomingCallActivity: ComponentActivity() {
private val vm by viewModels<SimplexViewModel>()
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContent { IncomingCallActivityView(vm.chatModel) }
setContent { IncomingCallActivityView(ChatModel) }
unlockForIncomingCall()
}
@@ -103,7 +101,7 @@ fun IncomingCallActivityView(m: ChatModel) {
) {
if (showCallView) {
Box {
ActiveCallView(m)
ActiveCallView()
if (invitation != null) IncomingCallAlertView(invitation, m)
}
} else if (invitation != null) {
@@ -121,7 +119,7 @@ fun IncomingCallLockScreenAlert(invitation: RcvCallInvitation, chatModel: ChatMo
DisposableEffect(Unit) {
onDispose {
// Cancel notification whatever happens next since otherwise sound from notification and from inside the app can co-exist
chatModel.controller.ntfManager.cancelCallNotification()
ntfManager.cancelCallNotification()
}
}
IncomingCallLockScreenAlertLayout(
@@ -131,7 +129,7 @@ fun IncomingCallLockScreenAlert(invitation: RcvCallInvitation, chatModel: ChatMo
rejectCall = { cm.endCall(invitation = invitation) },
ignoreCall = {
chatModel.activeCallInvitation.value = null
chatModel.controller.ntfManager.cancelCallNotification()
ntfManager.cancelCallNotification()
},
acceptCall = { cm.acceptIncomingCall(invitation = invitation) },
openApp = {
@@ -171,18 +169,18 @@ fun IncomingCallLockScreenAlertLayout(
Text(invitation.contact.chatViewName, style = MaterialTheme.typography.h2)
Spacer(Modifier.fillMaxHeight().weight(1f))
Row {
LockScreenCallButton(stringResource(MR.strings.reject), painterResource(MR.images.ic_call_end_filled), Color.Red, rejectCall)
LockScreenCallButton(stringResource(MR.strings.reject), painterResource(R.drawable.ic_call_end_filled), Color.Red, rejectCall)
Spacer(Modifier.size(48.dp))
LockScreenCallButton(stringResource(MR.strings.ignore), painterResource(MR.images.ic_close), MaterialTheme.colors.primary, ignoreCall)
LockScreenCallButton(stringResource(MR.strings.ignore), painterResource(R.drawable.ic_close), MaterialTheme.colors.primary, ignoreCall)
Spacer(Modifier.size(48.dp))
LockScreenCallButton(stringResource(MR.strings.accept), painterResource(MR.images.ic_check_filled), SimplexGreen, acceptCall)
LockScreenCallButton(stringResource(MR.strings.accept), painterResource(R.drawable.ic_check_filled), SimplexGreen, acceptCall)
}
} else if (callOnLockScreen == CallOnLockScreen.SHOW) {
SimpleXLogo()
Text(stringResource(MR.strings.open_simplex_chat_to_accept_call), textAlign = TextAlign.Center, lineHeight = 22.sp)
Text(stringResource(MR.strings.allow_accepting_calls_from_lock_screen), textAlign = TextAlign.Center, style = MaterialTheme.typography.body2, lineHeight = 22.sp)
Spacer(Modifier.fillMaxHeight().weight(1f))
SimpleButton(text = stringResource(MR.strings.open_verb), icon = painterResource(MR.images.ic_check_filled), click = openApp)
SimpleButton(text = stringResource(MR.strings.open_verb), icon = painterResource(R.drawable.ic_check_filled), click = openApp)
}
}
}
@@ -190,7 +188,7 @@ fun IncomingCallLockScreenAlertLayout(
@Composable
private fun SimpleXLogo() {
Image(
painter = painterResource(if (isInDarkTheme()) MR.images.logo_light else MR.images.logo),
painter = painterResource(if (isInDarkTheme()) R.drawable.logo_light else R.drawable.logo),
contentDescription = stringResource(MR.strings.image_descr_simplex_logo),
modifier = Modifier
.padding(vertical = DEFAULT_PADDING)
@@ -219,10 +217,10 @@ private fun LockScreenCallButton(text: String, icon: Painter, color: Color, acti
}
}
@Preview(
@Preview/*(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true
)
)*/
@Composable
fun PreviewIncomingCallLockScreenAlert() {
SimpleXTheme(true) {
@@ -1,62 +0,0 @@
package chat.simplex.app.views.helpers
import androidx.compose.foundation.layout.*
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.MutableState
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.graphics.Color
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.unit.dp
import chat.simplex.app.R
import chat.simplex.app.views.newchat.ActionButton
import chat.simplex.res.MR
sealed class AttachmentOption {
object CameraPhoto: AttachmentOption()
object GalleryImage: AttachmentOption()
object GalleryVideo: AttachmentOption()
object File: AttachmentOption()
}
@Composable
fun ChooseAttachmentView(
attachmentOption: MutableState<AttachmentOption?>,
hide: () -> Unit
) {
Box(
modifier = Modifier
.fillMaxWidth()
.wrapContentHeight()
.onFocusChanged { focusState ->
if (!focusState.hasFocus) hide()
}
) {
Row(
Modifier
.fillMaxWidth()
.padding(horizontal = 8.dp, vertical = 30.dp),
horizontalArrangement = Arrangement.SpaceEvenly
) {
ActionButton(Modifier.fillMaxWidth(0.25f), null, stringResource(MR.strings.use_camera_button), icon = painterResource(MR.images.ic_camera_enhance)) {
attachmentOption.value = AttachmentOption.CameraPhoto
hide()
}
ActionButton(Modifier.fillMaxWidth(0.33f), null, stringResource(MR.strings.gallery_image_button), icon = painterResource(MR.images.ic_add_photo)) {
attachmentOption.value = AttachmentOption.GalleryImage
hide()
}
ActionButton(Modifier.fillMaxWidth(0.50f), null, stringResource(MR.strings.gallery_video_button), icon = painterResource(MR.images.ic_smart_display)) {
attachmentOption.value = AttachmentOption.GalleryVideo
hide()
}
ActionButton(Modifier.fillMaxWidth(1f), null, stringResource(MR.strings.choose_file), icon = painterResource(MR.images.ic_note_add)) {
attachmentOption.value = AttachmentOption.File
hide()
}
}
}
}
@@ -1,148 +0,0 @@
package chat.simplex.app.views.helpers
import android.os.Build.VERSION.SDK_INT
import androidx.activity.compose.BackHandler
import androidx.biometric.BiometricManager
import androidx.biometric.BiometricManager.Authenticators.*
import androidx.biometric.BiometricPrompt
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Surface
import androidx.compose.ui.Modifier
import androidx.core.content.ContextCompat
import androidx.fragment.app.FragmentActivity
import chat.simplex.app.R
import chat.simplex.app.SimplexApp
import chat.simplex.app.views.helpers.DatabaseUtils.ksAppPassword
import chat.simplex.app.views.localauth.LocalAuthView
import chat.simplex.app.views.usersettings.LAMode
import chat.simplex.res.MR
sealed class LAResult {
object Success: LAResult()
class Error(val errString: CharSequence): LAResult()
class Failed(val errString: CharSequence? = null): LAResult()
class Unavailable(val errString: CharSequence? = null): LAResult()
}
data class LocalAuthRequest (
val title: String?,
val reason: String,
val password: String,
val selfDestruct: Boolean,
val completed: (LAResult) -> Unit
) {
companion object {
val sample = LocalAuthRequest(generalGetString(MR.strings.la_enter_app_passcode), generalGetString(MR.strings.la_authenticate), "", selfDestruct = false) { }
}
}
fun authenticate(
promptTitle: String,
promptSubtitle: String,
selfDestruct: Boolean = false,
usingLAMode: LAMode = SimplexApp.context.chatModel.controller.appPrefs.laMode.get(),
completed: (LAResult) -> Unit
) {
val activity = SimplexApp.context.mainActivity.get() ?: return completed(LAResult.Error(""))
when (usingLAMode) {
LAMode.SYSTEM -> when {
SDK_INT in 28..29 ->
// KeyguardManager.isDeviceSecure()? https://developer.android.com/training/sign-in/biometric-auth#declare-supported-authentication-types
authenticateWithBiometricManager(promptTitle, promptSubtitle, activity, completed, BIOMETRIC_WEAK or DEVICE_CREDENTIAL)
SDK_INT > 29 ->
authenticateWithBiometricManager(promptTitle, promptSubtitle, activity, completed, BIOMETRIC_STRONG or DEVICE_CREDENTIAL)
else -> completed(LAResult.Unavailable())
}
LAMode.PASSCODE -> {
val password = ksAppPassword.get() ?: return completed(LAResult.Unavailable(generalGetString(MR.strings.la_no_app_password)))
ModalManager.shared.showPasscodeCustomModal { close ->
BackHandler {
close()
completed(LAResult.Error(generalGetString(MR.strings.authentication_cancelled)))
}
Surface(Modifier.fillMaxSize(), color = MaterialTheme.colors.background) {
LocalAuthView(SimplexApp.context.chatModel, LocalAuthRequest(promptTitle, promptSubtitle, password, selfDestruct && SimplexApp.context.chatModel.controller.appPrefs.selfDestruct.get()) {
close()
completed(it)
})
}
}
}
}
}
private fun authenticateWithBiometricManager(
promptTitle: String,
promptSubtitle: String,
activity: FragmentActivity,
completed: (LAResult) -> Unit,
authenticators: Int
) {
val biometricManager = BiometricManager.from(activity)
when (biometricManager.canAuthenticate(authenticators)) {
BiometricManager.BIOMETRIC_SUCCESS -> {
val executor = ContextCompat.getMainExecutor(activity)
val biometricPrompt = BiometricPrompt(
activity,
executor,
object: BiometricPrompt.AuthenticationCallback() {
override fun onAuthenticationError(
errorCode: Int,
errString: CharSequence
) {
super.onAuthenticationError(errorCode, errString)
completed(LAResult.Error(errString))
}
override fun onAuthenticationSucceeded(
result: BiometricPrompt.AuthenticationResult
) {
super.onAuthenticationSucceeded(result)
completed(LAResult.Success)
}
override fun onAuthenticationFailed() {
super.onAuthenticationFailed()
completed(LAResult.Failed())
}
}
)
val promptInfo = BiometricPrompt.PromptInfo.Builder()
.setTitle(promptTitle)
.setSubtitle(promptSubtitle)
.setAllowedAuthenticators(authenticators)
.setConfirmationRequired(false)
.build()
biometricPrompt.authenticate(promptInfo)
}
else -> completed(LAResult.Unavailable())
}
}
fun laTurnedOnAlert() = AlertManager.shared.showAlertMsg(
generalGetString(MR.strings.auth_simplex_lock_turned_on),
generalGetString(MR.strings.auth_you_will_be_required_to_authenticate_when_you_start_or_resume)
)
fun laPasscodeNotSetAlert() = AlertManager.shared.showAlertMsg(
generalGetString(MR.strings.lock_not_enabled),
generalGetString(MR.strings.you_can_turn_on_lock)
)
fun laFailedAlert() {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.la_auth_failed),
text = generalGetString(MR.strings.la_could_not_be_verified)
)
}
fun laUnavailableInstructionAlert() = AlertManager.shared.showAlertMsg(
generalGetString(MR.strings.auth_unavailable),
generalGetString(MR.strings.auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled)
)
fun laUnavailableTurningOffAlert() = AlertManager.shared.showAlertMsg(
generalGetString(MR.strings.auth_unavailable),
generalGetString(MR.strings.auth_device_authentication_is_disabled_turning_off)
)
@@ -1,128 +0,0 @@
package chat.simplex.app.views.helpers
import android.Manifest
import android.content.*
import android.net.Uri
import android.provider.MediaStore
import android.util.Log
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.runtime.Composable
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import chat.simplex.app.*
import chat.simplex.app.model.CIFile
import chat.simplex.res.MR
import java.io.BufferedOutputStream
import java.io.File
fun shareText(text: String) {
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
putExtra(Intent.EXTRA_TEXT, text)
type = "text/plain"
}
val shareIntent = Intent.createChooser(sendIntent, null)
// This flag is needed when you start a new activity from non-Activity context
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
SimplexApp.context.startActivity(shareIntent)
}
fun shareFile(text: String, filePath: String) {
val uri = FileProvider.getUriForFile(SimplexApp.context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath))
val ext = filePath.substringAfterLast(".")
val mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(ext) ?: return
val sendIntent: Intent = Intent().apply {
action = Intent.ACTION_SEND
/*if (text.isNotEmpty()) {
putExtra(Intent.EXTRA_TEXT, text)
}*/
putExtra(Intent.EXTRA_STREAM, uri)
type = mimeType
}
val shareIntent = Intent.createChooser(sendIntent, null)
// This flag is needed when you start a new activity from non-Activity context
shareIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
SimplexApp.context.startActivity(shareIntent)
}
fun copyText(text: String) {
val clipboard = ContextCompat.getSystemService(SimplexApp.context, ClipboardManager::class.java)
clipboard?.setPrimaryClip(ClipData.newPlainText("text", text))
}
fun sendEmail(subject: String, body: CharSequence) {
val emailIntent = Intent(Intent.ACTION_SENDTO, Uri.parse("mailto:"))
emailIntent.putExtra(Intent.EXTRA_SUBJECT, subject)
emailIntent.putExtra(Intent.EXTRA_TEXT, body)
// This flag is needed when you start a new activity from non-Activity context
emailIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
try {
SimplexApp.context.startActivity(emailIntent)
} catch (e: ActivityNotFoundException) {
Log.e(TAG, "No activity was found for handling email intent")
}
}
@Composable
fun rememberSaveFileLauncher(ciFile: CIFile?): ManagedActivityResultLauncher<String, Uri?> =
rememberLauncherForActivityResult(
contract = ActivityResultContracts.CreateDocument(),
onResult = { destination ->
destination?.let {
val cxt = SimplexApp.context
val filePath = getLoadedFilePath(ciFile)
if (filePath != null) {
val contentResolver = cxt.contentResolver
contentResolver.openOutputStream(destination)?.let { stream ->
val outputStream = BufferedOutputStream(stream)
File(filePath).inputStream().use { it.copyTo(outputStream) }
outputStream.close()
Toast.makeText(cxt, generalGetString(MR.strings.file_saved), Toast.LENGTH_SHORT).show()
}
} else {
Toast.makeText(cxt, generalGetString(MR.strings.file_not_found), Toast.LENGTH_SHORT).show()
}
}
}
)
fun imageMimeType(fileName: String): String {
val lowercaseName = fileName.lowercase()
return when {
lowercaseName.endsWith(".png") -> "image/png"
lowercaseName.endsWith(".gif") -> "image/gif"
lowercaseName.endsWith(".webp") -> "image/webp"
lowercaseName.endsWith(".avif") -> "image/avif"
lowercaseName.endsWith(".svg") -> "image/svg+xml"
else -> "image/jpeg"
}
}
/** Before calling, make sure the user allows to write to external storage [Manifest.permission.WRITE_EXTERNAL_STORAGE] */
fun saveImage(ciFile: CIFile?) {
val cxt = SimplexApp.context
val filePath = getLoadedFilePath(ciFile)
val fileName = ciFile?.fileName
if (filePath != null && fileName != null) {
val values = ContentValues()
values.put(MediaStore.Images.Media.DATE_TAKEN, System.currentTimeMillis())
values.put(MediaStore.Images.Media.MIME_TYPE, imageMimeType(fileName))
values.put(MediaStore.MediaColumns.DISPLAY_NAME, fileName)
values.put(MediaStore.MediaColumns.TITLE, fileName)
val uri = cxt.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
uri?.let {
cxt.contentResolver.openOutputStream(uri)?.let { stream ->
val outputStream = BufferedOutputStream(stream)
File(filePath).inputStream().use { it.copyTo(outputStream) }
outputStream.close()
Toast.makeText(cxt, generalGetString(MR.strings.image_saved), Toast.LENGTH_SHORT).show()
}
}
} else {
Toast.makeText(cxt, generalGetString(MR.strings.file_not_found), Toast.LENGTH_SHORT).show()
}
}
@@ -1,687 +0,0 @@
package chat.simplex.app.views.helpers
import android.app.Activity
import android.app.Application
//import android.app.LocaleManager
import android.content.ActivityNotFoundException
import android.content.Context
import android.content.res.Configuration
import android.content.res.Resources
import android.graphics.*
import android.graphics.Typeface
import android.graphics.drawable.Drawable
import android.media.MediaMetadataRetriever
import android.net.Uri
import android.os.*
import android.provider.OpenableColumns
import android.text.Spanned
import android.text.SpannedString
import android.text.style.*
import android.util.Base64
import android.util.Log
import android.view.View
import android.view.ViewTreeObserver
import android.view.inputmethod.InputMethodManager
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.Saver
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.*
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.*
import androidx.compose.ui.text.style.BaselineShift
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.*
import androidx.core.content.FileProvider
import androidx.core.graphics.ColorUtils
import androidx.core.text.HtmlCompat
import chat.simplex.app.*
import chat.simplex.app.model.*
import chat.simplex.app.ui.theme.ThemeOverrides
import com.charleskorn.kaml.decodeFromStream
import chat.simplex.res.MR
import dev.icerock.moko.resources.StringResource
import kotlinx.coroutines.*
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
import org.apache.commons.io.IOUtils
import java.io.*
import java.text.SimpleDateFormat
import java.util.*
import kotlin.math.*
fun withApi(action: suspend CoroutineScope.() -> Unit): Job = withScope(GlobalScope, action)
fun withScope(scope: CoroutineScope, action: suspend CoroutineScope.() -> Unit): Job =
scope.launch { withContext(Dispatchers.Main, action) }
fun withBGApi(action: suspend CoroutineScope.() -> Unit): Job =
CoroutineScope(Dispatchers.Default).launch(block = action)
enum class KeyboardState {
Opened, Closed
}
@Composable
fun getKeyboardState(): State<KeyboardState> {
val keyboardState = remember { mutableStateOf(KeyboardState.Closed) }
val view = LocalView.current
DisposableEffect(view) {
val onGlobalListener = ViewTreeObserver.OnGlobalLayoutListener {
val rect = Rect()
view.getWindowVisibleDisplayFrame(rect)
val screenHeight = view.rootView.height
val keypadHeight = screenHeight - rect.bottom
keyboardState.value = if (keypadHeight > screenHeight * 0.15) {
KeyboardState.Opened
} else {
KeyboardState.Closed
}
}
view.viewTreeObserver.addOnGlobalLayoutListener(onGlobalListener)
onDispose {
view.viewTreeObserver.removeOnGlobalLayoutListener(onGlobalListener)
}
}
return keyboardState
}
fun hideKeyboard(view: View) =
(SimplexApp.context.getSystemService(Context.INPUT_METHOD_SERVICE) as InputMethodManager).hideSoftInputFromWindow(view.windowToken, 0)
// Resource to annotated string from
// https://stackoverflow.com/questions/68549248/android-jetpack-compose-how-to-show-styled-text-from-string-resources
fun generalGetString(id: StringResource): String {
// prefer stringResource in Composable items to retain preview abilities
return id.getString(SimplexApp.context)
}
@Composable
@ReadOnlyComposable
private fun resources(): Resources {
LocalConfiguration.current
return LocalContext.current.resources
}
fun Spanned.toHtmlWithoutParagraphs(): String {
return HtmlCompat.toHtml(this, HtmlCompat.TO_HTML_PARAGRAPH_LINES_CONSECUTIVE)
.substringAfter("<p dir=\"ltr\">").substringBeforeLast("</p>")
}
fun Resources.getText(id: StringResource, vararg args: Any): CharSequence {
val escapedArgs = args.map {
if (it is Spanned) it.toHtmlWithoutParagraphs() else it
}.toTypedArray()
val resource = SpannedString(getText(id))
val htmlResource = resource.toHtmlWithoutParagraphs()
val formattedHtml = String.format(htmlResource, *escapedArgs)
return HtmlCompat.fromHtml(formattedHtml, HtmlCompat.FROM_HTML_MODE_LEGACY)
}
fun escapedHtmlToAnnotatedString(text: String, density: Density): AnnotatedString {
return spannableStringToAnnotatedString(HtmlCompat.fromHtml(text, HtmlCompat.FROM_HTML_MODE_LEGACY), density)
}
@Composable
fun annotatedStringResource(id: StringResource): AnnotatedString {
val density = LocalDensity.current
return remember(id) {
val text = id.getString(SimplexApp.context)
escapedHtmlToAnnotatedString(text, density)
}
}
private fun spannableStringToAnnotatedString(
text: CharSequence,
density: Density,
): AnnotatedString {
return if (text is Spanned) {
with(density) {
buildAnnotatedString {
append((text.toString()))
text.getSpans(0, text.length, Any::class.java).forEach {
val start = text.getSpanStart(it)
val end = text.getSpanEnd(it)
when (it) {
is StyleSpan -> when (it.style) {
Typeface.NORMAL -> addStyle(
SpanStyle(
fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Normal,
),
start,
end
)
Typeface.BOLD -> addStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Normal
),
start,
end
)
Typeface.ITALIC -> addStyle(
SpanStyle(
fontWeight = FontWeight.Normal,
fontStyle = FontStyle.Italic
),
start,
end
)
Typeface.BOLD_ITALIC -> addStyle(
SpanStyle(
fontWeight = FontWeight.Bold,
fontStyle = FontStyle.Italic
),
start,
end
)
}
is TypefaceSpan -> addStyle(
SpanStyle(
fontFamily = when (it.family) {
FontFamily.SansSerif.name -> FontFamily.SansSerif
FontFamily.Serif.name -> FontFamily.Serif
FontFamily.Monospace.name -> FontFamily.Monospace
FontFamily.Cursive.name -> FontFamily.Cursive
else -> FontFamily.Default
}
),
start,
end
)
is AbsoluteSizeSpan -> addStyle(
SpanStyle(fontSize = if (it.dip) it.size.dp.toSp() else it.size.toSp()),
start,
end
)
is RelativeSizeSpan -> addStyle(
SpanStyle(fontSize = it.sizeChange.em),
start,
end
)
is StrikethroughSpan -> addStyle(
SpanStyle(textDecoration = TextDecoration.LineThrough),
start,
end
)
is UnderlineSpan -> addStyle(
SpanStyle(textDecoration = TextDecoration.Underline),
start,
end
)
is SuperscriptSpan -> addStyle(
SpanStyle(baselineShift = BaselineShift.Superscript),
start,
end
)
is SubscriptSpan -> addStyle(
SpanStyle(baselineShift = BaselineShift.Subscript),
start,
end
)
is ForegroundColorSpan -> addStyle(
SpanStyle(color = Color(it.foregroundColor)),
start,
end
)
else -> addStyle(SpanStyle(color = Color.White), start, end)
}
}
}
}
} else {
AnnotatedString(text.toString())
}
}
// maximum image file size to be auto-accepted
const val MAX_IMAGE_SIZE: Long = 261_120 // 255KB
const val MAX_IMAGE_SIZE_AUTO_RCV: Long = MAX_IMAGE_SIZE * 2
const val MAX_VOICE_SIZE_AUTO_RCV: Long = MAX_IMAGE_SIZE * 2
const val MAX_VIDEO_SIZE_AUTO_RCV: Long = 1_047_552 // 1023KB
const val MAX_VOICE_MILLIS_FOR_SENDING: Int = 300_000
const val MAX_FILE_SIZE_SMP: Long = 8000000
const val MAX_FILE_SIZE_XFTP: Long = 1_073_741_824 // 1GB
fun getFilesDirectory(): String {
return SimplexApp.context.filesDir.toString()
}
fun getTempFilesDirectory(): String {
return "${getFilesDirectory()}/temp_files"
}
fun getAppFilesDirectory(): String {
return "${getFilesDirectory()}/app_files"
}
fun getAppFilePath(fileName: String): String {
return "${getAppFilesDirectory()}/$fileName"
}
fun getAppFileUri(fileName: String): Uri {
return Uri.parse("${getAppFilesDirectory()}/$fileName")
}
fun getLoadedFilePath(file: CIFile?): String? {
return if (file?.filePath != null && file.loaded) {
val filePath = getAppFilePath(file.filePath)
if (File(filePath).exists()) filePath else null
} else {
null
}
}
// https://developer.android.com/training/data-storage/shared/documents-files#bitmap
fun getLoadedImage(file: CIFile?): Bitmap? {
val filePath = getLoadedFilePath(file)
return if (filePath != null) {
try {
val uri = FileProvider.getUriForFile(SimplexApp.context, "${BuildConfig.APPLICATION_ID}.provider", File(filePath))
val parcelFileDescriptor = SimplexApp.context.contentResolver.openFileDescriptor(uri, "r")
val fileDescriptor = parcelFileDescriptor?.fileDescriptor
val image = decodeSampledBitmapFromFileDescriptor(fileDescriptor, 1000, 1000)
parcelFileDescriptor?.close()
image
} catch (e: Exception) {
null
}
} else {
null
}
}
// https://developer.android.com/topic/performance/graphics/load-bitmap#load-bitmap
private fun decodeSampledBitmapFromFileDescriptor(fileDescriptor: FileDescriptor?, reqWidth: Int, reqHeight: Int): Bitmap {
// First decode with inJustDecodeBounds=true to check dimensions
return BitmapFactory.Options().run {
inJustDecodeBounds = true
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, this)
// Calculate inSampleSize
inSampleSize = calculateInSampleSize(this, reqWidth, reqHeight)
// Decode bitmap with inSampleSize set
inJustDecodeBounds = false
BitmapFactory.decodeFileDescriptor(fileDescriptor, null, this)
}
}
private fun calculateInSampleSize(options: BitmapFactory.Options, reqWidth: Int, reqHeight: Int): Int {
// Raw height and width of image
val (height: Int, width: Int) = options.run { outHeight to outWidth }
var inSampleSize = 1
if (height > reqHeight || width > reqWidth) {
val halfHeight: Int = height / 2
val halfWidth: Int = width / 2
// Calculate the largest inSampleSize value that is a power of 2 and keeps both
// height and width larger than the requested height and width.
while (halfHeight / inSampleSize >= reqHeight && halfWidth / inSampleSize >= reqWidth) {
inSampleSize *= 2
}
}
return inSampleSize
}
fun getFileName(uri: Uri): String? {
return SimplexApp.context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()
cursor.getString(nameIndex)
}
}
fun getAppFilePath(uri: Uri): String? {
return SimplexApp.context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val nameIndex = cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
cursor.moveToFirst()
getAppFilePath(cursor.getString(nameIndex))
}
}
fun getFileSize(uri: Uri): Long? {
return SimplexApp.context.contentResolver.query(uri, null, null, null, null)?.use { cursor ->
val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
cursor.moveToFirst()
cursor.getLong(sizeIndex)
}
}
fun getBitmapFromUri(uri: Uri, withAlertOnException: Boolean = true): Bitmap? {
return if (Build.VERSION.SDK_INT >= 28) {
val source = ImageDecoder.createSource(SimplexApp.context.contentResolver, uri)
try {
ImageDecoder.decodeBitmap(source)
} catch (e: android.graphics.ImageDecoder.DecodeException) {
Log.e(TAG, "Unable to decode the image: ${e.stackTraceToString()}")
if (withAlertOnException) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.image_decoding_exception_title),
text = generalGetString(MR.strings.image_decoding_exception_desc)
)
}
null
}
} else {
BitmapFactory.decodeFile(getAppFilePath(uri))
}
}
fun getDrawableFromUri(uri: Uri, withAlertOnException: Boolean = true): Drawable? {
return if (Build.VERSION.SDK_INT >= 28) {
val source = ImageDecoder.createSource(SimplexApp.context.contentResolver, uri)
try {
ImageDecoder.decodeDrawable(source)
} catch (e: android.graphics.ImageDecoder.DecodeException) {
if (withAlertOnException) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.image_decoding_exception_title),
text = generalGetString(MR.strings.image_decoding_exception_desc)
)
}
Log.e(TAG, "Error while decoding drawable: ${e.stackTraceToString()}")
null
}
} else {
Drawable.createFromPath(getAppFilePath(uri))
}
}
fun getThemeFromUri(uri: Uri, withAlertOnException: Boolean = true): ThemeOverrides? {
SimplexApp.context.contentResolver.openInputStream(uri).use {
runCatching {
return yaml.decodeFromStream<ThemeOverrides>(it!!)
}.onFailure {
if (withAlertOnException) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.import_theme_error),
text = generalGetString(MR.strings.import_theme_error_desc),
)
}
}
}
return null
}
fun saveImage(uri: Uri): String? {
val bitmap = getBitmapFromUri(uri) ?: return null
return saveImage(bitmap)
}
fun saveImage(image: Bitmap): String? {
return try {
val ext = if (image.hasAlpha()) "png" else "jpg"
val dataResized = resizeImageToDataSize(image, ext == "png", maxDataSize = MAX_IMAGE_SIZE)
val fileToSave = generateNewFileName("IMG", ext)
val file = File(getAppFilePath(fileToSave))
val output = FileOutputStream(file)
dataResized.writeTo(output)
output.flush()
output.close()
fileToSave
} catch (e: Exception) {
Log.e(chat.simplex.app.TAG, "Util.kt saveImage error: ${e.message}")
null
}
}
fun saveAnimImage(uri: Uri): String? {
return try {
val filename = getFileName(uri)?.lowercase()
var ext = when {
// remove everything but extension
filename?.contains(".") == true -> filename.replaceBeforeLast('.', "").replace(".", "")
else -> "gif"
}
// Just in case the image has a strange extension
if (ext.length < 3 || ext.length > 4) ext = "gif"
val fileToSave = generateNewFileName("IMG", ext)
val file = File(getAppFilePath(fileToSave))
val output = FileOutputStream(file)
SimplexApp.context.contentResolver.openInputStream(uri)!!.use { input ->
output.use { output ->
input.copyTo(output)
}
}
fileToSave
} catch (e: Exception) {
Log.e(chat.simplex.app.TAG, "Util.kt saveAnimImage error: ${e.message}")
null
}
}
fun saveTempImageUncompressed(image: Bitmap, asPng: Boolean): File? {
return try {
val ext = if (asPng) "png" else "jpg"
val tmpDir = SimplexApp.context.getDir("temp", Application.MODE_PRIVATE)
return File(tmpDir.absolutePath + File.separator + generateNewFileName("IMG", ext)).apply {
outputStream().use { out ->
image.compress(if (asPng) Bitmap.CompressFormat.PNG else Bitmap.CompressFormat.JPEG, 85, out)
out.flush()
}
deleteOnExit()
SimplexApp.context.chatModel.filesToDelete.add(this)
}
} catch (e: Exception) {
Log.e(TAG, "Util.kt saveTempImageUncompressed error: ${e.message}")
null
}
}
fun saveFileFromUri(uri: Uri): String? {
return try {
val inputStream = SimplexApp.context.contentResolver.openInputStream(uri)
val fileToSave = getFileName(uri)
if (inputStream != null && fileToSave != null) {
val destFileName = uniqueCombine(fileToSave)
val destFile = File(getAppFilePath(destFileName))
IOUtils.copy(inputStream, FileOutputStream(destFile))
destFileName
} else {
Log.e(chat.simplex.app.TAG, "Util.kt saveFileFromUri null inputStream")
null
}
} catch (e: Exception) {
Log.e(chat.simplex.app.TAG, "Util.kt saveFileFromUri error: ${e.message}")
null
}
}
fun generateNewFileName(prefix: String, ext: String): String {
val sdf = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.US)
sdf.timeZone = TimeZone.getTimeZone("GMT")
val timestamp = sdf.format(Date())
return uniqueCombine("${prefix}_$timestamp.$ext")
}
fun uniqueCombine(fileName: String): String {
val orig = File(fileName)
val name = orig.nameWithoutExtension
val ext = orig.extension
fun tryCombine(n: Int): String {
val suffix = if (n == 0) "" else "_$n"
val f = "$name$suffix.$ext"
return if (File(getAppFilePath(f)).exists()) tryCombine(n + 1) else f
}
return tryCombine(0)
}
fun formatBytes(bytes: Long): String {
if (bytes == 0.toLong()) {
return "0 bytes"
}
val bytesDouble = bytes.toDouble()
val k = 1024.toDouble()
val units = arrayOf("bytes", "KB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB")
val i = floor(log2(bytesDouble) / log2(k))
val size = bytesDouble / k.pow(i)
val unit = units[i.toInt()]
return if (i <= 1) {
String.format("%.0f %s", size, unit)
} else {
String.format("%.2f %s", size, unit)
}
}
fun removeFile(fileName: String): Boolean {
val file = File(getAppFilePath(fileName))
val fileDeleted = file.delete()
if (!fileDeleted) {
Log.e(chat.simplex.app.TAG, "Util.kt removeFile error")
}
return fileDeleted
}
fun deleteAppFiles() {
val dir = File(getAppFilesDirectory())
try {
dir.list()?.forEach {
removeFile(it)
}
} catch (e: java.lang.Exception) {
Log.e(TAG, "Util deleteAppFiles error: ${e.stackTraceToString()}")
}
}
fun directoryFileCountAndSize(dir: String): Pair<Int, Long> { // count, size in bytes
var fileCount = 0
var bytes = 0L
try {
File(dir).listFiles()?.forEach {
fileCount++
bytes += it.length()
}
} catch (e: java.lang.Exception) {
Log.e(TAG, "Util directoryFileCountAndSize error: ${e.stackTraceToString()}")
}
return fileCount to bytes
}
fun getMaxFileSize(fileProtocol: FileProtocol): Long {
return when (fileProtocol) {
FileProtocol.XFTP -> MAX_FILE_SIZE_XFTP
FileProtocol.SMP -> MAX_FILE_SIZE_SMP
}
}
fun getBitmapFromVideo(uri: Uri, timestamp: Long? = null, random: Boolean = true): VideoPlayer.PreviewAndDuration {
val mmr = MediaMetadataRetriever()
mmr.setDataSource(SimplexApp.context, uri)
val durationMs = mmr.extractMetadata(MediaMetadataRetriever.METADATA_KEY_DURATION)?.toLong()
val image = when {
timestamp != null -> mmr.getFrameAtTime(timestamp * 1000, MediaMetadataRetriever.OPTION_CLOSEST)
random -> mmr.frameAtTime
else -> mmr.getFrameAtTime(0)
}
mmr.release()
return VideoPlayer.PreviewAndDuration(image, durationMs, timestamp ?: 0)
}
fun Color.darker(factor: Float = 0.1f): Color =
Color(max(red * (1 - factor), 0f), max(green * (1 - factor), 0f), max(blue * (1 - factor), 0f), alpha)
fun Color.lighter(factor: Float = 0.1f): Color =
Color(min(red * (1 + factor), 1f), min(green * (1 + factor), 1f), min(blue * (1 + factor), 1f), alpha)
fun Color.mixWith(color: Color, alpha: Float): Color =
Color(ColorUtils.blendARGB(color.toArgb(), toArgb(), alpha))
fun ByteArray.toBase64String() = Base64.encodeToString(this, Base64.DEFAULT)
fun String.toByteArrayFromBase64() = Base64.decode(this, Base64.DEFAULT)
val LongRange.Companion.saver
get() = Saver<MutableState<LongRange>, Pair<Long, Long>>(
save = { it.value.first to it.value.last },
restore = { mutableStateOf(it.first..it.second) }
)
/* Make sure that T class has @Serializable annotation */
inline fun <reified T> serializableSaver(): Saver<T, *> = Saver(
save = { json.encodeToString(it) },
restore = { json.decodeFromString(it) }
)
fun saveAppLocale(pref: SharedPreference<String?>, activity: Activity, languageCode: String? = null) {
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
// val localeManager = SimplexApp.context.getSystemService(LocaleManager::class.java)
// localeManager.applicationLocales = LocaleList(Locale.forLanguageTag(languageCode ?: return))
// } else {
pref.set(languageCode)
if (languageCode == null) {
activity.applyLocale(SimplexApp.context.defaultLocale)
}
activity.recreate()
// }
}
fun Activity.applyAppLocale(pref: SharedPreference<String?>) {
// if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
val lang = pref.get() ?: return
applyLocale(Locale.forLanguageTag(lang))
// }
}
private fun Activity.applyLocale(locale: Locale) {
Locale.setDefault(locale)
val appConf = Configuration(SimplexApp.context.resources.configuration).apply { setLocale(locale) }
val activityConf = Configuration(resources.configuration).apply { setLocale(locale) }
@Suppress("DEPRECATION")
SimplexApp.context.resources.updateConfiguration(appConf, resources.displayMetrics)
@Suppress("DEPRECATION")
resources.updateConfiguration(activityConf, resources.displayMetrics)
}
fun UriHandler.openUriCatching(uri: String) {
try {
openUri(uri)
} catch (e: ActivityNotFoundException) {
Log.e(TAG, e.stackTraceToString())
}
}
fun IntSize.Companion.Saver(): Saver<IntSize, *> = Saver(
save = { it.width to it.height },
restore = { IntSize(it.first, it.second) }
)
@Composable
fun DisposableEffectOnGone(always: () -> Unit = {}, whenDispose: () -> Unit = {}, whenGone: () -> Unit) {
val context = LocalContext.current
DisposableEffect(Unit) {
always()
val activity = context as? Activity ?: return@DisposableEffect onDispose {}
val orientation = activity.resources.configuration.orientation
onDispose {
whenDispose()
if (orientation == activity.resources.configuration.orientation) {
whenGone()
}
}
}
}
@Composable
fun DisposableEffectOnRotate(always: () -> Unit = {}, whenDispose: () -> Unit = {}, whenRotate: () -> Unit) {
val context = LocalContext.current
DisposableEffect(Unit) {
always()
val activity = context as? Activity ?: return@DisposableEffect onDispose {}
val orientation = activity.resources.configuration.orientation
onDispose {
whenDispose()
if (orientation != activity.resources.configuration.orientation) {
whenRotate()
}
}
}
}
@@ -1,171 +0,0 @@
package chat.simplex.app.views.newchat
import SectionBottomSpacer
import SectionSpacer
import SectionView
import android.content.res.Configuration
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import dev.icerock.moko.resources.compose.painterResource
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import chat.simplex.app.R
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
import chat.simplex.app.views.usersettings.SettingsActionItem
import chat.simplex.res.MR
@Composable
fun AddContactView(connReqInvitation: String, connIncognito: Boolean) {
AddContactLayout(
connReq = connReqInvitation,
connIncognito = connIncognito,
share = { shareText(connReqInvitation) },
learnMore = {
ModalManager.shared.showModal {
Column(
Modifier
.fillMaxHeight()
.padding(horizontal = DEFAULT_PADDING),
verticalArrangement = Arrangement.SpaceBetween
) {
AddContactLearnMore()
}
}
}
)
}
@Composable
fun AddContactLayout(connReq: String, connIncognito: Boolean, share: () -> Unit, learnMore: () -> Unit) {
Column(
Modifier
.verticalScroll(rememberScrollState()),
verticalArrangement = Arrangement.SpaceBetween,
) {
AppBarTitle(stringResource(MR.strings.add_contact))
OneTimeLinkProfileText(connIncognito)
SectionSpacer()
SectionView(stringResource(MR.strings.one_time_link_short).uppercase()) {
OneTimeLinkSection(connReq, share, learnMore)
}
SectionBottomSpacer()
}
}
@Composable
fun OneTimeLinkProfileText(connIncognito: Boolean) {
Row(Modifier.padding(horizontal = DEFAULT_PADDING)) {
InfoAboutIncognito(
connIncognito,
true,
generalGetString(MR.strings.incognito_random_profile_description),
generalGetString(MR.strings.your_profile_will_be_sent)
)
}
}
@Composable
fun ColumnScope.OneTimeLinkSection(connReq: String, share: () -> Unit, learnMore: () -> Unit) {
if (connReq.isNotEmpty()) {
QRCode(
connReq, Modifier
.padding(horizontal = DEFAULT_PADDING, vertical = DEFAULT_PADDING_HALF)
.aspectRatio(1f)
)
} else {
CircularProgressIndicator(
Modifier
.size(36.dp)
.padding(4.dp)
.align(Alignment.CenterHorizontally),
color = MaterialTheme.colors.secondary,
strokeWidth = 3.dp
)
}
ShareLinkButton(share)
OneTimeLinkLearnMoreButton(learnMore)
}
@Composable
fun ShareLinkButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(MR.images.ic_share),
stringResource(MR.strings.share_invitation_link),
onClick,
iconColor = MaterialTheme.colors.primary,
textColor = MaterialTheme.colors.primary,
)
}
@Composable
fun OneTimeLinkLearnMoreButton(onClick: () -> Unit) {
SettingsActionItem(
painterResource(MR.images.ic_info),
stringResource(MR.strings.learn_more),
onClick,
)
}
@Composable
fun InfoAboutIncognito(chatModelIncognito: Boolean, supportedIncognito: Boolean = true, onText: String, offText: String, centered: Boolean = false) {
if (chatModelIncognito) {
Row(
Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = if (centered) Arrangement.Center else Arrangement.Start
) {
Icon(
if (supportedIncognito) painterResource(MR.images.ic_theater_comedy_filled) else painterResource(MR.images.ic_info),
stringResource(MR.strings.incognito),
tint = if (supportedIncognito) Indigo else WarningOrange,
modifier = Modifier.padding(end = 10.dp).size(20.dp)
)
Text(onText, textAlign = if (centered) TextAlign.Center else TextAlign.Left, style = MaterialTheme.typography.body2)
}
} else {
Row(
Modifier
.fillMaxWidth()
.padding(vertical = 4.dp),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = if (centered) Arrangement.Center else Arrangement.Start
) {
Icon(
painterResource(MR.images.ic_info),
stringResource(MR.strings.incognito),
tint = MaterialTheme.colors.secondary,
modifier = Modifier.padding(end = 10.dp).size(20.dp)
)
Text(offText, textAlign = if (centered) TextAlign.Center else TextAlign.Left, style = MaterialTheme.typography.body2)
}
}
}
@Preview
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewAddContactView() {
SimpleXTheme {
AddContactLayout(
connReq = "https://simplex.chat/contact#/?v=1&smp=smp%3A%2F%2FPQUV2eL0t7OStZOoAsPEV2QYWt4-xilbakvGUGOItUo%3D%40smp6.simplex.im%2FK1rslx-m5bpXVIdMZg9NLUZ_8JBm8xTt%23MCowBQYDK2VuAyEALDeVe-sG8mRY22LsXlPgiwTNs9dbiLrNuA7f3ZMAJ2w%3D",
connIncognito = false,
share = {},
learnMore = {},
)
}
}
@@ -1,139 +0,0 @@
package chat.simplex.app.views.newchat
import SectionBottomSpacer
import android.content.ClipboardManager
import android.content.res.Configuration
import android.net.Uri
import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.core.content.ContextCompat.getSystemService
import chat.simplex.app.R
import chat.simplex.app.TAG
import chat.simplex.app.model.ChatModel
import chat.simplex.app.ui.theme.*
import chat.simplex.app.views.helpers.*
import chat.simplex.res.MR
@Composable
fun PasteToConnectView(chatModel: ChatModel, close: () -> Unit) {
val connectionLink = remember { mutableStateOf("") }
val context = LocalContext.current
val clipboard = getSystemService(context, ClipboardManager::class.java)
PasteToConnectLayout(
chatModel.incognito.value,
connectionLink = connectionLink,
pasteFromClipboard = {
connectionLink.value = clipboard?.primaryClip?.getItemAt(0)?.coerceToText(context) as? String ?: return@PasteToConnectLayout
},
connectViaLink = { connReqUri ->
try {
val uri = Uri.parse(connReqUri)
withUriAction(uri) { linkType ->
val action = suspend {
Log.d(TAG, "connectViaUri: connecting")
if (connectViaUri(chatModel, linkType, uri)) {
close()
}
}
if (linkType == ConnectionLinkType.GROUP) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.connect_via_group_link),
text = generalGetString(MR.strings.you_will_join_group),
confirmText = generalGetString(MR.strings.connect_via_link_verb),
onConfirm = { withApi { action() } }
)
} else action()
}
} catch (e: RuntimeException) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.invalid_connection_link),
text = generalGetString(MR.strings.this_string_is_not_a_connection_link)
)
}
},
)
}
@Composable
fun PasteToConnectLayout(
chatModelIncognito: Boolean,
connectionLink: MutableState<String>,
pasteFromClipboard: () -> Unit,
connectViaLink: (String) -> Unit,
) {
Column(
Modifier.verticalScroll(rememberScrollState()).padding(horizontal = DEFAULT_PADDING),
verticalArrangement = Arrangement.SpaceBetween,
) {
AppBarTitle(stringResource(MR.strings.connect_via_link), false)
Text(stringResource(MR.strings.paste_connection_link_below_to_connect))
InfoAboutIncognito(
chatModelIncognito,
true,
generalGetString(MR.strings.incognito_random_profile_from_contact_description),
generalGetString(MR.strings.profile_will_be_sent_to_contact_sending_link)
)
Box(Modifier.padding(top = DEFAULT_PADDING, bottom = 6.dp)) {
TextEditor(connectionLink, Modifier.height(180.dp), contentPadding = PaddingValues())
}
Row(
Modifier.fillMaxWidth().padding(bottom = 6.dp),
horizontalArrangement = Arrangement.Start,
) {
if (connectionLink.value == "") {
SimpleButton(text = stringResource(MR.strings.paste_button), icon = painterResource(MR.images.ic_content_paste)) {
pasteFromClipboard()
}
} else {
SimpleButton(text = stringResource(MR.strings.clear_verb), icon = painterResource(MR.images.ic_close)) {
connectionLink.value = ""
}
}
Spacer(Modifier.weight(1f).fillMaxWidth())
SimpleButton(text = stringResource(MR.strings.connect_button), icon = painterResource(MR.images.ic_link)) {
connectViaLink(connectionLink.value)
}
}
Text(annotatedStringResource(MR.strings.you_can_also_connect_by_clicking_the_link))
SectionBottomSpacer()
}
}
@Preview(showBackground = true)
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
name = "Dark Mode"
)
@Composable
fun PreviewPasteToConnectTextbox() {
SimpleXTheme {
PasteToConnectLayout(
chatModelIncognito = false,
connectionLink = remember { mutableStateOf("") },
pasteFromClipboard = {},
connectViaLink = { link ->
try {
println(link)
// withApi { chatModel.controller.apiConnect(link) }
} catch (e: Exception) {
e.printStackTrace()
}
},
)
}
}
@@ -1,164 +0,0 @@
package chat.simplex.app.views.newchat
import SectionBottomSpacer
import android.Manifest
import android.content.res.Configuration
import android.net.Uri
import android.util.Log
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.*
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.ui.Modifier
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.core.net.toUri
import chat.simplex.app.R
import chat.simplex.app.TAG
import chat.simplex.app.model.ChatModel
import chat.simplex.app.model.json
import chat.simplex.app.ui.theme.DEFAULT_PADDING
import chat.simplex.app.ui.theme.SimpleXTheme
import chat.simplex.app.views.helpers.*
import com.google.accompanist.permissions.rememberPermissionState
import chat.simplex.res.MR
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@Composable
fun ScanToConnectView(chatModel: ChatModel, close: () -> Unit) {
val cameraPermissionState = rememberPermissionState(permission = Manifest.permission.CAMERA)
LaunchedEffect(Unit) {
cameraPermissionState.launchPermissionRequest()
}
ConnectContactLayout(
chatModelIncognito = chatModel.incognito.value,
qrCodeScanner = {
QRCodeScanner { connReqUri ->
try {
val uri = Uri.parse(connReqUri)
withUriAction(uri) { linkType ->
val action = suspend {
Log.d(TAG, "connectViaUri: connecting")
if (connectViaUri(chatModel, linkType, uri)) {
close()
}
}
if (linkType == ConnectionLinkType.GROUP) {
AlertManager.shared.showAlertDialog(
title = generalGetString(MR.strings.connect_via_group_link),
text = generalGetString(MR.strings.you_will_join_group),
confirmText = generalGetString(MR.strings.connect_via_link_verb),
onConfirm = { withApi { action() } }
)
} else action()
}
} catch (e: RuntimeException) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.invalid_QR_code),
text = generalGetString(MR.strings.this_QR_code_is_not_a_link)
)
}
}
},
)
}
enum class ConnectionLinkType {
CONTACT, INVITATION, GROUP
}
@Serializable
sealed class CReqClientData {
@Serializable @SerialName("group") data class Group(val groupLinkId: String): CReqClientData()
}
fun withUriAction(uri: Uri, run: suspend (ConnectionLinkType) -> Unit) {
val action = uri.path?.drop(1)?.replace("/", "")
val data = uri.toString().replaceFirst("#/", "/").toUri().getQueryParameter("data")
val type = when {
data != null -> {
val parsed = runCatching {
json.decodeFromString(CReqClientData.serializer(), data)
}
when {
parsed.getOrNull() is CReqClientData.Group -> ConnectionLinkType.GROUP
else -> null
}
}
action == "contact" -> ConnectionLinkType.CONTACT
action == "invitation" -> ConnectionLinkType.INVITATION
else -> null
}
if (type != null) {
withApi { run(type) }
} else {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.invalid_contact_link),
text = generalGetString(MR.strings.this_link_is_not_a_valid_connection_link)
)
}
}
suspend fun connectViaUri(chatModel: ChatModel, action: ConnectionLinkType, uri: Uri): Boolean {
val r = chatModel.controller.apiConnect(uri.toString())
if (r) {
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.connection_request_sent),
text =
when (action) {
ConnectionLinkType.CONTACT -> generalGetString(MR.strings.you_will_be_connected_when_your_connection_request_is_accepted)
ConnectionLinkType.INVITATION -> generalGetString(MR.strings.you_will_be_connected_when_your_contacts_device_is_online)
ConnectionLinkType.GROUP -> generalGetString(MR.strings.you_will_be_connected_when_group_host_device_is_online)
}
)
}
return r
}
@Composable
fun ConnectContactLayout(chatModelIncognito: Boolean, qrCodeScanner: @Composable () -> Unit) {
Column(
Modifier.verticalScroll(rememberScrollState()).padding(horizontal = DEFAULT_PADDING),
verticalArrangement = Arrangement.spacedBy(12.dp)
) {
AppBarTitle(stringResource(MR.strings.scan_QR_code), false)
InfoAboutIncognito(
chatModelIncognito,
true,
generalGetString(MR.strings.incognito_random_profile_description),
generalGetString(MR.strings.your_profile_will_be_sent)
)
Box(
Modifier
.fillMaxWidth()
.aspectRatio(ratio = 1F)
.padding(bottom = 12.dp)
) { qrCodeScanner() }
Text(
annotatedStringResource(MR.strings.if_you_cannot_meet_in_person_scan_QR_in_video_call_or_ask_for_invitation_link),
lineHeight = 22.sp
)
SectionBottomSpacer()
}
}
@Preview
@Preview(
uiMode = Configuration.UI_MODE_NIGHT_YES,
showBackground = true,
name = "Dark Mode"
)
@Composable
fun PreviewConnectContactLayout() {
SimpleXTheme {
ConnectContactLayout(
chatModelIncognito = false,
qrCodeScanner = { Surface {} },
)
}
}

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