Compare commits

..

30 Commits

Author SHA1 Message Date
Ghost of Sparta
e85d005415 Translated using Weblate (Hungarian)
Currently translated at 43.6% (613 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:34 +01:00
Ghost of Sparta
d6374f8551 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1608 of 1608 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/
2024-01-27 21:06:33 +01:00
jonnysemon
76fe4b7bc0 Translated using Weblate (Arabic)
Currently translated at 99.7% (1604 of 1608 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/
2024-01-27 21:06:33 +01:00
summoner001
3410e9b1f5 Translated using Weblate (Hungarian)
Currently translated at 29.8% (419 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:32 +01:00
Ghost of Sparta
58d6c91ca0 Translated using Weblate (Hungarian)
Currently translated at 29.8% (419 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:32 +01:00
summoner001
afb9796801 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1608 of 1608 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/
2024-01-27 21:06:31 +01:00
Ghost of Sparta
3549966abe Translated using Weblate (Hungarian)
Currently translated at 100.0% (1608 of 1608 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/
2024-01-27 21:06:30 +01:00
Ghost of Sparta
fd7fe302ad Translated using Weblate (Hungarian)
Currently translated at 20.8% (292 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:30 +01:00
Ghost of Sparta
5006d930b8 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1608 of 1608 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/
2024-01-27 21:06:29 +01:00
大王叫我来巡山
a02259a166 Translated using Weblate (Chinese (Simplified))
Currently translated at 100.0% (1608 of 1608 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/zh_Hans/
2024-01-27 21:06:29 +01:00
Ghost of Sparta
8bfa0f2253 Translated using Weblate (Hungarian)
Currently translated at 5.9% (84 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:28 +01:00
Ghost of Sparta
0528302935 Translated using Weblate (Hungarian)
Currently translated at 0.6% (9 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:27 +01:00
summoner001
04c22a133a Translated using Weblate (Hungarian)
Currently translated at 0.2% (4 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:27 +01:00
Ghost of Sparta
34b24c7997 Translated using Weblate (Hungarian)
Currently translated at 0.2% (4 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/hu/
2024-01-27 21:06:26 +01:00
Ghost of Sparta
4926154d67 Translated using Weblate (Hungarian)
Currently translated at 100.0% (1607 of 1607 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/
2024-01-27 21:06:25 +01:00
z0rden
b637e7b870 Translated using Weblate (Turkish)
Currently translated at 100.0% (1607 of 1607 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/
2024-01-27 21:06:25 +01:00
z0rden
84818d70a2 Translated using Weblate (Turkish)
Currently translated at 100.0% (1403 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/tr/
2024-01-27 21:06:24 +01:00
jonnysemon
7d33c53789 Translated using Weblate (Arabic)
Currently translated at 99.7% (1603 of 1607 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/ar/
2024-01-27 21:06:23 +01:00
Random
650ba37824 Translated using Weblate (Italian)
Currently translated at 100.0% (1607 of 1607 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/
2024-01-27 21:06:23 +01:00
summoner001
f6021c5dfb Translated using Weblate (Hungarian)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/hu/
2024-01-27 21:06:22 +01:00
M1K4
d41766b450 Translated using Weblate (Dutch)
Currently translated at 100.0% (1403 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/nl/
2024-01-27 21:06:21 +01:00
M1K4
e6bba2c8d7 Translated using Weblate (Dutch)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/nl/
2024-01-27 21:06:21 +01:00
elgratea
a5607088a6 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/bg/
2024-01-27 21:06:20 +01:00
elgratea
682d6fdbf0 Translated using Weblate (Bulgarian)
Currently translated at 100.0% (1403 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/bg/
2024-01-27 21:06:19 +01:00
Random
378fd6f48c Translated using Weblate (Italian)
Currently translated at 100.0% (1403 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/it/
2024-01-27 21:06:19 +01:00
Random
d0c0a2b049 Translated using Weblate (Italian)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/it/
2024-01-27 21:06:18 +01:00
Siavash
c5de6750c5 Translated using Weblate (Persian)
Currently translated at 9.2% (149 of 1605 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/fa/
2024-01-27 21:06:18 +01:00
z0rden
5ad6303bf9 Translated using Weblate (Turkish)
Currently translated at 100.0% (1605 of 1605 strings)

Translation: SimpleX Chat/SimpleX Chat Android
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/android/tr/
2024-01-27 21:06:17 +01:00
z0rden
189c441653 Translated using Weblate (Turkish)
Currently translated at 100.0% (1403 of 1403 strings)

Translation: SimpleX Chat/SimpleX Chat iOS
Translate-URL: https://hosted.weblate.org/projects/simplex-chat/ios/tr/
2024-01-27 21:06:16 +01:00
Evgeny Poberezkin
059d82a8de Added translation using Weblate (Hungarian) 2024-01-27 21:06:16 +01:00
68 changed files with 7840 additions and 1782 deletions

View File

@@ -217,8 +217,9 @@
<target>%lld блокирани съобщения</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve">
<trans-unit id="%lld messages blocked by admin" xml:space="preserve" approved="no">
<source>%lld messages blocked by admin</source>
<target state="translated">%lld съобщения, блокирани от администратора</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
@@ -642,8 +643,9 @@
<target>Всички членове на групата ще останат свързани.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve">
<trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve" approved="no">
<source>All messages will be deleted - this cannot be undone!</source>
<target state="translated">Всички съобщения ще бъдат изтрити - това не може да бъде отменено!</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">
@@ -921,8 +923,9 @@
<target>Блокирай</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block for all" xml:space="preserve">
<trans-unit id="Block for all" xml:space="preserve" approved="no">
<source>Block for all</source>
<target state="translated">Блокирай за всички</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
@@ -935,8 +938,9 @@
<target>Блокирай член</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member for all?" xml:space="preserve">
<trans-unit id="Block member for all?" xml:space="preserve" approved="no">
<source>Block member for all?</source>
<target state="translated">Блокиране на член за всички?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
@@ -944,8 +948,9 @@
<target>Блокирай члена?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Blocked by admin" xml:space="preserve">
<trans-unit id="Blocked by admin" xml:space="preserve" approved="no">
<source>Blocked by admin</source>
<target state="translated">Блокиран от админ</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -1159,8 +1164,9 @@
<target>Изчисти разговора?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear private notes?" xml:space="preserve">
<trans-unit id="Clear private notes?" xml:space="preserve" approved="no">
<source>Clear private notes?</source>
<target state="translated">Изчистване на лични бележки?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear verification" xml:space="preserve">
@@ -1457,12 +1463,14 @@ This is your own one-time link!</source>
<target>Създай своя профил</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Created at" xml:space="preserve">
<trans-unit id="Created at" xml:space="preserve" approved="no">
<source>Created at</source>
<target state="translated">Създаден на</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Created at: %@" xml:space="preserve">
<trans-unit id="Created at: %@" xml:space="preserve" approved="no">
<source>Created at: %@</source>
<target state="translated">Създаден на: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Created on %@" xml:space="preserve">
@@ -1940,9 +1948,9 @@ This cannot be undone!</source>
<target>Открийте и се присъединете към групи</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Discover via local network" xml:space="preserve">
<trans-unit id="Discover via local network" xml:space="preserve" approved="no">
<source>Discover via local network</source>
<target>Открий през локалната мрежа</target>
<target state="translated">Откриване през локалната мрежа</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do NOT use SimpleX for emergency calls." xml:space="preserve">
@@ -2250,8 +2258,9 @@ This cannot be undone!</source>
<target>Грешка при създаване на контакт с член</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating message" xml:space="preserve">
<trans-unit id="Error creating message" xml:space="preserve" approved="no">
<source>Error creating message</source>
<target state="translated">Грешка при създаване на съобщение</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating profile!" xml:space="preserve">
@@ -2924,8 +2933,9 @@ This cannot be undone!</source>
<target>Импортиране на база данни</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Improved message delivery" xml:space="preserve">
<trans-unit id="Improved message delivery" xml:space="preserve" approved="no">
<source>Improved message delivery</source>
<target state="translated">Подобрена доставка на съобщения</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Improved privacy and security" xml:space="preserve">
@@ -3151,8 +3161,9 @@ This cannot be undone!</source>
<target>Влез в групата</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join group conversations" xml:space="preserve">
<trans-unit id="Join group conversations" xml:space="preserve" approved="no">
<source>Join group conversations</source>
<target state="translated">Присъединяване към групи</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
@@ -3861,8 +3872,9 @@ This is your link for group %@!</source>
<target>Парола за показване</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Past member %@" xml:space="preserve">
<trans-unit id="Past member %@" xml:space="preserve" approved="no">
<source>Past member %@</source>
<target state="translated">Бивш член %@</target>
<note>past/unknown group member</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
@@ -3875,8 +3887,9 @@ This is your link for group %@!</source>
<target>Постави изображение</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste link to connect!" xml:space="preserve">
<trans-unit id="Paste link to connect!" xml:space="preserve" approved="no">
<source>Paste link to connect!</source>
<target state="translated">Поставете линк, за да се свържете!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve">
@@ -4011,8 +4024,9 @@ Error: %@</source>
<target>Поверителни имена на файлове</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Private notes" xml:space="preserve">
<trans-unit id="Private notes" xml:space="preserve" approved="no">
<source>Private notes</source>
<target state="translated">Лични бележки</target>
<note>name of notes to self</note>
</trans-unit>
<trans-unit id="Profile and server connections" xml:space="preserve">
@@ -4195,8 +4209,9 @@ Error: %@</source>
<target>Получаване чрез</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve">
<trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve" approved="no">
<source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source>
<target state="translated">Скорошна история и подобрен [bot за директория за групи](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPd jdLW3%23%2F%3Fv%3D1-2% 26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Recipients see updates as you type them." xml:space="preserve">
@@ -4484,8 +4499,9 @@ Error: %@</source>
<target>Запазените WebRTC ICE сървъри ще бъдат премахнати</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Saved message" xml:space="preserve">
<trans-unit id="Saved message" xml:space="preserve" approved="no">
<source>Saved message</source>
<target state="translated">Запазено съобщение</target>
<note>message info title</note>
</trans-unit>
<trans-unit id="Scan QR code" xml:space="preserve">
@@ -4518,8 +4534,9 @@ Error: %@</source>
<target>Търсене</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Search bar accepts invitation links." xml:space="preserve">
<trans-unit id="Search bar accepts invitation links." xml:space="preserve" approved="no">
<source>Search bar accepts invitation links.</source>
<target state="translated">Лентата за търсене приема линк за връзка.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
@@ -5356,8 +5373,9 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>Опит за свързване със сървъра, използван за получаване на съобщения от този контакт.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turkish interface" xml:space="preserve">
<trans-unit id="Turkish interface" xml:space="preserve" approved="no">
<source>Turkish interface</source>
<target state="translated">Турски интерфейс</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn off" xml:space="preserve">
@@ -5380,8 +5398,9 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>Отблокирай</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock for all" xml:space="preserve">
<trans-unit id="Unblock for all" xml:space="preserve" approved="no">
<source>Unblock for all</source>
<target state="translated">Отблокирай за всички</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
@@ -5389,8 +5408,9 @@ You will be prompted to complete authentication before this feature is enabled.<
<target>Отблокирай член</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<trans-unit id="Unblock member for all?" xml:space="preserve" approved="no">
<source>Unblock member for all?</source>
<target state="translated">Отблокиране на член за всички?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -5605,29 +5625,29 @@ To connect, please ask your contact to create another connection link and check
<target>Използват се сървърите на SimpleX Chat.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify code with desktop" xml:space="preserve">
<trans-unit id="Verify code with desktop" xml:space="preserve" approved="no">
<source>Verify code with desktop</source>
<target>Потвръди кода с настолното устройство</target>
<target state="translated">Потвърди кода с настолното устройство</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection" xml:space="preserve">
<trans-unit id="Verify connection" xml:space="preserve" approved="no">
<source>Verify connection</source>
<target>Потвръди връзките</target>
<target state="translated">Потвърди връзка</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connection security" xml:space="preserve">
<trans-unit id="Verify connection security" xml:space="preserve" approved="no">
<source>Verify connection security</source>
<target>Потвръди сигурността на връзката</target>
<target state="translated">Потвърди сигурността на връзката</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify connections" xml:space="preserve">
<trans-unit id="Verify connections" xml:space="preserve" approved="no">
<source>Verify connections</source>
<target>Потвръди връзките</target>
<target state="translated">Потвърждение за свързване</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Verify security code" xml:space="preserve">
<trans-unit id="Verify security code" xml:space="preserve" approved="no">
<source>Verify security code</source>
<target>Потвръди кода за сигурност</target>
<target state="translated">Потвърди кода за сигурност</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Via browser" xml:space="preserve">
@@ -5755,8 +5775,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="With encrypted files and media." xml:space="preserve">
<trans-unit id="With encrypted files and media." xml:space="preserve" approved="no">
<source>With encrypted files and media.</source>
<target state="translated">С криптирани файлове и медия.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="With optional welcome message." xml:space="preserve">
@@ -5764,8 +5785,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="With reduced battery usage." xml:space="preserve">
<trans-unit id="With reduced battery usage." xml:space="preserve" approved="no">
<source>With reduced battery usage.</source>
<target state="translated">С намален разход на батерията.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Wrong database passphrase" xml:space="preserve">
@@ -6271,12 +6293,14 @@ SimpleX сървърите не могат да видят вашия профи
<target>блокиран</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="blocked %@" xml:space="preserve">
<trans-unit id="blocked %@" xml:space="preserve" approved="no">
<source>blocked %@</source>
<target state="translated">блокиран %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="blocked by admin" xml:space="preserve">
<trans-unit id="blocked by admin" xml:space="preserve" approved="no">
<source>blocked by admin</source>
<target state="translated">блокиран от админ</target>
<note>blocked chat item</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@@ -6304,9 +6328,9 @@ SimpleX сървърите не могат да видят вашия профи
<target>отменен %@</target>
<note>feature offered item</note>
</trans-unit>
<trans-unit id="changed address for you" xml:space="preserve">
<trans-unit id="changed address for you" xml:space="preserve" approved="no">
<source>changed address for you</source>
<target>променен е адреса за вас</target>
<target state="translated">адреса за изпращане е променен</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="changed role of %@ to %@" xml:space="preserve">
@@ -6399,8 +6423,9 @@ SimpleX сървърите не могат да видят вашия профи
<target>връзка:%@</target>
<note>connection information</note>
</trans-unit>
<trans-unit id="contact %@ changed to %@" xml:space="preserve">
<trans-unit id="contact %@ changed to %@" xml:space="preserve" approved="no">
<source>contact %1$@ changed to %2$@</source>
<target state="translated">името на контакта %1$@ е променено на %2$@</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="contact has e2e encryption" xml:space="preserve">
@@ -6673,8 +6698,9 @@ SimpleX сървърите не могат да видят вашия профи
<target>член</target>
<note>member role</note>
</trans-unit>
<trans-unit id="member %@ changed to %@" xml:space="preserve">
<trans-unit id="member %@ changed to %@" xml:space="preserve" approved="no">
<source>member %1$@ changed to %2$@</source>
<target state="translated">името на члена %1$@ е променено на %2$@</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="member connected" xml:space="preserve">
@@ -6799,12 +6825,14 @@ SimpleX сървърите не могат да видят вашия профи
<target>отстранен %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="removed contact address" xml:space="preserve">
<trans-unit id="removed contact address" xml:space="preserve" approved="no">
<source>removed contact address</source>
<target state="translated">премахнат адрес за контакт</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed profile picture" xml:space="preserve">
<trans-unit id="removed profile picture" xml:space="preserve" approved="no">
<source>removed profile picture</source>
<target state="translated">премахната профилна снимка</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed you" xml:space="preserve">
@@ -6837,12 +6865,14 @@ SimpleX сървърите не могат да видят вашия профи
<target>изпрати лично съобщение</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="set new contact address" xml:space="preserve">
<trans-unit id="set new contact address" xml:space="preserve" approved="no">
<source>set new contact address</source>
<target state="translated">зададен нов адрес за контакт</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="set new profile picture" xml:space="preserve">
<trans-unit id="set new profile picture" xml:space="preserve" approved="no">
<source>set new profile picture</source>
<target state="translated">зададена нова профилна снимка</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="starting…" xml:space="preserve">
@@ -6860,8 +6890,9 @@ SimpleX сървърите не могат да видят вашия профи
<target>този контакт</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="unblocked %@" xml:space="preserve">
<trans-unit id="unblocked %@" xml:space="preserve" approved="no">
<source>unblocked %@</source>
<target state="translated">отблокиран %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
@@ -6869,8 +6900,9 @@ SimpleX сървърите не могат да видят вашия профи
<target>неизвестен</target>
<note>connection info</note>
</trans-unit>
<trans-unit id="unknown status" xml:space="preserve">
<trans-unit id="unknown status" xml:space="preserve" approved="no">
<source>unknown status</source>
<target state="translated">неизвестен статус</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="updated group profile" xml:space="preserve">
@@ -6878,8 +6910,9 @@ SimpleX сървърите не могат да видят вашия профи
<target>актуализиран профил на групата</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="updated profile" xml:space="preserve">
<trans-unit id="updated profile" xml:space="preserve" approved="no">
<source>updated profile</source>
<target state="translated">актуализиран профил</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="v%@" xml:space="preserve">
@@ -6952,18 +6985,19 @@ SimpleX сървърите не могат да видят вашия профи
<target>вие сте наблюдател</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<trans-unit id="you blocked %@" xml:space="preserve" approved="no">
<source>you blocked %@</source>
<target state="translated">вие блокирахте %@</target>
<note>snd group event chat item</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>променихте адреса</target>
<target state="translated">адреса за получаване е променен</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>променихте адреса за %@</target>
<target state="translated">променихте адреса получаване за %@</target>
<note>chat item text</note>
</trans-unit>
<trans-unit id="you changed role for yourself to %@" xml:space="preserve">
@@ -6996,8 +7030,9 @@ SimpleX сървърите не могат да видят вашия профи
<target>споделихте еднократен инкогнито линк за връзка</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="you unblocked %@" xml:space="preserve">
<trans-unit id="you unblocked %@" xml:space="preserve" approved="no">
<source>you unblocked %@</source>
<target state="translated">вие отблокирахте %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">

File diff suppressed because it is too large Load Diff

View File

@@ -6171,9 +6171,9 @@ Puoi annullare questa connessione e rimuovere il contatto (e riprovare più tard
<target>Il tuo profilo</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve">
<trans-unit id="Your profile **%@** will be shared." xml:space="preserve" approved="no">
<source>Your profile **%@** will be shared.</source>
<target>Il tuo profilo **%@** verrà condiviso.</target>
<target state="translated">Verrà condiviso il tuo profilo **%@**.</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">

View File

@@ -4539,9 +4539,9 @@ Fout: %@</target>
<target>Zoekbalk accepteert uitnodigingslinks.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
<trans-unit id="Search or paste SimpleX link" xml:space="preserve" approved="no">
<source>Search or paste SimpleX link</source>
<target>Zoek of plak een SimpleX link</target>
<target state="translated">Zoeken of plak een SimpleX link</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Secure queue" xml:space="preserve">

View File

@@ -212,23 +212,24 @@
<target>%lld üyeler</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages blocked" xml:space="preserve">
<trans-unit id="%lld messages blocked" xml:space="preserve" approved="no">
<source>%lld messages blocked</source>
<target>%lld mesajlar engellendi</target>
<target state="translated">%lld mesaj engellendi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages blocked by admin" xml:space="preserve">
<trans-unit id="%lld messages blocked by admin" xml:space="preserve" approved="no">
<source>%lld messages blocked by admin</source>
<target state="translated">%lld mesaj yönetici tarafından engellendi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages marked deleted" xml:space="preserve">
<trans-unit id="%lld messages marked deleted" xml:space="preserve" approved="no">
<source>%lld messages marked deleted</source>
<target>%lld mesajlar silinmiş olarak işaretlendi</target>
<target state="translated">%lld mesaj silinmiş olarak işaretlendi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld messages moderated by %@" xml:space="preserve">
<trans-unit id="%lld messages moderated by %@" xml:space="preserve" approved="no">
<source>%lld messages moderated by %@</source>
<target>%lld mesajları %@ tarafından yönetildi</target>
<target state="translated">%lld mesaj %@ tarafından yönetildi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="%lld minutes" xml:space="preserve">
@@ -617,9 +618,9 @@
<target>Yöneticiler gruplara katılmak için bağlantılar oluşturabilir.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Advanced network settings" xml:space="preserve">
<trans-unit id="Advanced network settings" xml:space="preserve" approved="no">
<source>Advanced network settings</source>
<target>GGelişmiş ağ ayarları</target>
<target state="translated">Gelişmiş ağ ayarları</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="All app data is deleted." xml:space="preserve">
@@ -642,8 +643,9 @@
<target>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!" xml:space="preserve">
<trans-unit id="All messages will be deleted - this cannot be undone!" xml:space="preserve" approved="no">
<source>All messages will be deleted - this cannot be undone!</source>
<target state="translated">Tüm mesajlar silinecektir - bu geri alınamaz!</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">
@@ -681,8 +683,9 @@
<target>Eğer kişide izin verirse kaybolan mesajlara izin ver.</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. (24 hours)" xml:space="preserve">
<trans-unit id="Allow irreversible message deletion only if your contact allows it to you. (24 hours)" xml:space="preserve" approved="no">
<source>Allow irreversible message deletion only if your contact allows it to you. (24 hours)</source>
<target state="translated">Konuştuğun kişi, kalıcı olarak silinebilen mesajlara izin veriyorsa sen de ver. (24 saat içinde)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow message reactions only if your contact allows them." xml:space="preserve">
@@ -705,8 +708,9 @@
<target>Kendiliğinden yok olan mesajlar göndermeye izin ver.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve">
<trans-unit id="Allow to irreversibly delete sent messages. (24 hours)" xml:space="preserve" approved="no">
<source>Allow to irreversibly delete sent messages. (24 hours)</source>
<target state="translated">Gönderilen mesajların kalıcı olarak silinmesine izin ver. (24 saat içinde)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow to send files and media." xml:space="preserve">
@@ -739,8 +743,9 @@
<target>Kişilerinin seni aramasına izin ver.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve">
<trans-unit id="Allow your contacts to irreversibly delete sent messages. (24 hours)" xml:space="preserve" approved="no">
<source>Allow your contacts to irreversibly delete sent messages. (24 hours)</source>
<target state="translated">Kişilerinin gönderilen mesajları kalıcı olarak silmesine izin ver. (24 saat içinde)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Allow your contacts to send disappearing messages." xml:space="preserve">
@@ -918,8 +923,9 @@
<target>Engelle</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block for all" xml:space="preserve">
<trans-unit id="Block for all" xml:space="preserve" approved="no">
<source>Block for all</source>
<target state="translated">Herkes için engelle</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block group members" xml:space="preserve">
@@ -932,8 +938,9 @@
<target>Üyeyi engelle</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member for all?" xml:space="preserve">
<trans-unit id="Block member for all?" xml:space="preserve" approved="no">
<source>Block member for all?</source>
<target state="translated">Üye herkes için engellensin mi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Block member?" xml:space="preserve">
@@ -941,8 +948,9 @@
<target>Üyeyi engelle?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Blocked by admin" xml:space="preserve">
<trans-unit id="Blocked by admin" xml:space="preserve" approved="no">
<source>Blocked by admin</source>
<target state="translated">Yönetici tarafından engellendi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can add message reactions." xml:space="preserve">
@@ -950,8 +958,9 @@
<target>Sen ve konuştuğun kişi mesaj tepkileri ekleyebilir.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve">
<trans-unit id="Both you and your contact can irreversibly delete sent messages. (24 hours)" xml:space="preserve" approved="no">
<source>Both you and your contact can irreversibly delete sent messages. (24 hours)</source>
<target state="translated">Konuştuğun kişi ve sen mesajları kalıcı olarak silebilirsiniz. (24 saat içinde)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Both you and your contact can make calls." xml:space="preserve">
@@ -1155,8 +1164,9 @@
<target>Sohbet temizlensin mi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear private notes?" xml:space="preserve">
<trans-unit id="Clear private notes?" xml:space="preserve" approved="no">
<source>Clear private notes?</source>
<target state="translated">Gizli notlar temizlensin mi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Clear verification" xml:space="preserve">
@@ -1453,12 +1463,14 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
<target>Profilini oluştur</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Created at" xml:space="preserve">
<trans-unit id="Created at" xml:space="preserve" approved="no">
<source>Created at</source>
<target state="translated">Şurada oluşturuldu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Created at: %@" xml:space="preserve">
<trans-unit id="Created at: %@" xml:space="preserve" approved="no">
<source>Created at: %@</source>
<target state="translated">Şurada oluşturuldu: %@</target>
<note>copied message info</note>
</trans-unit>
<trans-unit id="Created on %@" xml:space="preserve">
@@ -1609,9 +1621,9 @@ Bu senin kendi tek kullanımlık bağlantın!</target>
<target>Sil</target>
<note>chat item action</note>
</trans-unit>
<trans-unit id="Delete %lld messages?" xml:space="preserve">
<trans-unit id="Delete %lld messages?" xml:space="preserve" approved="no">
<source>Delete %lld messages?</source>
<target>%lld mesajları silinsin mi?</target>
<target state="translated">%lld mesaj silinsin mi?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Delete Contact" xml:space="preserve">
@@ -1951,8 +1963,9 @@ Bu geri alınamaz!</target>
<target>Sonra yap</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Do not send history to new members." xml:space="preserve">
<trans-unit id="Do not send history to new members." xml:space="preserve" approved="no">
<source>Do not send history to new members.</source>
<target state="translated">Yeni üyelere geçmişi gönderme.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Don't create address" xml:space="preserve">
@@ -2245,8 +2258,9 @@ Bu geri alınamaz!</target>
<target>Kişi iletişimi oluşturulurken hata oluştu</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating message" xml:space="preserve">
<trans-unit id="Error creating message" xml:space="preserve" approved="no">
<source>Error creating message</source>
<target state="translated">Mesaj oluşturulurken hata</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Error creating profile!" xml:space="preserve">
@@ -2714,8 +2728,9 @@ Bu geri alınamaz!</target>
<target>Grup üyeleri mesaj tepkileri ekleyebilir.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve">
<trans-unit id="Group members can irreversibly delete sent messages. (24 hours)" xml:space="preserve" approved="no">
<source>Group members can irreversibly delete sent messages. (24 hours)</source>
<target state="translated">Grup üyeleri, gönderilen mesajları kalıcı olarak silebilir. (24 saat içinde)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Group members can send direct messages." xml:space="preserve">
@@ -2823,8 +2838,9 @@ Bu geri alınamaz!</target>
<target>Geçmiş</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="History is not sent to new members." xml:space="preserve">
<trans-unit id="History is not sent to new members." xml:space="preserve" approved="no">
<source>History is not sent to new members.</source>
<target state="translated">Yeni üyelere geçmiş gönderilmedi.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="How SimpleX works" xml:space="preserve">
@@ -2917,8 +2933,9 @@ Bu geri alınamaz!</target>
<target>Veritabanını içe aktar</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Improved message delivery" xml:space="preserve">
<trans-unit id="Improved message delivery" xml:space="preserve" approved="no">
<source>Improved message delivery</source>
<target state="translated">İyileştirilmiş mesaj iletimi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Improved privacy and security" xml:space="preserve">
@@ -3033,8 +3050,9 @@ Bu geri alınamaz!</target>
<target>Geçersiz bağlanma bağlantısı</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid display name!" xml:space="preserve">
<trans-unit id="Invalid display name!" xml:space="preserve" approved="no">
<source>Invalid display name!</source>
<target state="translated">Geçersiz görünen ad!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Invalid link" xml:space="preserve">
@@ -3143,8 +3161,9 @@ Bu geri alınamaz!</target>
<target>Gruba katıl</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join group conversations" xml:space="preserve">
<trans-unit id="Join group conversations" xml:space="preserve" approved="no">
<source>Join group conversations</source>
<target state="translated">Grup sohbetlerine katıl</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Join group?" xml:space="preserve">
@@ -3718,8 +3737,9 @@ Bu senin grup için bağlantın %@!</target>
<target>Sadece siz mesaj tepkileri ekleyebilirsiniz.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve">
<trans-unit id="Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)" xml:space="preserve" approved="no">
<source>Only you can irreversibly delete messages (your contact can mark them for deletion). (24 hours)</source>
<target state="translated">Mesajları yalnızca siz geri döndürülemez şekilde silebilirsiniz (kişiniz bunları silinmek üzere işaretleyebilir). (24 saat içinde)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only you can make calls." xml:space="preserve">
@@ -3742,8 +3762,9 @@ Bu senin grup için bağlantın %@!</target>
<target>Sadece karşıdaki kişi mesaj tepkileri ekleyebilir.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve">
<trans-unit id="Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)" xml:space="preserve" approved="no">
<source>Only your contact can irreversibly delete messages (you can mark them for deletion). (24 hours)</source>
<target state="translated">Yalnızca kişiniz mesajları geri alınamaz şekilde silebilir (silinmeleri için işaretleyebilirsiniz). (24 saat içinde)</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Only your contact can make calls." xml:space="preserve">
@@ -3851,8 +3872,9 @@ Bu senin grup için bağlantın %@!</target>
<target>Gösterilecek şifre</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Past member %@" xml:space="preserve">
<trans-unit id="Past member %@" xml:space="preserve" approved="no">
<source>Past member %@</source>
<target state="translated">Geçmiş üye %@</target>
<note>past/unknown group member</note>
</trans-unit>
<trans-unit id="Paste desktop address" xml:space="preserve">
@@ -3865,8 +3887,9 @@ Bu senin grup için bağlantın %@!</target>
<target>Fotoğraf yapıştır</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste link to connect!" xml:space="preserve">
<trans-unit id="Paste link to connect!" xml:space="preserve" approved="no">
<source>Paste link to connect!</source>
<target state="translated">Bağlanmak için bağlantıyı yapıştır!</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Paste the link you received" xml:space="preserve">
@@ -4001,8 +4024,9 @@ Hata: %@</target>
<target>Gizli dosya adları</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Private notes" xml:space="preserve">
<trans-unit id="Private notes" xml:space="preserve" approved="no">
<source>Private notes</source>
<target state="translated">Gizli notlar</target>
<note>name of notes to self</note>
</trans-unit>
<trans-unit id="Profile and server connections" xml:space="preserve">
@@ -4185,8 +4209,9 @@ Hata: %@</target>
<target>Aracılığıyla alınıyor</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve">
<trans-unit id="Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion)." xml:space="preserve" approved="no">
<source>Recent history and improved [directory bot](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex.im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</source>
<target state="translated">Yakın geçmiş ve geliştirilmiş [dizin botu](simplex:/contact#/?v=1-4&amp;smp=smp%3A%2F%2Fu2dS9sG8nMNURyZwqASV4yROM28Er0luVTx5X1CsMrU%3D%40smp4.simplex. im%2FeXSPwqTkKyDO3px4fLf1wx3MvPdjdLW3%23%2F%3Fv%3D1-2%26dh%3DMCowBQYDK2VuAyEAaiv6MkMH44L2TcYrt_CsX3ZvM11WgbMEUn0hkIKTOho%253D%26srv%3Do5vmywmrnaxalvz6wi3zicyftgio6psuvyniis6gco6bp6ekl4cqj4id.onion).</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Recipients see updates as you type them." xml:space="preserve">
@@ -4474,8 +4499,9 @@ Hata: %@</target>
<target>Kaydedilmiş WebRTC ICE sunucuları silinecek</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Saved message" xml:space="preserve">
<trans-unit id="Saved message" xml:space="preserve" approved="no">
<source>Saved message</source>
<target state="translated">Kaydedilmiş mesaj</target>
<note>message info title</note>
</trans-unit>
<trans-unit id="Scan QR code" xml:space="preserve">
@@ -4508,8 +4534,9 @@ Hata: %@</target>
<target>Ara</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Search bar accepts invitation links." xml:space="preserve">
<trans-unit id="Search bar accepts invitation links." xml:space="preserve" approved="no">
<source>Search bar accepts invitation links.</source>
<target state="translated">Arama çubuğu davet bağlantılarını kabul eder.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Search or paste SimpleX link" xml:space="preserve">
@@ -4622,8 +4649,9 @@ Hata: %@</target>
<target>Bunları galeriden veya özel klavyelerden gönder.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Send up to 100 last messages to new members." xml:space="preserve">
<trans-unit id="Send up to 100 last messages to new members." xml:space="preserve" approved="no">
<source>Send up to 100 last messages to new members.</source>
<target state="translated">Yeni üyelere 100 adete kadar son mesajları gönderin.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Sender cancelled file transfer." xml:space="preserve">
@@ -5238,8 +5266,10 @@ Bazı hatalar nedeniyle veya bağlantı tehlikeye girdiğinde meydana gelebilir.
<target>Bu cihazın ismi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve">
<trans-unit id="This display name is invalid. Please choose another name." xml:space="preserve" approved="no">
<source>This display name is invalid. Please choose another name.</source>
<target state="translated">Görünen ad geçerli değil.
Lütfen başka bir ad seç.</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">
@@ -5344,8 +5374,9 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec
<target>Bu kişiden mesaj almak için kullanılan sunucuya bağlanılmaya çalışılıyor.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turkish interface" xml:space="preserve">
<trans-unit id="Turkish interface" xml:space="preserve" approved="no">
<source>Turkish interface</source>
<target state="translated">Türkçe arayüz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Turn off" xml:space="preserve">
@@ -5368,8 +5399,9 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec
<target>Engeli kaldır</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock for all" xml:space="preserve">
<trans-unit id="Unblock for all" xml:space="preserve" approved="no">
<source>Unblock for all</source>
<target state="translated">Herkes için engeli kaldır</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member" xml:space="preserve">
@@ -5377,8 +5409,9 @@ Bu özellik etkinleştirilmeden önce kimlik doğrulamayı tamamlamanız istenec
<target>Üyenin engelini kaldır</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member for all?" xml:space="preserve">
<trans-unit id="Unblock member for all?" xml:space="preserve" approved="no">
<source>Unblock member for all?</source>
<target state="translated">Üyenin engeli herkes için kaldırılsın mı?</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Unblock member?" xml:space="preserve">
@@ -5478,8 +5511,9 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
<target>Okunmamış</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve">
<trans-unit id="Up to 100 last messages are sent to new members." xml:space="preserve" approved="no">
<source>Up to 100 last messages are sent to new members.</source>
<target state="translated">Yeni üyelere 100e kadar en son mesajlar gönderildi.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Update" xml:space="preserve">
@@ -5652,8 +5686,9 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
<target>Güvenlik kodunu görüntüle</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Visible history" xml:space="preserve">
<trans-unit id="Visible history" xml:space="preserve" approved="no">
<source>Visible history</source>
<target state="translated">Görünür geçmiş</target>
<note>chat feature</note>
</trans-unit>
<trans-unit id="Voice messages" xml:space="preserve">
@@ -5741,8 +5776,9 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
<target>Biriyle gizli bir profil paylaştığınızda, bu profil sizi davet ettikleri gruplar için kullanılacaktır.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="With encrypted files and media." xml:space="preserve">
<trans-unit id="With encrypted files and media." xml:space="preserve" approved="no">
<source>With encrypted files and media.</source>
<target state="translated">Şifrelenmiş dosyalar ve medya ile birlikte.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="With optional welcome message." xml:space="preserve">
@@ -5750,8 +5786,9 @@ Bağlanmak için lütfen kişinizden başka bir bağlantı oluşturmasını iste
<target>İsteğe bağlı karşılama mesajı ile.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="With reduced battery usage." xml:space="preserve">
<trans-unit id="With reduced battery usage." xml:space="preserve" approved="no">
<source>With reduced battery usage.</source>
<target state="translated">Azaltılmış pil kullanımı ile birlikte.</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="Wrong database passphrase" xml:space="preserve">
@@ -6257,12 +6294,14 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>engellendi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="blocked %@" xml:space="preserve">
<trans-unit id="blocked %@" xml:space="preserve" approved="no">
<source>blocked %@</source>
<target state="translated">engellendi %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="blocked by admin" xml:space="preserve">
<trans-unit id="blocked by admin" xml:space="preserve" approved="no">
<source>blocked by admin</source>
<target state="translated">yönetici tarafından engellendi</target>
<note>blocked chat item</note>
</trans-unit>
<trans-unit id="bold" xml:space="preserve">
@@ -6385,8 +6424,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>bağlantı:%@</target>
<note>connection information</note>
</trans-unit>
<trans-unit id="contact %@ changed to %@" xml:space="preserve">
<trans-unit id="contact %@ changed to %@" xml:space="preserve" approved="no">
<source>contact %1$@ changed to %2$@</source>
<target state="translated">%1$@ kişisi %2$@ olarak değişti</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="contact has e2e encryption" xml:space="preserve">
@@ -6544,9 +6584,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>hata</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="event happened" xml:space="preserve">
<trans-unit id="event happened" xml:space="preserve" approved="no">
<source>event happened</source>
<target>etkinliği yaşandı</target>
<target state="translated">etkinlik yaşandı</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="group deleted" xml:space="preserve">
@@ -6619,9 +6659,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>davet edildi</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="invited %@" xml:space="preserve">
<trans-unit id="invited %@" xml:space="preserve" approved="no">
<source>invited %@</source>
<target>%@ a davet edildi</target>
<target state="translated">%@ davet edildi</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="invited to connect" xml:space="preserve">
@@ -6659,8 +6699,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>üye</target>
<note>member role</note>
</trans-unit>
<trans-unit id="member %@ changed to %@" xml:space="preserve">
<trans-unit id="member %@ changed to %@" xml:space="preserve" approved="no">
<source>member %1$@ changed to %2$@</source>
<target state="translated">kişi %1$@ , %2$@ olarak değişti</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="member connected" xml:space="preserve">
@@ -6785,12 +6826,14 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>%@ kaldırıldı</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="removed contact address" xml:space="preserve">
<trans-unit id="removed contact address" xml:space="preserve" approved="no">
<source>removed contact address</source>
<target state="translated">kişi adresi silindi</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed profile picture" xml:space="preserve">
<trans-unit id="removed profile picture" xml:space="preserve" approved="no">
<source>removed profile picture</source>
<target state="translated">profil fotoğrafı silindi</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="removed you" xml:space="preserve">
@@ -6823,12 +6866,14 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>doğrudan mesaj gönder</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="set new contact address" xml:space="preserve">
<trans-unit id="set new contact address" xml:space="preserve" approved="no">
<source>set new contact address</source>
<target state="translated">yeni kişi adresi ayarla</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="set new profile picture" xml:space="preserve">
<trans-unit id="set new profile picture" xml:space="preserve" approved="no">
<source>set new profile picture</source>
<target state="translated">yeni profil fotoğrafı ayarla</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="starting…" xml:space="preserve">
@@ -6846,8 +6891,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>Bu kişi</target>
<note>notification title</note>
</trans-unit>
<trans-unit id="unblocked %@" xml:space="preserve">
<trans-unit id="unblocked %@" xml:space="preserve" approved="no">
<source>unblocked %@</source>
<target state="translated">engeli kaldırıldı %@</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="unknown" xml:space="preserve">
@@ -6855,8 +6901,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>bilinmeyen</target>
<note>connection info</note>
</trans-unit>
<trans-unit id="unknown status" xml:space="preserve">
<trans-unit id="unknown status" xml:space="preserve" approved="no">
<source>unknown status</source>
<target state="translated">bilinmeyen durum</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="updated group profile" xml:space="preserve">
@@ -6864,8 +6911,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>grup profili güncellendi</target>
<note>rcv group event chat item</note>
</trans-unit>
<trans-unit id="updated profile" xml:space="preserve">
<trans-unit id="updated profile" xml:space="preserve" approved="no">
<source>updated profile</source>
<target state="translated">güncellenmiş profil</target>
<note>profile update event chat item</note>
</trans-unit>
<trans-unit id="v%@" xml:space="preserve">
@@ -6938,8 +6986,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>gözlemcisiniz</target>
<note>No comment provided by engineer.</note>
</trans-unit>
<trans-unit id="you blocked %@" xml:space="preserve">
<trans-unit id="you blocked %@" xml:space="preserve" approved="no">
<source>you blocked %@</source>
<target state="translated">engelledin %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you changed address" xml:space="preserve">
@@ -6982,8 +7031,9 @@ SimpleX sunucuları profilinizi göremez.</target>
<target>tek kullanımlık link paylaştınız gizli</target>
<note>chat list item description</note>
</trans-unit>
<trans-unit id="you unblocked %@" xml:space="preserve">
<trans-unit id="you unblocked %@" xml:space="preserve" approved="no">
<source>you unblocked %@</source>
<target state="translated">engelini kaldırdın %@</target>
<note>snd group event chat item</note>
</trans-unit>
<trans-unit id="you: " xml:space="preserve">

View File

@@ -29,11 +29,6 @@
5C116CDC27AABE0400E66D01 /* ContactRequestView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C116CDB27AABE0400E66D01 /* ContactRequestView.swift */; };
5C13730B28156D2700F43030 /* ContactConnectionView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C13730A28156D2700F43030 /* ContactConnectionView.swift */; };
5C1A4C1E27A715B700EAD5AD /* ChatItemView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C1A4C1D27A715B700EAD5AD /* ChatItemView.swift */; };
5C29C3AF2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C29C3AA2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk-ghc9.6.3.a */; };
5C29C3B02B783F82003DF84C /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C29C3AB2B783F82003DF84C /* libgmpxx.a */; };
5C29C3B12B783F82003DF84C /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C29C3AC2B783F82003DF84C /* libffi.a */; };
5C29C3B22B783F82003DF84C /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C29C3AD2B783F82003DF84C /* libgmp.a */; };
5C29C3B32B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C29C3AE2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk.a */; };
5C2E260727A2941F00F70299 /* SimpleXAPI.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260627A2941F00F70299 /* SimpleXAPI.swift */; };
5C2E260B27A30CFA00F70299 /* ChatListView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260A27A30CFA00F70299 /* ChatListView.swift */; };
5C2E260F27A30FDC00F70299 /* ChatView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C2E260E27A30FDC00F70299 /* ChatView.swift */; };
@@ -66,6 +61,11 @@
5C7505A527B679EE00BE3227 /* NavLinkPlain.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A427B679EE00BE3227 /* NavLinkPlain.swift */; };
5C7505A827B6D34800BE3227 /* ChatInfoToolbar.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C7505A727B6D34800BE3227 /* ChatInfoToolbar.swift */; };
5C764E89279CBCB3000C6508 /* ChatModel.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C764E88279CBCB3000C6508 /* ChatModel.swift */; };
5C83A1AD2B5EF67D00AE0A4A /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1A82B5EF67D00AE0A4A /* libgmp.a */; };
5C83A1AE2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1A92B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a */; };
5C83A1AF2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1AA2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a */; };
5C83A1B02B5EF67D00AE0A4A /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1AB2B5EF67D00AE0A4A /* libffi.a */; };
5C83A1B12B5EF67D00AE0A4A /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 5C83A1AC2B5EF67D00AE0A4A /* libgmpxx.a */; };
5C8F01CD27A6F0D8007D2C8D /* CodeScanner in Frameworks */ = {isa = PBXBuildFile; productRef = 5C8F01CC27A6F0D8007D2C8D /* CodeScanner */; };
5C93292F29239A170090FFF9 /* ProtocolServersView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C93292E29239A170090FFF9 /* ProtocolServersView.swift */; };
5C93293129239BED0090FFF9 /* ProtocolServerView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 5C93293029239BED0090FFF9 /* ProtocolServerView.swift */; };
@@ -164,11 +164,6 @@
64466DC829FC2B3B00E3D48D /* CreateSimpleXAddress.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64466DC729FC2B3B00E3D48D /* CreateSimpleXAddress.swift */; };
64466DCC29FFE3E800E3D48D /* MailView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 64466DCB29FFE3E800E3D48D /* MailView.swift */; };
6448BBB628FA9D56000D2AB9 /* GroupLinkView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 6448BBB528FA9D56000D2AB9 /* GroupLinkView.swift */; };
6449333A2AF8E51000AC506E /* libgmpxx.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933352AF8E51000AC506E /* libgmpxx.a */; };
6449333B2AF8E51000AC506E /* libgmp.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933362AF8E51000AC506E /* libgmp.a */; };
6449333C2AF8E51000AC506E /* libffi.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933372AF8E51000AC506E /* libffi.a */; };
6449333D2AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933382AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a */; };
6449333E2AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 644933392AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a */; };
644EFFDE292BCD9D00525D5B /* ComposeVoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644EFFDD292BCD9D00525D5B /* ComposeVoiceView.swift */; };
644EFFE0292CFD7F00525D5B /* CIVoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644EFFDF292CFD7F00525D5B /* CIVoiceView.swift */; };
644EFFE2292D089800525D5B /* FramedCIVoiceView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 644EFFE1292D089800525D5B /* FramedCIVoiceView.swift */; };
@@ -283,11 +278,6 @@
5C245F3C2B501E98001CC39F /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/Localizable.strings; sourceTree = "<group>"; };
5C245F3D2B501F13001CC39F /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = "tr.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; };
5C245F3E2B501F13001CC39F /* tr */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = tr; path = tr.lproj/InfoPlist.strings; sourceTree = "<group>"; };
5C29C3AA2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk-ghc9.6.3.a"; sourceTree = "<group>"; };
5C29C3AB2B783F82003DF84C /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5C29C3AC2B783F82003DF84C /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5C29C3AD2B783F82003DF84C /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5C29C3AE2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk.a"; sourceTree = "<group>"; };
5C2E260627A2941F00F70299 /* SimpleXAPI.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SimpleXAPI.swift; sourceTree = "<group>"; };
5C2E260A27A30CFA00F70299 /* ChatListView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatListView.swift; sourceTree = "<group>"; };
5C2E260E27A30FDC00F70299 /* ChatView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatView.swift; sourceTree = "<group>"; };
@@ -335,6 +325,11 @@
5C7505A427B679EE00BE3227 /* NavLinkPlain.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = NavLinkPlain.swift; sourceTree = "<group>"; };
5C7505A727B6D34800BE3227 /* ChatInfoToolbar.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatInfoToolbar.swift; sourceTree = "<group>"; };
5C764E88279CBCB3000C6508 /* ChatModel.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ChatModel.swift; sourceTree = "<group>"; };
5C83A1A82B5EF67D00AE0A4A /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
5C83A1A92B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a"; sourceTree = "<group>"; };
5C83A1AA2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a"; sourceTree = "<group>"; };
5C83A1AB2B5EF67D00AE0A4A /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
5C83A1AC2B5EF67D00AE0A4A /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
5C84FE9129A216C800D95B1A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/Localizable.strings; sourceTree = "<group>"; };
5C84FE9329A2179C00D95B1A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = "nl.lproj/SimpleX--iOS--InfoPlist.strings"; sourceTree = "<group>"; };
5C84FE9429A2179C00D95B1A /* nl */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = nl; path = nl.lproj/InfoPlist.strings; sourceTree = "<group>"; };
@@ -455,11 +450,6 @@
64466DC729FC2B3B00E3D48D /* CreateSimpleXAddress.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CreateSimpleXAddress.swift; sourceTree = "<group>"; };
64466DCB29FFE3E800E3D48D /* MailView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = MailView.swift; sourceTree = "<group>"; };
6448BBB528FA9D56000D2AB9 /* GroupLinkView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = GroupLinkView.swift; sourceTree = "<group>"; };
644933352AF8E51000AC506E /* libgmpxx.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmpxx.a; sourceTree = "<group>"; };
644933362AF8E51000AC506E /* libgmp.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libgmp.a; sourceTree = "<group>"; };
644933372AF8E51000AC506E /* libffi.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = libffi.a; sourceTree = "<group>"; };
644933382AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8-ghc9.6.3.a"; sourceTree = "<group>"; };
644933392AF8E51000AC506E /* libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a */ = {isa = PBXFileReference; lastKnownFileType = archive.ar; path = "libHSsimplex-chat-5.4.0.3-EnhmkSQK6HvJ11g1uZERg8.a"; sourceTree = "<group>"; };
644EFFDD292BCD9D00525D5B /* ComposeVoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = ComposeVoiceView.swift; sourceTree = "<group>"; };
644EFFDF292CFD7F00525D5B /* CIVoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = CIVoiceView.swift; sourceTree = "<group>"; };
644EFFE1292D089800525D5B /* FramedCIVoiceView.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = FramedCIVoiceView.swift; sourceTree = "<group>"; };
@@ -524,13 +514,13 @@
isa = PBXFrameworksBuildPhase;
buildActionMask = 2147483647;
files = (
5C29C3B02B783F82003DF84C /* libgmpxx.a in Frameworks */,
5C29C3B32B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk.a in Frameworks */,
5CE2BA93284534B000EC33A6 /* libiconv.tbd in Frameworks */,
5C83A1B02B5EF67D00AE0A4A /* libffi.a in Frameworks */,
5C83A1AD2B5EF67D00AE0A4A /* libgmp.a in Frameworks */,
5C83A1AE2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a in Frameworks */,
5C83A1AF2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a in Frameworks */,
5CE2BA94284534BB00EC33A6 /* libz.tbd in Frameworks */,
5C29C3B12B783F82003DF84C /* libffi.a in Frameworks */,
5C29C3B22B783F82003DF84C /* libgmp.a in Frameworks */,
5C29C3AF2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk-ghc9.6.3.a in Frameworks */,
5C83A1B12B5EF67D00AE0A4A /* libgmpxx.a in Frameworks */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -592,11 +582,11 @@
5C764E5C279C70B7000C6508 /* Libraries */ = {
isa = PBXGroup;
children = (
5C29C3AC2B783F82003DF84C /* libffi.a */,
5C29C3AD2B783F82003DF84C /* libgmp.a */,
5C29C3AB2B783F82003DF84C /* libgmpxx.a */,
5C29C3AA2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk-ghc9.6.3.a */,
5C29C3AE2B783F82003DF84C /* libHSsimplex-chat-5.5.3.0-AUrnxTuqxo1yzY63w39Bk.a */,
5C83A1AB2B5EF67D00AE0A4A /* libffi.a */,
5C83A1A82B5EF67D00AE0A4A /* libgmp.a */,
5C83A1AC2B5EF67D00AE0A4A /* libgmpxx.a */,
5C83A1A92B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3-ghc9.6.3.a */,
5C83A1AA2B5EF67D00AE0A4A /* libHSsimplex-chat-5.5.0.4-HTW6wkBBAjO2GDtnvnI9O3.a */,
);
path = Libraries;
sourceTree = "<group>";
@@ -1519,7 +1509,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198;
CURRENT_PROJECT_VERSION = 194;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1541,7 +1531,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.5.3;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1562,7 +1552,7 @@
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_ENTITLEMENTS = "SimpleX (iOS).entitlements";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198;
CURRENT_PROJECT_VERSION = 194;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
ENABLE_PREVIEWS = YES;
@@ -1584,7 +1574,7 @@
"$(inherited)",
"@executable_path/Frameworks",
);
MARKETING_VERSION = 5.5.3;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.app;
PRODUCT_NAME = SimpleX;
SDKROOT = iphoneos;
@@ -1643,7 +1633,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198;
CURRENT_PROJECT_VERSION = 194;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1656,7 +1646,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.5.3;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1675,7 +1665,7 @@
CODE_SIGN_ENTITLEMENTS = "SimpleX NSE/SimpleX NSE.entitlements";
CODE_SIGN_IDENTITY = "Apple Development";
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198;
CURRENT_PROJECT_VERSION = 194;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
ENABLE_BITCODE = NO;
GENERATE_INFOPLIST_FILE = YES;
@@ -1688,7 +1678,7 @@
"@executable_path/Frameworks",
"@executable_path/../../Frameworks",
);
MARKETING_VERSION = 5.5.3;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = "chat.simplex.app.SimpleX-NSE";
PRODUCT_NAME = "$(TARGET_NAME)";
PROVISIONING_PROFILE_SPECIFIER = "";
@@ -1707,7 +1697,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198;
CURRENT_PROJECT_VERSION = 194;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1731,7 +1721,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
MARKETING_VERSION = 5.5.3;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;
@@ -1753,7 +1743,7 @@
APPLICATION_EXTENSION_API_ONLY = YES;
CLANG_ENABLE_MODULES = YES;
CODE_SIGN_STYLE = Automatic;
CURRENT_PROJECT_VERSION = 198;
CURRENT_PROJECT_VERSION = 194;
DEFINES_MODULE = YES;
DEVELOPMENT_TEAM = 5NN7GUYB6T;
DYLIB_COMPATIBILITY_VERSION = 1;
@@ -1777,7 +1767,7 @@
"$(inherited)",
"$(PROJECT_DIR)/Libraries/sim",
);
MARKETING_VERSION = 5.5.3;
MARKETING_VERSION = 5.5;
PRODUCT_BUNDLE_IDENTIFIER = chat.simplex.SimpleXChat;
PRODUCT_NAME = "$(TARGET_NAME:c99extidentifier)";
SDKROOT = iphoneos;

View File

@@ -103,14 +103,11 @@
</intent-filter>
</activity-alias>
<activity android:name=".views.call.CallActivity"
<activity android:name=".views.call.IncomingCallActivity"
android:showOnLockScreen="true"
android:exported="false"
android:launchMode="singleInstance"
android:supportsPictureInPicture="true"
android:autoRemoveFromRecents="true"
android:screenOrientation="portrait"
android:configChanges="screenSize|smallestScreenSize|screenLayout|orientation"/>
android:launchMode="singleTask"/>
<provider
android:name="androidx.core.content.FileProvider"
@@ -136,18 +133,6 @@
android:stopWithTask="false"></service>
<!-- SimplexService restart on reboot -->
<service
android:name=".CallService"
android:enabled="true"
android:exported="false"
android:stopWithTask="false"/>
<receiver
android:name=".CallService$CallActionReceiver"
android:enabled="true"
android:exported="false" />
<receiver
android:name=".SimplexService$StartReceiver"
android:enabled="true"

View File

@@ -1,176 +0,0 @@
package chat.simplex.app
import android.app.*
import android.content.*
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.os.*
import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import chat.simplex.app.model.NtfManager.EndCallAction
import chat.simplex.app.views.call.CallActivity
import chat.simplex.common.model.NotificationPreviewMode
import chat.simplex.common.platform.*
import chat.simplex.common.views.call.CallState
import chat.simplex.common.views.helpers.*
import chat.simplex.res.MR
import kotlinx.datetime.Instant
class CallService: Service() {
private var wakeLock: PowerManager.WakeLock? = null
private var notificationManager: NotificationManager? = null
private var serviceNotification: Notification? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "onStartCommand startId: $startId")
if (intent != null) {
val action = intent.action
Log.d(TAG, "intent action $action")
when (action) {
Action.START.name -> startService()
else -> Log.e(TAG, "No action in the intent")
}
} else {
Log.d(TAG, "null intent. Probably restarted by the system.")
}
startForeground(CALL_SERVICE_ID, serviceNotification)
return START_STICKY
}
override fun onCreate() {
super.onCreate()
Log.d(TAG, "Call service created")
notificationManager = createNotificationChannel()
updateNotification()
startForeground(CALL_SERVICE_ID, serviceNotification)
}
override fun onDestroy() {
Log.d(TAG, "Call service destroyed")
try {
wakeLock?.let {
while (it.isHeld) it.release() // release all, in case acquired more than once
}
wakeLock = null
} catch (e: Exception) {
Log.d(TAG, "Exception while releasing wakelock: ${e.message}")
}
super.onDestroy()
}
private fun startService() {
Log.d(TAG, "CallService startService")
if (wakeLock != null) return
wakeLock = (getSystemService(Context.POWER_SERVICE) as PowerManager).run {
newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, WAKE_LOCK_TAG).apply {
acquire()
}
}
}
fun updateNotification() {
val call = chatModel.activeCall.value
val previewMode = appPreferences.notificationPreviewMode.get()
val title = if (previewMode == NotificationPreviewMode.HIDDEN.name)
generalGetString(MR.strings.notification_preview_somebody)
else
call?.contact?.profile?.displayName ?: ""
val text = generalGetString(if (call?.supportsVideo() == true) MR.strings.call_service_notification_video_call else MR.strings.call_service_notification_audio_call)
val image = call?.contact?.image
val largeIcon = if (image == null || previewMode == NotificationPreviewMode.HIDDEN.name)
BitmapFactory.decodeResource(resources, R.drawable.icon)
else
base64ToBitmap(image).asAndroidBitmap()
serviceNotification = createNotification(title, text, largeIcon, call?.connectedAt)
startForeground(CALL_SERVICE_ID, serviceNotification)
}
private fun createNotificationChannel(): NotificationManager? {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val channel = NotificationChannel(CALL_NOTIFICATION_CHANNEL_ID, CALL_NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT)
notificationManager.createNotificationChannel(channel)
return notificationManager
}
return null
}
private fun createNotification(title: String, text: String, icon: Bitmap, connectedAt: Instant? = null): Notification {
val pendingIntent: PendingIntent = Intent(this, CallActivity::class.java).let { notificationIntent ->
PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE)
}
val endCallPendingIntent: PendingIntent = Intent(this, CallActionReceiver::class.java).let { notificationIntent ->
notificationIntent.setAction(EndCallAction)
PendingIntent.getBroadcast(this, 1, notificationIntent, PendingIntent.FLAG_CANCEL_CURRENT or PendingIntent.FLAG_IMMUTABLE)
}
val builder = NotificationCompat.Builder(this, CALL_NOTIFICATION_CHANNEL_ID)
.setSmallIcon(R.drawable.ntf_icon)
.setLargeIcon(icon.clipToCircle())
.setColor(0x88FFFF)
.setContentTitle(title)
.setContentText(text)
.setContentIntent(pendingIntent)
.setSilent(true)
.addAction(R.drawable.ntf_icon, generalGetString(MR.strings.call_service_notification_end_call), endCallPendingIntent)
if (connectedAt != null) {
builder.setUsesChronometer(true)
builder.setWhen(connectedAt.epochSeconds * 1000)
}
return builder.build()
}
override fun onBind(intent: Intent): IBinder {
return CallServiceBinder()
}
inner class CallServiceBinder : Binder() {
fun getService() = this@CallService
}
enum class Action {
START,
}
class CallActionReceiver: BroadcastReceiver() {
override fun onReceive(context: Context?, intent: Intent?) {
when (intent?.action) {
EndCallAction -> {
val call = chatModel.activeCall.value
if (call != null) {
withBGApi {
chatModel.callManager.endCall(call)
}
}
}
else -> {
Log.e(TAG, "Unknown action. Make sure you provided an action")
}
}
}
}
companion object {
const val TAG = "CALL_SERVICE"
const val CALL_NOTIFICATION_CHANNEL_ID = "chat.simplex.app.CALL_SERVICE_NOTIFICATION"
const val CALL_NOTIFICATION_CHANNEL_NAME = "SimpleX Chat call service"
const val CALL_SERVICE_ID = 6788
const val WAKE_LOCK_TAG = "CallService::lock"
fun startService(): Intent {
Log.d(TAG, "CallService start")
return Intent(androidAppContext, CallService::class.java).also {
it.action = Action.START.name
ContextCompat.startForegroundService(androidAppContext, it)
}
}
fun stopService() {
androidAppContext.stopService(Intent(androidAppContext, CallService::class.java))
}
}
}

View File

@@ -1,15 +1,14 @@
package chat.simplex.app
import android.app.*
import android.app.Application
import android.content.Context
import androidx.compose.ui.platform.ClipboardManager
import chat.simplex.common.platform.Log
import android.content.Intent
import android.app.UiModeManager
import android.os.*
import androidx.lifecycle.*
import androidx.work.*
import chat.simplex.app.model.NtfManager
import chat.simplex.app.model.NtfManager.AcceptCallAction
import chat.simplex.app.views.call.CallActivity
import chat.simplex.common.helpers.APPLICATION_ID
import chat.simplex.common.helpers.requiresIgnoringBattery
import chat.simplex.common.model.*
@@ -19,7 +18,6 @@ import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.CurrentColors
import chat.simplex.common.ui.theme.DefaultTheme
import chat.simplex.common.views.call.RcvCallInvitation
import chat.simplex.common.views.call.activeCallDestroyWebView
import chat.simplex.common.views.helpers.*
import chat.simplex.common.views.onboarding.OnboardingStage
import com.jakewharton.processphoenix.ProcessPhoenix
@@ -186,10 +184,6 @@ class SimplexApp: Application(), LifecycleEventObserver {
SimplexService.safeStopService()
}
override fun androidCallServiceSafeStop() {
CallService.stopService()
}
override fun androidNotificationsModeChanged(mode: NotificationsMode) {
if (mode.requiresIgnoringBattery && !SimplexService.isBackgroundAllowed()) {
appPrefs.backgroundServiceNoticeShown.set(false)
@@ -260,28 +254,6 @@ class SimplexApp: Application(), LifecycleEventObserver {
uiModeManager.setApplicationNightMode(mode)
}
override fun androidStartCallActivity(acceptCall: Boolean, remoteHostId: Long?, chatId: ChatId?) {
val context = mainActivity.get() ?: return
val intent = Intent(context, CallActivity::class.java)
.addFlags(Intent.FLAG_ACTIVITY_NO_ANIMATION)
if (acceptCall) {
intent.setAction(AcceptCallAction)
.putExtra("remoteHostId", remoteHostId)
.putExtra("chatId", chatId)
}
intent.flags += Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
context.startActivity(intent)
}
override fun androidPictureInPictureAllowed(): Boolean {
val appOps = androidAppContext.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
return appOps.checkOpNoThrow(AppOpsManager.OPSTR_PICTURE_IN_PICTURE, Process.myUid(), packageName) == AppOpsManager.MODE_ALLOWED
}
override fun androidCallEnded() {
activeCallDestroyWebView()
}
override suspend fun androidAskToAllowBackgroundCalls(): Boolean {
if (SimplexService.isBackgroundRestricted()) {
val userChoice: CompletableDeferred<Boolean> = CompletableDeferred()

View File

@@ -34,13 +34,12 @@ import kotlin.system.exitProcess
class SimplexService: Service() {
private var wakeLock: PowerManager.WakeLock? = null
private var isCheckingNewMessages = false
private var isStartingService = false
private var notificationManager: NotificationManager? = null
private var serviceNotification: Notification? = null
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "onStartCommand startId: $startId")
isServiceStarting = false
if (intent != null) {
val action = intent.action
Log.d(TAG, "intent action $action")
@@ -72,7 +71,6 @@ class SimplexService: Service() {
stopForeground(true)
stopSelf()
} else {
isServiceStarting = false
isServiceStarted = true
// In case of self-destruct is enabled the initialization process will not start in SimplexApp, Let's start it here
if (DatabaseUtils.ksSelfDestructPassword.get() != null && chatModel.chatDbStatus.value == null) {
@@ -91,7 +89,6 @@ class SimplexService: Service() {
} catch (e: Exception) {
Log.d(TAG, "Exception while releasing wakelock: ${e.message}")
}
isServiceStarting = false
isServiceStarted = false
stopAfterStart = false
saveServiceState(this, ServiceState.STOPPED)
@@ -104,9 +101,9 @@ class SimplexService: Service() {
private fun startService() {
Log.d(TAG, "SimplexService startService")
if (wakeLock != null || isCheckingNewMessages) return
if (wakeLock != null || isStartingService) return
val self = this
isCheckingNewMessages = true
isStartingService = true
withLongRunningApi {
val chatController = ChatController
waitDbMigrationEnds(chatController)
@@ -126,7 +123,7 @@ class SimplexService: Service() {
}
}
} finally {
isCheckingNewMessages = false
isStartingService = false
}
}
}
@@ -265,7 +262,6 @@ class SimplexService: Service() {
private const val SHARED_PREFS_SERVICE_STATE = "SIMPLEX_SERVICE_STATE"
private const val WORK_NAME_ONCE = "ServiceStartWorkerOnce"
var isServiceStarting = false
var isServiceStarted = false
private var stopAfterStart = false
@@ -285,7 +281,7 @@ class SimplexService: Service() {
fun safeStopService() {
if (isServiceStarted) {
androidAppContext.stopService(Intent(androidAppContext, SimplexService::class.java))
} else if (isServiceStarting) {
} else {
stopAfterStart = true
}
}
@@ -295,7 +291,6 @@ class SimplexService: Service() {
withContext(Dispatchers.IO) {
Intent(androidAppContext, SimplexService::class.java).also {
it.action = action.name
isServiceStarting = true
ContextCompat.startForegroundService(androidAppContext, it)
}
}

View File

@@ -13,7 +13,7 @@ import androidx.compose.ui.graphics.asAndroidBitmap
import androidx.core.app.*
import chat.simplex.app.*
import chat.simplex.app.TAG
import chat.simplex.app.views.call.CallActivity
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.*
@@ -33,7 +33,6 @@ object NtfManager {
const val CallChannel: String = "chat.simplex.app.CALL_NOTIFICATION_2"
const val AcceptCallAction: String = "chat.simplex.app.ACCEPT_CALL"
const val RejectCallAction: String = "chat.simplex.app.REJECT_CALL"
const val EndCallAction: String = "chat.simplex.app.END_CALL"
const val CallNotificationId: Int = -1
private const val UserIdKey: String = "userId"
private const val ChatIdKey: String = "chatId"
@@ -158,7 +157,7 @@ object NtfManager {
val screenOff = displayManager.displays.all { it.state != Display.STATE_ON }
var ntfBuilder =
if ((keyguardManager.isKeyguardLocked || screenOff) && appPreferences.callOnLockScreen.get() != CallOnLockScreen.DISABLE) {
val fullScreenIntent = Intent(context, CallActivity::class.java)
val fullScreenIntent = Intent(context, IncomingCallActivity::class.java)
val fullScreenPendingIntent = PendingIntent.getActivity(context, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
NotificationCompat.Builder(context, CallChannel)
.setFullScreenIntent(fullScreenPendingIntent, true)

View File

@@ -1,18 +1,17 @@
package chat.simplex.app.views.call
import android.app.*
import android.content.*
import android.content.res.Configuration
import android.graphics.Rect
import android.os.*
import android.util.Rational
import android.view.*
import android.app.Activity
import android.app.KeyguardManager
import android.content.Context
import android.content.Intent
import android.os.Build
import android.os.Bundle
import chat.simplex.common.platform.Log
import android.view.WindowManager
import androidx.activity.ComponentActivity
import androidx.activity.compose.setContent
import androidx.activity.trackPipAnimationHintView
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.*
@@ -23,115 +22,33 @@ 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 androidx.compose.ui.platform.LocalView
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.lifecycle.Lifecycle
import chat.simplex.app.*
import chat.simplex.app.R
import chat.simplex.app.TAG
import chat.simplex.app.model.NtfManager
import chat.simplex.app.model.NtfManager.AcceptCallAction
import chat.simplex.common.model.*
import chat.simplex.common.platform.*
import chat.simplex.app.model.NtfManager.OpenChatAction
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.coroutines.launch
import kotlinx.datetime.Clock
import java.lang.ref.WeakReference
import chat.simplex.common.platform.chatModel as m
class CallActivity: ComponentActivity(), ServiceConnection {
var boundService: CallService? = null
class IncomingCallActivity: ComponentActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
callActivity = WeakReference(this)
when (intent?.action) {
AcceptCallAction -> {
val remoteHostId = intent.getLongExtra("remoteHostId", -1).takeIf { it != -1L }
val chatId = intent.getStringExtra("chatId")
val invitation = (m.callInvitations.values + m.activeCallInvitation.value).lastOrNull {
it?.remoteHostId == remoteHostId && it?.contact?.id == chatId
}
if (invitation != null) {
m.callManager.acceptIncomingCall(invitation = invitation)
}
}
}
setContent { CallActivityView() }
if (isOnLockScreenNow()) {
unlockForIncomingCall()
}
setContent { IncomingCallActivityView(ChatModel) }
unlockForIncomingCall()
}
override fun onDestroy() {
super.onDestroy()
if (isOnLockScreenNow()) {
lockAfterIncomingCall()
}
try {
unbindService(this)
} catch (e: Exception) {
Log.i(TAG, "Unable to unbind service: " + e.stackTraceToString())
}
}
private fun isOnLockScreenNow() = getKeyguardManager(this).isKeyguardLocked
fun setPipParams(video: Boolean, sourceRectHint: Rect? = null, viewRatio: Rational? = null) {
// By manually specifying source rect we exclude empty background while toggling PiP
val builder = PictureInPictureParams.Builder()
.setAspectRatio(viewRatio)
.setSourceRectHint(sourceRectHint)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
builder.setAutoEnterEnabled(video)
}
setPictureInPictureParams(builder.build())
}
override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, newConfig: Configuration) {
super.onPictureInPictureModeChanged(isInPictureInPictureMode, newConfig)
m.activeCallViewIsCollapsed.value = isInPictureInPictureMode
val layoutType = if (!isInPictureInPictureMode) {
LayoutType.Default
} else {
LayoutType.RemoteVideo
}
m.callCommand.add(WCallCommand.Layout(layoutType))
}
override fun onBackPressed() {
if (isOnLockScreenNow()) {
super.onBackPressed()
} else {
m.activeCallViewIsCollapsed.value = true
}
}
override fun onPictureInPictureRequested(): Boolean {
Log.d(TAG, "Requested picture-in-picture from the system")
return super.onPictureInPictureRequested()
}
override fun onUserLeaveHint() {
// On Android 12+ PiP is enabled automatically when a user hides the app
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.R && callSupportsVideo() && platform.androidPictureInPictureAllowed()) {
enterPictureInPictureMode()
}
}
override fun onResume() {
super.onResume()
m.activeCallViewIsCollapsed.value = false
lockAfterIncomingCall()
}
private fun unlockForIncomingCall() {
@@ -155,23 +72,6 @@ class CallActivity: ComponentActivity(), ServiceConnection {
}
}
fun startServiceAndBind() {
/**
* On Android 12 there is a bug that prevents starting activity after pressing back button
* (the error says that it denies to start activity in background).
* Workaround is to bind to a service
* */
bindService(CallService.startService(), this, 0)
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
boundService = (service as CallService.CallServiceBinder).getService()
}
override fun onServiceDisconnected(name: ComponentName?) {
boundService = null
}
companion object {
const val activityFlags = WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
}
@@ -180,96 +80,38 @@ class CallActivity: ComponentActivity(), ServiceConnection {
fun getKeyguardManager(context: Context): KeyguardManager =
context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
private fun callSupportsVideo() = m.activeCall.value?.supportsVideo() == true || m.activeCallInvitation.value?.callType?.media == CallMediaType.Video
@Composable
fun CallActivityView() {
fun IncomingCallActivityView(m: ChatModel) {
val switchingCall = m.switchingCall.value
val invitation = m.activeCallInvitation.value
val call = remember { m.activeCall }.value
val call = m.activeCall.value
val showCallView = m.showCallView.value
val activity = LocalContext.current as CallActivity
LaunchedEffect(Unit) {
snapshotFlow { m.activeCallViewIsCollapsed.value }
.collect { collapsed ->
when {
collapsed -> {
if (!platform.androidPictureInPictureAllowed() || !callSupportsVideo()) {
activity.moveTaskToBack(true)
activity.startActivity(Intent(activity, MainActivity::class.java))
} else if (!activity.isInPictureInPictureMode && activity.lifecycle.currentState == Lifecycle.State.RESUMED) {
// User pressed back button, show MainActivity
activity.startActivity(Intent(activity, MainActivity::class.java))
activity.enterPictureInPictureMode()
}
}
callSupportsVideo() && !platform.androidPictureInPictureAllowed() -> {
// PiP disabled by user
platform.androidStartCallActivity(false)
}
activity.isInPictureInPictureMode -> {
platform.androidStartCallActivity(false)
}
}
}
}
SimpleXTheme {
var prevCall by remember { mutableStateOf(call) }
KeyChangeEffect(m.activeCall.value) {
if (m.activeCall.value != null) {
prevCall = m.activeCall.value
activity.boundService?.updateNotification()
}
}
Box(Modifier.background(Color.Black)) {
if (call != null) {
val view = LocalView.current
ActiveCallView()
if (callSupportsVideo()) {
val scope = rememberCoroutineScope()
LaunchedEffect(Unit) {
scope.launch {
activity.setPipParams(callSupportsVideo(), viewRatio = Rational(view.width, view.height))
activity.trackPipAnimationHintView(view)
}
}
}
} else if (prevCall != null) {
prevCall?.let { ActiveCallOverlayDisabled(it) }
}
if (invitation != null) {
if (call == null) {
Surface(
Modifier
.fillMaxSize(),
color = MaterialTheme.colors.background,
contentColor = LocalContentColor.current
) {
IncomingCallLockScreenAlert(invitation, m)
}
} else {
IncomingCallAlertView(invitation, m)
}
}
}
}
LaunchedEffect(call == null) {
if (call != null) {
activity.startServiceAndBind()
}
}
val activity = LocalContext.current as Activity
LaunchedEffect(invitation, call, switchingCall, showCallView) {
if (!switchingCall && invitation == null && (!showCallView || call == null)) {
Log.d(TAG, "CallActivityView: finishing activity")
Log.d(TAG, "IncomingCallActivityView: finishing activity")
activity.finish()
}
}
SimpleXTheme {
Surface(
Modifier
.fillMaxSize(),
color = MaterialTheme.colors.background,
contentColor = LocalContentColor.current
) {
if (showCallView) {
Box {
ActiveCallView()
if (invitation != null) IncomingCallAlertView(invitation, m)
}
} else if (invitation != null) {
IncomingCallLockScreenAlert(invitation, m)
}
}
}
}
/**
* Related to lockscreen
* */
@Composable
fun IncomingCallLockScreenAlert(invitation: RcvCallInvitation, chatModel: ChatModel) {
val cm = chatModel.callManager
@@ -293,7 +135,7 @@ fun IncomingCallLockScreenAlert(invitation: RcvCallInvitation, chatModel: ChatMo
acceptCall = { cm.acceptIncomingCall(invitation = invitation) },
openApp = {
val intent = Intent(context, MainActivity::class.java)
.setAction(NtfManager.OpenChatAction)
.setAction(OpenChatAction)
.putExtra("userId", invitation.user.userId)
.putExtra("chatId", invitation.contact.id)
context.startActivity(intent)

View File

@@ -4,7 +4,6 @@ import android.annotation.SuppressLint
import android.content.Context
import android.net.LocalServerSocket
import android.util.Log
import androidx.activity.ComponentActivity
import androidx.fragment.app.FragmentActivity
import chat.simplex.common.*
import chat.simplex.common.platform.*
@@ -26,8 +25,7 @@ val defaultLocale: Locale = Locale.getDefault()
@SuppressLint("StaticFieldLeak")
lateinit var androidAppContext: Context
var mainActivity: WeakReference<FragmentActivity> = WeakReference(null)
var callActivity: WeakReference<ComponentActivity> = WeakReference(null)
lateinit var mainActivity: WeakReference<FragmentActivity>
fun initHaskell() {
val socketName = "chat.simplex.app.local.socket.address.listen.native.cmd2" + Random.nextLong(100000)

View File

@@ -61,16 +61,6 @@ actual fun cropToSquare(image: ImageBitmap): ImageBitmap {
return Bitmap.createBitmap(image.asAndroidBitmap(), xOffset, yOffset, side, side).asImageBitmap()
}
fun Bitmap.clipToCircle(): Bitmap {
val circle = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888)
val path = android.graphics.Path()
path.addCircle(width / 2f, height / 2f, min(width, height) / 2f, android.graphics.Path.Direction.CCW)
val canvas = android.graphics.Canvas(circle)
canvas.clipPath(path)
canvas.drawBitmap(this, 0f, 0f, null)
return circle
}
actual fun compressImageStr(bitmap: ImageBitmap): String {
val usePng = bitmap.hasAlpha()
val ext = if (usePng) "png" else "jpg"

View File

@@ -28,7 +28,6 @@ import androidx.compose.ui.platform.LocalLifecycleOwner
import dev.icerock.moko.resources.compose.painterResource
import dev.icerock.moko.resources.compose.stringResource
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidView
import androidx.lifecycle.Lifecycle
@@ -51,30 +50,20 @@ import kotlinx.datetime.Clock
import kotlinx.serialization.decodeFromString
import kotlinx.serialization.encodeToString
// Should be destroy()'ed and set as null when call is ended. Otherwise, it will be a leak
@SuppressLint("StaticFieldLeak")
private var staticWebView: WebView? = null
// WebView methods must be called on Main thread
fun activeCallDestroyWebView() = withApi {
// Stop it when call ended
platform.androidCallServiceSafeStop()
staticWebView?.destroy()
staticWebView = null
Log.d(TAG, "CallView: webview was destroyed")
}
@SuppressLint("SourceLockedOrientationActivity")
@Composable
actual fun ActiveCallView() {
val chatModel = ChatModel
BackHandler(onBack = {
val call = chatModel.activeCall.value
if (call != null) withBGApi { chatModel.callManager.endCall(call) }
})
val audioViaBluetooth = rememberSaveable { mutableStateOf(false) }
val proximityLock = remember {
val pm = (androidAppContext.getSystemService(Context.POWER_SERVICE) as PowerManager)
if (pm.isWakeLockLevelSupported(PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
pm.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, androidAppContext.packageName + ":proximityLock")
} else {
null
}
val ntfModeService = remember { chatModel.controller.appPrefs.notificationsMode.get() == NotificationsMode.SERVICE }
LaunchedEffect(Unit) {
// Start service when call happening since it's not already started.
// It's needed to prevent Android from shutting down a microphone after a minute or so when screen is off
if (!ntfModeService) platform.androidServiceStart()
}
DisposableEffect(Unit) {
val am = androidAppContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
@@ -104,24 +93,22 @@ actual fun ActiveCallView() {
}
}
am.registerAudioDeviceCallback(audioCallback, null)
val pm = (androidAppContext.getSystemService(Context.POWER_SERVICE) as PowerManager)
val proximityLock = if (pm.isWakeLockLevelSupported(PROXIMITY_SCREEN_OFF_WAKE_LOCK)) {
pm.newWakeLock(PROXIMITY_SCREEN_OFF_WAKE_LOCK, androidAppContext.packageName + ":proximityLock")
} else {
null
}
proximityLock?.acquire()
onDispose {
// Stop it when call ended
if (!ntfModeService) platform.androidServiceSafeStop()
dropAudioManagerOverrides()
am.unregisterAudioDeviceCallback(audioCallback)
if (proximityLock?.isHeld == true) {
proximityLock.release()
}
}
}
LaunchedEffect(chatModel.activeCallViewIsCollapsed.value) {
if (chatModel.activeCallViewIsCollapsed.value) {
if (proximityLock?.isHeld == true) proximityLock.release()
} else {
delay(1000)
if (proximityLock?.isHeld == false) proximityLock.acquire()
proximityLock?.release()
}
}
val scope = rememberCoroutineScope()
val call = chatModel.activeCall.value
Box(Modifier.fillMaxSize()) {
WebRTCView(chatModel.callCommand) { apiMsg ->
Log.d(TAG, "received from WebRTCView: $apiMsg")
@@ -133,15 +120,15 @@ actual fun ActiveCallView() {
is WCallResponse.Capabilities -> withBGApi {
val callType = CallType(call.localMedia, r.capabilities)
chatModel.controller.apiSendCallInvitation(callRh, call.contact, callType)
updateActiveCall(call) { it.copy(callState = CallState.InvitationSent, localCapabilities = r.capabilities) }
chatModel.activeCall.value = call.copy(callState = CallState.InvitationSent, localCapabilities = r.capabilities)
}
is WCallResponse.Offer -> withBGApi {
chatModel.controller.apiSendCallOffer(callRh, call.contact, r.offer, r.iceCandidates, call.localMedia, r.capabilities)
updateActiveCall(call) { it.copy(callState = CallState.OfferSent, localCapabilities = r.capabilities) }
chatModel.activeCall.value = call.copy(callState = CallState.OfferSent, localCapabilities = r.capabilities)
}
is WCallResponse.Answer -> withBGApi {
chatModel.controller.apiSendCallAnswer(callRh, call.contact, r.answer, r.iceCandidates)
updateActiveCall(call) { it.copy(callState = CallState.Negotiated) }
chatModel.activeCall.value = call.copy(callState = CallState.Negotiated)
}
is WCallResponse.Ice -> withBGApi {
chatModel.controller.apiSendCallExtraInfo(callRh, call.contact, r.iceCandidates)
@@ -150,7 +137,7 @@ actual fun ActiveCallView() {
try {
val callStatus = json.decodeFromString<WebRTCCallStatus>("\"${r.state.connectionState}\"")
if (callStatus == WebRTCCallStatus.Connected) {
updateActiveCall(call) { it.copy(callState = CallState.Connected, connectedAt = Clock.System.now()) }
chatModel.activeCall.value = call.copy(callState = CallState.Connected, connectedAt = Clock.System.now())
setCallSound(call.soundSpeaker, audioViaBluetooth)
}
withBGApi { chatModel.controller.apiCallStatus(callRh, call.contact, callStatus) }
@@ -158,7 +145,7 @@ actual fun ActiveCallView() {
Log.d(TAG,"call status ${r.state.connectionState} not used")
}
is WCallResponse.Connected -> {
updateActiveCall(call) { it.copy(callState = CallState.Connected, connectionInfo = r.connectionInfo) }
chatModel.activeCall.value = call.copy(callState = CallState.Connected, connectionInfo = r.connectionInfo)
scope.launch {
setCallSound(call.soundSpeaker, audioViaBluetooth)
}
@@ -167,29 +154,27 @@ actual fun ActiveCallView() {
withBGApi { chatModel.callManager.endCall(call) }
}
is WCallResponse.Ended -> {
updateActiveCall(call) { it.copy(callState = CallState.Ended) }
chatModel.activeCall.value = call.copy(callState = CallState.Ended)
withBGApi { chatModel.callManager.endCall(call) }
chatModel.showCallView.value = false
}
is WCallResponse.Ok -> when (val cmd = apiMsg.command) {
is WCallCommand.Answer ->
updateActiveCall(call) { it.copy(callState = CallState.Negotiated) }
chatModel.activeCall.value = call.copy(callState = CallState.Negotiated)
is WCallCommand.Media -> {
updateActiveCall(call) {
when (cmd.media) {
CallMediaType.Video -> it.copy(videoEnabled = cmd.enable)
CallMediaType.Audio -> it.copy(audioEnabled = cmd.enable)
}
when (cmd.media) {
CallMediaType.Video -> chatModel.activeCall.value = call.copy(videoEnabled = cmd.enable)
CallMediaType.Audio -> chatModel.activeCall.value = call.copy(audioEnabled = cmd.enable)
}
}
is WCallCommand.Camera -> {
updateActiveCall(call) { it.copy(localCamera = cmd.camera) }
chatModel.activeCall.value = call.copy(localCamera = cmd.camera)
if (!call.audioEnabled) {
chatModel.callCommand.add(WCallCommand.Media(CallMediaType.Audio, enable = false))
}
}
is WCallCommand.End -> {
withBGApi { chatModel.callManager.endCall(call) }
}
is WCallCommand.End ->
chatModel.showCallView.value = false
else -> {}
}
is WCallResponse.Error -> {
@@ -198,16 +183,8 @@ actual fun ActiveCallView() {
}
}
}
val showOverlay = when {
call == null -> false
!platform.androidPictureInPictureAllowed() -> true
!call.supportsVideo() -> true
!chatModel.activeCallViewIsCollapsed.value -> true
else -> false
}
if (call != null && showOverlay) {
ActiveCallOverlay(call, chatModel, audioViaBluetooth)
}
val call = chatModel.activeCall.value
if (call != null) ActiveCallOverlay(call, chatModel, audioViaBluetooth)
}
val context = LocalContext.current
@@ -252,20 +229,6 @@ private fun ActiveCallOverlay(call: Call, chatModel: ChatModel, audioViaBluetoot
)
}
@Composable
fun ActiveCallOverlayDisabled(call: Call) {
ActiveCallOverlayLayout(
call = call,
speakerCanBeEnabled = false,
enabled = false,
dismiss = {},
toggleAudio = {},
toggleVideo = {},
toggleSound = {},
flipCamera = {}
)
}
private fun setCallSound(speaker: Boolean, audioViaBluetooth: MutableState<Boolean>) {
val am = androidAppContext.getSystemService(Context.AUDIO_SERVICE) as AudioManager
Log.d(TAG, "setCallSound: set audio mode, speaker enabled: $speaker")
@@ -308,69 +271,59 @@ private fun dropAudioManagerOverrides() {
private fun ActiveCallOverlayLayout(
call: Call,
speakerCanBeEnabled: Boolean,
enabled: Boolean = true,
dismiss: () -> Unit,
toggleAudio: () -> Unit,
toggleVideo: () -> Unit,
toggleSound: () -> Unit,
flipCamera: () -> Unit
) {
Column {
val media = call.peerMedia ?: call.localMedia
CloseSheetBar({ chatModel.activeCallViewIsCollapsed.value = true }, true, tintColor = Color(0xFFFFFFD8)) {
if (media == CallMediaType.Video) {
Text(call.contact.chatViewName, Modifier.fillMaxWidth().padding(end = DEFAULT_PADDING), color = Color(0xFFFFFFD8), style = MaterialTheme.typography.h2, overflow = TextOverflow.Ellipsis, maxLines = 1)
}
}
Column(Modifier.padding(horizontal = DEFAULT_PADDING)) {
when (media) {
CallMediaType.Video -> {
VideoCallInfoView(call)
Box(Modifier.fillMaxWidth().fillMaxHeight().weight(1f), contentAlignment = Alignment.BottomCenter) {
DisabledBackgroundCallsButton()
Column(Modifier.padding(DEFAULT_PADDING)) {
when (call.peerMedia ?: call.localMedia) {
CallMediaType.Video -> {
CallInfoView(call, alignment = Alignment.Start)
Box(Modifier.fillMaxWidth().fillMaxHeight().weight(1f), contentAlignment = Alignment.BottomCenter) {
DisabledBackgroundCallsButton()
}
Row(Modifier.fillMaxWidth().padding(horizontal = 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
ToggleAudioButton(call, toggleAudio)
Spacer(Modifier.size(40.dp))
IconButton(onClick = dismiss) {
Icon(painterResource(MR.images.ic_call_end_filled), stringResource(MR.strings.icon_descr_hang_up), tint = Color.Red, modifier = Modifier.size(64.dp))
}
Row(Modifier.fillMaxWidth().padding(horizontal = 6.dp), horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically) {
ToggleAudioButton(call, enabled, toggleAudio)
Spacer(Modifier.size(40.dp))
IconButton(onClick = dismiss, enabled = enabled) {
Icon(painterResource(MR.images.ic_call_end_filled), stringResource(MR.strings.icon_descr_hang_up), tint = if (enabled) Color.Red else MaterialTheme.colors.secondary, modifier = Modifier.size(64.dp))
}
if (call.videoEnabled) {
ControlButton(call, painterResource(MR.images.ic_flip_camera_android_filled), MR.strings.icon_descr_flip_camera, enabled, flipCamera)
ControlButton(call, painterResource(MR.images.ic_videocam_filled), MR.strings.icon_descr_video_off, enabled, toggleVideo)
} else {
Spacer(Modifier.size(48.dp))
ControlButton(call, painterResource(MR.images.ic_videocam_off), MR.strings.icon_descr_video_on, enabled, toggleVideo)
}
if (call.videoEnabled) {
ControlButton(call, painterResource(MR.images.ic_flip_camera_android_filled), MR.strings.icon_descr_flip_camera, flipCamera)
ControlButton(call, painterResource(MR.images.ic_videocam_filled), MR.strings.icon_descr_video_off, toggleVideo)
} else {
Spacer(Modifier.size(48.dp))
ControlButton(call, painterResource(MR.images.ic_videocam_off), MR.strings.icon_descr_video_on, toggleVideo)
}
}
CallMediaType.Audio -> {
Spacer(Modifier.fillMaxHeight().weight(1f))
Column(
Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ProfileImage(size = 192.dp, image = call.contact.profile.image)
AudioCallInfoView(call)
}
Box(Modifier.fillMaxWidth().fillMaxHeight().weight(1f), contentAlignment = Alignment.BottomCenter) {
DisabledBackgroundCallsButton()
}
Box(Modifier.fillMaxWidth().padding(bottom = DEFAULT_BOTTOM_PADDING), contentAlignment = Alignment.CenterStart) {
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
IconButton(onClick = dismiss, enabled = enabled) {
Icon(painterResource(MR.images.ic_call_end_filled), stringResource(MR.strings.icon_descr_hang_up), tint = if (enabled) Color.Red else MaterialTheme.colors.secondary, modifier = Modifier.size(64.dp))
}
}
CallMediaType.Audio -> {
Spacer(Modifier.fillMaxHeight().weight(1f))
Column(
Modifier.fillMaxWidth(),
horizontalAlignment = Alignment.CenterHorizontally,
verticalArrangement = Arrangement.Center
) {
ProfileImage(size = 192.dp, image = call.contact.profile.image)
CallInfoView(call, alignment = Alignment.CenterHorizontally)
}
Box(Modifier.fillMaxWidth().fillMaxHeight().weight(1f), contentAlignment = Alignment.BottomCenter) {
DisabledBackgroundCallsButton()
}
Box(Modifier.fillMaxWidth().padding(bottom = DEFAULT_BOTTOM_PADDING), contentAlignment = Alignment.CenterStart) {
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.Center) {
IconButton(onClick = dismiss) {
Icon(painterResource(MR.images.ic_call_end_filled), stringResource(MR.strings.icon_descr_hang_up), tint = Color.Red, modifier = Modifier.size(64.dp))
}
Box(Modifier.padding(start = 32.dp)) {
ToggleAudioButton(call, enabled, toggleAudio)
}
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterEnd) {
Box(Modifier.padding(end = 32.dp)) {
ToggleSoundButton(call, speakerCanBeEnabled && enabled, toggleSound)
}
}
Box(Modifier.padding(start = 32.dp)) {
ToggleAudioButton(call, toggleAudio)
}
Box(Modifier.fillMaxWidth(), contentAlignment = Alignment.CenterEnd) {
Box(Modifier.padding(end = 32.dp)) {
ToggleSoundButton(call, speakerCanBeEnabled, toggleSound)
}
}
}
@@ -380,7 +333,7 @@ private fun ActiveCallOverlayLayout(
}
@Composable
private fun ControlButton(call: Call, icon: Painter, iconText: StringResource, enabled: Boolean = true, action: () -> Unit) {
private fun ControlButton(call: Call, icon: Painter, iconText: StringResource, action: () -> Unit, enabled: Boolean = true) {
if (call.hasMedia) {
IconButton(onClick = action, enabled = enabled) {
Icon(icon, stringResource(iconText), tint = if (enabled) Color(0xFFFFFFD8) else MaterialTheme.colors.secondary, modifier = Modifier.size(40.dp))
@@ -391,26 +344,28 @@ private fun ControlButton(call: Call, icon: Painter, iconText: StringResource, e
}
@Composable
private fun ToggleAudioButton(call: Call, enabled: Boolean = true, toggleAudio: () -> Unit) {
private fun ToggleAudioButton(call: Call, toggleAudio: () -> Unit) {
if (call.audioEnabled) {
ControlButton(call, painterResource(MR.images.ic_mic), MR.strings.icon_descr_audio_off, enabled, toggleAudio)
ControlButton(call, painterResource(MR.images.ic_mic), MR.strings.icon_descr_audio_off, toggleAudio)
} else {
ControlButton(call, painterResource(MR.images.ic_mic_off), MR.strings.icon_descr_audio_on, enabled, toggleAudio)
ControlButton(call, painterResource(MR.images.ic_mic_off), MR.strings.icon_descr_audio_on, toggleAudio)
}
}
@Composable
private fun ToggleSoundButton(call: Call, enabled: Boolean, toggleSound: () -> Unit) {
if (call.soundSpeaker) {
ControlButton(call, painterResource(MR.images.ic_volume_up), MR.strings.icon_descr_speaker_off, enabled, toggleSound)
ControlButton(call, painterResource(MR.images.ic_volume_up), MR.strings.icon_descr_speaker_off, toggleSound, enabled)
} else {
ControlButton(call, painterResource(MR.images.ic_volume_down), MR.strings.icon_descr_speaker_on, enabled, toggleSound)
ControlButton(call, painterResource(MR.images.ic_volume_down), MR.strings.icon_descr_speaker_on, toggleSound, enabled)
}
}
@Composable
fun AudioCallInfoView(call: Call) {
Column(horizontalAlignment = Alignment.CenterHorizontally) {
fun CallInfoView(call: Call, alignment: Alignment.Horizontal) {
@Composable fun InfoText(text: String, style: TextStyle = MaterialTheme.typography.body2) =
Text(text, color = Color(0xFFFFFFD8), style = style)
Column(horizontalAlignment = alignment) {
InfoText(call.contact.chatViewName, style = MaterialTheme.typography.h2)
InfoText(call.callState.text)
@@ -420,21 +375,6 @@ fun AudioCallInfoView(call: Call) {
}
}
@Composable
fun VideoCallInfoView(call: Call) {
Column(horizontalAlignment = Alignment.Start) {
InfoText(call.callState.text)
val connInfo = call.connectionInfo
val connInfoText = if (connInfo == null) "" else " (${connInfo.text})"
InfoText(call.encryptionStatus + connInfoText)
}
}
@Composable
fun InfoText(text: String, modifier: Modifier = Modifier, style: TextStyle = MaterialTheme.typography.body2) =
Text(text, modifier, color = Color(0xFFFFFFD8), style = style)
@Composable
private fun DisabledBackgroundCallsButton() {
var show by remember { mutableStateOf(!platform.androidIsBackgroundCallAllowed()) }
@@ -512,6 +452,7 @@ private fun DisabledBackgroundCallsButton() {
@Composable
fun WebRTCView(callCommand: SnapshotStateList<WCallCommand>, onResponse: (WVAPIMessage) -> Unit) {
val scope = rememberCoroutineScope()
val webView = remember { mutableStateOf<WebView?>(null) }
val permissionsState = rememberMultiplePermissionsState(
permissions = listOf(
@@ -534,10 +475,10 @@ fun WebRTCView(callCommand: SnapshotStateList<WCallCommand>, onResponse: (WVAPIM
}
lifecycleOwner.lifecycle.addObserver(observer)
onDispose {
val wv = webView.value
if (wv != null) processCommand(wv, WCallCommand.End)
lifecycleOwner.lifecycle.removeObserver(observer)
// val wv = webView.value
// if (wv != null) processCommand(wv, WCallCommand.End)
// webView.value?.destroy()
webView.value?.destroy()
webView.value = null
}
}
@@ -564,7 +505,7 @@ fun WebRTCView(callCommand: SnapshotStateList<WCallCommand>, onResponse: (WVAPIM
Box(Modifier.fillMaxSize()) {
AndroidView(
factory = { AndroidViewContext ->
(staticWebView ?: WebView(androidAppContext)).apply {
WebView(AndroidViewContext).apply {
layoutParams = ViewGroup.LayoutParams(
ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT,
@@ -589,11 +530,7 @@ fun WebRTCView(callCommand: SnapshotStateList<WCallCommand>, onResponse: (WVAPIM
webViewSettings.javaScriptEnabled = true
webViewSettings.mediaPlaybackRequiresUserGesture = false
webViewSettings.cacheMode = WebSettings.LOAD_NO_CACHE
if (staticWebView == null) {
this.loadUrl("file:android_asset/www/android/call.html")
} else {
webView.value = this
}
this.loadUrl("file:android_asset/www/android/call.html")
}
}
) { /* WebView */ }
@@ -617,15 +554,6 @@ class WebRTCInterface(private val onResponse: (WVAPIMessage) -> Unit) {
}
}
private fun updateActiveCall(initial: Call, transform: (Call) -> Call) {
val activeCall = chatModel.activeCall.value
if (activeCall != null && activeCall.contact.apiId == initial.contact.apiId) {
chatModel.activeCall.value = transform(activeCall)
} else {
Log.d(TAG, "withActiveCall: ignoring, not in call with the contact ${activeCall?.contact?.id}")
}
}
private class LocalContentWebViewClient(val webView: MutableState<WebView?>, private val assetLoader: WebViewAssetLoader) : WebViewClientCompat() {
override fun shouldInterceptRequest(
view: WebView,
@@ -638,7 +566,6 @@ private class LocalContentWebViewClient(val webView: MutableState<WebView?>, pri
super.onPageFinished(view, url)
view.evaluateJavascript("sendMessageToNative = (msg) => WebRTCInterface.postMessage(JSON.stringify(msg))", null)
webView.value = view
staticWebView = view
Log.d(TAG, "WebRTCView: webview ready")
// for debugging
// view.evaluateJavascript("sendMessageToNative = ({resp}) => WebRTCInterface.postMessage(JSON.stringify({command: resp}))", null)
@@ -652,7 +579,6 @@ fun PreviewActiveCallOverlayVideo() {
ActiveCallOverlayLayout(
call = Call(
remoteHostId = null,
userProfile = Profile.sampleData,
contact = Contact.sampleData,
callState = CallState.Negotiated,
localMedia = CallMediaType.Video,
@@ -679,7 +605,6 @@ fun PreviewActiveCallOverlayAudio() {
ActiveCallOverlayLayout(
call = Call(
remoteHostId = null,
userProfile = Profile.sampleData,
contact = Contact.sampleData,
callState = CallState.Negotiated,
localMedia = CallMediaType.Audio,

View File

@@ -1,112 +1,8 @@
package chat.simplex.common.views.chatlist
import android.app.Activity
import androidx.compose.foundation.*
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.toArgb
import androidx.compose.ui.platform.*
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import chat.simplex.common.ANDROID_CALL_TOP_PADDING
import chat.simplex.common.model.durationText
import chat.simplex.common.platform.*
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.painterResource
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.datetime.Clock
private val CALL_INTERACTIVE_AREA_HEIGHT = 74.dp
private val CALL_TOP_OFFSET = (-10).dp
private val CALL_TOP_GREEN_LINE_HEIGHT = ANDROID_CALL_TOP_PADDING - CALL_TOP_OFFSET
private val CALL_BOTTOM_ICON_OFFSET = (-15).dp
private val CALL_BOTTOM_ICON_HEIGHT = CALL_INTERACTIVE_AREA_HEIGHT + CALL_BOTTOM_ICON_OFFSET
@Composable
actual fun ActiveCallInteractiveArea(call: Call, newChatSheetState: MutableStateFlow<AnimatedViewState>) {
val onClick = { platform.androidStartCallActivity(false) }
Box(Modifier.offset(y = CALL_TOP_OFFSET).height(CALL_INTERACTIVE_AREA_HEIGHT)) {
val source = remember { MutableInteractionSource() }
val indication = rememberRipple(bounded = true, 3000.dp)
Box(Modifier.height(CALL_TOP_GREEN_LINE_HEIGHT).clickable(onClick = onClick, indication = indication, interactionSource = source)) {
GreenLine(call)
}
Box(
Modifier
.offset(y = CALL_BOTTOM_ICON_OFFSET)
.size(CALL_BOTTOM_ICON_HEIGHT)
.background(SimplexGreen, CircleShape)
.clip(CircleShape)
.clickable(onClick = onClick, indication = indication, interactionSource = source)
.align(Alignment.BottomCenter),
contentAlignment = Alignment.Center
) {
val media = call.peerMedia ?: call.localMedia
if (media == CallMediaType.Video) {
Icon(painterResource(MR.images.ic_videocam_filled), null, Modifier.size(27.dp).offset(x = 2.5.dp, y = 2.dp), tint = Color.White)
} else {
Icon(painterResource(MR.images.ic_call_filled), null, Modifier.size(27.dp).offset(x = -0.5.dp, y = 2.dp), tint = Color.White)
}
}
}
}
@Composable
private fun GreenLine(call: Call) {
Row(
Modifier
.fillMaxSize()
.background(SimplexGreen)
.padding(top = -CALL_TOP_OFFSET)
.padding(horizontal = DEFAULT_PADDING),
verticalAlignment = Alignment.CenterVertically,
horizontalArrangement = Arrangement.Center
) {
ContactName(call.contact.displayName)
Spacer(Modifier.weight(1f))
CallDuration(call)
}
val window = (LocalContext.current as Activity).window
DisposableEffect(Unit) {
window.statusBarColor = SimplexGreen.toArgb()
onDispose {
window.statusBarColor = Color.Black.toArgb()
}
}
}
@Composable
private fun ContactName(name: String) {
Text(name, Modifier.width(windowWidth() * 0.35f), color = Color.White, maxLines = 1, overflow = TextOverflow.Ellipsis)
}
@Composable
private fun CallDuration(call: Call) {
val connectedAt = call.connectedAt
if (connectedAt != null) {
val time = remember { mutableStateOf(durationText(0)) }
LaunchedEffect(Unit) {
while (true) {
time.value = durationText((Clock.System.now() - connectedAt).inWholeSeconds.toInt())
delay(250)
}
}
val text = time.value
val sp40Or50 = with(LocalDensity.current) { if (text.length >= 6) 60.sp.toDp() else 42.sp.toDp() }
val offset = with(LocalDensity.current) { 7.sp.toDp() }
Text(text, Modifier.offset(x = offset).widthIn(min = sp40Or50), color = Color.White)
}
}
actual fun DesktopActiveCallOverlayLayout(newChatSheetState: MutableStateFlow<AnimatedViewState>) {}

View File

@@ -71,7 +71,7 @@ if(NOT APPLE)
else()
# Without direct linking it can't find hs_init in linking step
add_library( rts SHARED IMPORTED )
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/deps/libHSrts*_thr-*.${OS_LIB_EXT})
FILE(GLOB RTSLIB ${CMAKE_SOURCE_DIR}/libs/${OS_LIB_PATH}-${OS_LIB_ARCH}/libHSrts*_thr-*.${OS_LIB_EXT})
set_target_properties( rts PROPERTIES IMPORTED_LOCATION ${RTSLIB})
target_link_libraries(app-lib rts simplex)

View File

@@ -1,19 +1,16 @@
package chat.simplex.common
import androidx.compose.animation.core.Animatable
import androidx.compose.foundation.*
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.*
import androidx.compose.material.ripple.rememberRipple
import androidx.compose.runtime.*
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.draw.clipToBounds
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.unit.dp
import chat.simplex.common.views.usersettings.SetDeliveryReceiptsView
@@ -23,7 +20,8 @@ import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.CreateFirstProfile
import chat.simplex.common.views.helpers.SimpleButton
import chat.simplex.common.views.SplashView
import chat.simplex.common.views.call.*
import chat.simplex.common.views.call.ActiveCallView
import chat.simplex.common.views.call.IncomingCallAlertView
import chat.simplex.common.views.chat.ChatView
import chat.simplex.common.views.chatlist.*
import chat.simplex.common.views.database.DatabaseErrorView
@@ -171,17 +169,7 @@ fun MainScreen() {
}
} else {
if (chatModel.showCallView.value) {
if (appPlatform.isAndroid) {
LaunchedEffect(Unit) {
// This if prevents running the activity in the following condition:
// - the activity already started before and was destroyed by collapsing active call (start audio call, press back button, go to a launcher)
if (!chatModel.activeCallViewIsCollapsed.value) {
platform.androidStartCallActivity(false)
}
}
} else {
ActiveCallView()
}
ActiveCallView()
} else {
// It's needed for privacy settings toggle, so it can be shown even if the app is passcode unlocked
ModalManager.fullscreen.showPasscodeInView()
@@ -218,13 +206,9 @@ fun MainScreen() {
}
}
val ANDROID_CALL_TOP_PADDING = 40.dp
@Composable
fun AndroidScreen(settingsState: SettingsViewState) {
BoxWithConstraints {
val call = remember { chatModel.activeCall} .value
val showCallArea = call != null && call.callState != CallState.WaitCapabilities && call.callState != CallState.InvitationAccepted
var currentChatId by rememberSaveable { mutableStateOf(chatModel.chatId.value) }
val offset = remember { Animatable(if (chatModel.chatId.value == null) 0f else maxWidth.value) }
Box(
@@ -232,7 +216,6 @@ fun AndroidScreen(settingsState: SettingsViewState) {
.graphicsLayer {
translationX = -offset.value.dp.toPx()
}
.padding(top = if (showCallArea) ANDROID_CALL_TOP_PADDING else 0.dp)
) {
StartPartOfScreen(settingsState)
}
@@ -259,17 +242,11 @@ fun AndroidScreen(settingsState: SettingsViewState) {
}
}
}
Box(Modifier
.graphicsLayer { translationX = maxWidth.toPx() - offset.value.dp.toPx() }
.padding(top = if (showCallArea) ANDROID_CALL_TOP_PADDING else 0.dp)
) Box2@{
Box(Modifier.graphicsLayer { translationX = maxWidth.toPx() - offset.value.dp.toPx() }) Box2@{
currentChatId?.let {
ChatView(it, chatModel, onComposed)
}
}
if (call != null && showCallArea) {
ActiveCallInteractiveArea(call, remember { MutableStateFlow(AnimatedViewState.GONE) })
}
}
}

View File

@@ -96,7 +96,6 @@ object ChatModel {
val activeCallInvitation = mutableStateOf<RcvCallInvitation?>(null)
val activeCall = mutableStateOf<Call?>(null)
val activeCallViewIsVisible = mutableStateOf<Boolean>(false)
val activeCallViewIsCollapsed = mutableStateOf<Boolean>(false)
val callCommand = mutableStateListOf<WCallCommand>()
val showCallView = mutableStateOf(false)
val switchingCall = mutableStateOf(false)

View File

@@ -1900,8 +1900,10 @@ object ChatController {
if (invitation != null) {
chatModel.callManager.reportCallRemoteEnded(invitation = invitation)
}
withCall(r, r.contact) { call ->
withBGApi { chatModel.callManager.endCall(call) }
withCall(r, r.contact) { _ ->
chatModel.callCommand.add(WCallCommand.End)
chatModel.activeCall.value = null
chatModel.showCallView.value = false
}
}
is CR.ContactSwitch ->

View File

@@ -1,21 +1,16 @@
package chat.simplex.common.platform
import chat.simplex.common.model.ChatId
import chat.simplex.common.model.NotificationsMode
interface PlatformInterface {
suspend fun androidServiceStart() {}
fun androidServiceSafeStop() {}
fun androidCallServiceSafeStop() {}
fun androidNotificationsModeChanged(mode: NotificationsMode) {}
fun androidChatStartedAfterBeingOff() {}
fun androidChatStopped() {}
fun androidChatInitializedAndStarted() {}
fun androidIsBackgroundCallAllowed(): Boolean = true
fun androidSetNightModeIfSupported() {}
fun androidStartCallActivity(acceptCall: Boolean, remoteHostId: Long? = null, chatId: ChatId? = null) {}
fun androidPictureInPictureAllowed(): Boolean = true
fun androidCallEnded() {}
suspend fun androidAskToAllowBackgroundCalls(): Boolean = true
}
/**

View File

@@ -1,6 +1,6 @@
package chat.simplex.common.views.call
import chat.simplex.common.model.*
import chat.simplex.common.model.ChatModel
import chat.simplex.common.platform.*
import chat.simplex.common.views.helpers.withBGApi
import kotlinx.datetime.Clock
@@ -23,29 +23,27 @@ class CallManager(val chatModel: ChatModel) {
}
}
fun acceptIncomingCall(invitation: RcvCallInvitation) = withBGApi {
fun acceptIncomingCall(invitation: RcvCallInvitation) {
val call = chatModel.activeCall.value
val contactInfo = chatModel.controller.apiContactInfo(invitation.remoteHostId, invitation.contact.contactId)
val profile = contactInfo?.second ?: invitation.user.profile.toProfile()
// In case the same contact calling while previous call didn't end yet (abnormal ending of call from the other side)
if (call == null || (call.remoteHostId == invitation.remoteHostId && call.contact.id == invitation.contact.id)) {
justAcceptIncomingCall(invitation = invitation, profile)
if (call == null) {
justAcceptIncomingCall(invitation = invitation)
} else {
chatModel.switchingCall.value = true
try {
endCall(call = call)
justAcceptIncomingCall(invitation = invitation, profile)
} finally {
chatModel.switchingCall.value = false
withBGApi {
chatModel.switchingCall.value = true
try {
endCall(call = call)
justAcceptIncomingCall(invitation = invitation)
} finally {
chatModel.switchingCall.value = false
}
}
}
}
private fun justAcceptIncomingCall(invitation: RcvCallInvitation, userProfile: Profile) {
private fun justAcceptIncomingCall(invitation: RcvCallInvitation) {
with (chatModel) {
activeCall.value = Call(
remoteHostId = invitation.remoteHostId,
userProfile = userProfile,
contact = invitation.contact,
callState = CallState.InvitationAccepted,
localMedia = invitation.callType.media,
@@ -70,23 +68,17 @@ class CallManager(val chatModel: ChatModel) {
}
suspend fun endCall(call: Call) {
with(chatModel) {
// If there is active call currently and it's with other contact, don't interrupt it
if (activeCall.value != null && !(activeCall.value?.remoteHostId == call.remoteHostId && activeCall.value?.contact?.id == call.contact.id)) return
// Don't destroy WebView if you plan to accept next call right after this one
if (!switchingCall.value) {
showCallView.value = false
activeCall.value = null
activeCallViewIsCollapsed.value = false
platform.androidCallEnded()
}
with (chatModel) {
if (call.callState == CallState.Ended) {
Log.d(TAG, "CallManager.endCall: call ended")
activeCall.value = null
showCallView.value = false
} else {
Log.d(TAG, "CallManager.endCall: ending call...")
//callCommand.add(WCallCommand.End)
callCommand.add(WCallCommand.End)
showCallView.value = false
controller.apiEndCall(call.remoteHostId, call.contact)
activeCall.value = null
}
}
}

View File

@@ -7,11 +7,11 @@ import kotlinx.datetime.Instant
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
import java.net.URI
import java.util.*
import kotlin.collections.ArrayList
data class Call(
val remoteHostId: Long?,
val userProfile: Profile,
val contact: Contact,
val callState: CallState,
val localMedia: CallMediaType,
@@ -23,7 +23,7 @@ data class Call(
val soundSpeaker: Boolean = localMedia == CallMediaType.Video,
var localCamera: VideoCamera = VideoCamera.User,
val connectionInfo: ConnectionInfo? = null,
var connectedAt: Instant? = null,
var connectedAt: Instant? = null
) {
val encrypted: Boolean get() = localEncrypted && sharedKey != null
val localEncrypted: Boolean get() = localCapabilities?.encryption ?: false
@@ -36,9 +36,6 @@ data class Call(
}
val hasMedia: Boolean get() = callState == CallState.OfferSent || callState == CallState.Negotiated || callState == CallState.Connected
fun supportsVideo(): Boolean = peerMedia == CallMediaType.Video || localMedia == CallMediaType.Video
}
enum class CallState {
@@ -78,7 +75,6 @@ sealed class WCallCommand {
@Serializable @SerialName("media") data class Media(val media: CallMediaType, val enable: Boolean): WCallCommand()
@Serializable @SerialName("camera") data class Camera(val camera: VideoCamera): WCallCommand()
@Serializable @SerialName("description") data class Description(val state: String, val description: String): WCallCommand()
@Serializable @SerialName("layout") data class Layout(val layout: LayoutType): WCallCommand()
@Serializable @SerialName("end") object End: WCallCommand()
}
@@ -171,13 +167,6 @@ enum class VideoCamera {
val flipped: VideoCamera get() = if (this == User) Environment else User
}
@Serializable
enum class LayoutType {
@SerialName("default") Default,
@SerialName("localVideo") LocalVideo,
@SerialName("remoteVideo") RemoteVideo
}
@Serializable
data class ConnectionState(
val connectionState: String,

View File

@@ -301,9 +301,7 @@ fun ChatView(chatId: String, chatModel: ChatModel, onComposed: suspend (chatId:
withBGApi {
val cInfo = chat.chatInfo
if (cInfo is ChatInfo.Direct) {
val contactInfo = chatModel.controller.apiContactInfo(chat.remoteHostId, cInfo.contact.contactId)
val profile = contactInfo?.second ?: chatModel.currentUser.value?.profile?.toProfile() ?: return@withBGApi
chatModel.activeCall.value = Call(remoteHostId = chatRh, contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media, userProfile = profile)
chatModel.activeCall.value = Call(remoteHostId = chatRh, contact = cInfo.contact, callState = CallState.WaitCapabilities, localMedia = media)
chatModel.showCallView.value = true
chatModel.callCommand.add(WCallCommand.Capabilities(media))
}
@@ -675,7 +673,7 @@ fun ChatInfoToolbar(
}
}
}
} else if (activeCall?.contact?.id == chat.id && appPlatform.isDesktop) {
} else if (activeCall?.contact?.id == chat.id) {
barButtons.add {
val call = remember { chatModel.activeCall }.value
val connectedAt = call?.connectedAt

View File

@@ -29,7 +29,6 @@ import chat.simplex.common.views.onboarding.WhatsNewView
import chat.simplex.common.views.onboarding.shouldShowWhatsNew
import chat.simplex.common.views.usersettings.SettingsView
import chat.simplex.common.platform.*
import chat.simplex.common.views.call.Call
import chat.simplex.common.views.newchat.*
import chat.simplex.res.MR
import kotlinx.coroutines.*
@@ -122,12 +121,7 @@ fun ChatListView(chatModel: ChatModel, settingsState: SettingsViewState, setPerf
}
}
if (searchText.value.text.isEmpty()) {
if (appPlatform.isDesktop) {
val call = remember { chatModel.activeCall }.value
if (call != null) {
ActiveCallInteractiveArea(call, newChatSheetState)
}
}
DesktopActiveCallOverlayLayout(newChatSheetState)
// TODO disable this button and sheet for the duration of the switch
tryOrShowError("NewChatSheet", error = {}) {
NewChatSheet(chatModel, newChatSheetState, stopped, hideNewChatSheet)
@@ -320,7 +314,7 @@ private fun ToggleFilterDisabledButton() {
}
@Composable
expect fun ActiveCallInteractiveArea(call: Call, newChatSheetState: MutableStateFlow<AnimatedViewState>)
expect fun DesktopActiveCallOverlayLayout(newChatSheetState: MutableStateFlow<AnimatedViewState>)
fun connectIfOpenedViaUri(rhId: Long?, uri: URI, chatModel: ChatModel) {
Log.d(TAG, "connectIfOpenedViaUri: opened via link")

View File

@@ -85,7 +85,7 @@ private fun ShareListToolbar(chatModel: ChatModel, userPickerState: MutableState
userPickerState.value = AnimatedViewState.VISIBLE
}
}
else -> NavigationButtonBack(onButtonClicked = { chatModel.sharedContent.value = null })
else -> NavigationButtonBack { chatModel.sharedContent.value = null }
}
}
if (chatModel.chats.size >= 8) {
@@ -143,7 +143,7 @@ private fun ShareList(chatModel: ChatModel, search: String) {
}
val chats by remember(search) {
derivedStateOf {
if (search.isEmpty()) chatModel.chats.toList().filter { it.chatInfo.ready } else chatModel.chats.toList().filter { it.chatInfo.ready }.filter(filter)
if (search.isEmpty()) chatModel.chats.filter { it.chatInfo.ready } else chatModel.chats.filter { it.chatInfo.ready }.filter(filter)
}
}
LazyColumn(

View File

@@ -18,7 +18,7 @@ import chat.simplex.res.MR
import dev.icerock.moko.resources.compose.painterResource
@Composable
fun CloseSheetBar(close: (() -> Unit)?, showClose: Boolean = true, tintColor: Color = if (close != null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary, endButtons: @Composable RowScope.() -> Unit = {}) {
fun CloseSheetBar(close: (() -> Unit)?, showClose: Boolean = true, endButtons: @Composable RowScope.() -> Unit = {}) {
Column(
Modifier
.fillMaxWidth()
@@ -35,7 +35,7 @@ fun CloseSheetBar(close: (() -> Unit)?, showClose: Boolean = true, tintColor: Co
verticalAlignment = Alignment.CenterVertically
) {
if (showClose) {
NavigationButtonBack(tintColor = tintColor, onButtonClicked = close)
NavigationButtonBack(onButtonClicked = close)
} else {
Spacer(Modifier)
}

View File

@@ -44,10 +44,10 @@ fun DefaultTopAppBar(
}
@Composable
fun NavigationButtonBack(onButtonClicked: (() -> Unit)?, tintColor: Color = if (onButtonClicked != null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary) {
fun NavigationButtonBack(onButtonClicked: (() -> Unit)?) {
IconButton(onButtonClicked ?: {}, enabled = onButtonClicked != null) {
Icon(
painterResource(MR.images.ic_arrow_back_ios_new), stringResource(MR.strings.back), tint = tintColor
painterResource(MR.images.ic_arrow_back_ios_new), stringResource(MR.strings.back), tint = if (onButtonClicked != null) MaterialTheme.colors.primary else MaterialTheme.colors.secondary
)
}
}

View File

@@ -29,7 +29,7 @@ fun ModalView(
}
Surface(Modifier.fillMaxSize(), contentColor = LocalContentColor.current) {
Column(if (background != MaterialTheme.colors.background) Modifier.background(background) else Modifier.themedBackground()) {
CloseSheetBar(close, showClose, endButtons = endButtons)
CloseSheetBar(close, showClose, endButtons)
Box(modifier) { content() }
}
}

View File

@@ -419,7 +419,7 @@ expect fun ByteArray.toBase64StringForPassphrase(): String
// Android's default implementation that was used before multiplatform, adds non-needed characters at the end of string
// which can be bypassed by:
// fun String.toByteArrayFromBase64(): ByteArray = Base64.getMimeDecoder().decode(this.trimEnd { it == '\n' || it == ' ' })
// fun String.toByteArrayFromBase64(): ByteArray = Base64.getDecoder().decode(this.trimEnd { it == '\n' || it == ' ' })
expect fun String.toByteArrayFromBase64ForPassphrase(): ByteArray
val LongRange.Companion.saver

View File

@@ -1630,4 +1630,8 @@
<string name="block_for_all_question">حظر العضو للجميع؟</string>
<string name="blocked_by_admin_item_description">محظور من قبل المشرف</string>
<string name="member_blocked_by_admin">محظور من قبل المشرف</string>
<string name="message_too_large">الرسالة كبيرة جدًا</string>
<string name="welcome_message_is_too_long">رسالة الترحيب طويلة جدًا</string>
<string name="database_migration_in_progress">ترحيل قاعدة البيانات قيد التقدم.
\nقد يستغرق بضع دقائق.</string>
</resources>

View File

@@ -179,9 +179,6 @@
<!-- SimpleX Chat foreground Service -->
<string name="simplex_service_notification_title">SimpleX Chat service</string>
<string name="simplex_service_notification_text">Receiving messages…</string>
<string name="call_service_notification_audio_call">Audio call</string>
<string name="call_service_notification_video_call">Video call</string>
<string name="call_service_notification_end_call">End call</string>
<string name="hide_notification">Hide</string>
<!-- Notification channels -->
@@ -806,10 +803,6 @@
<string name="callstate_connected">connected</string>
<string name="callstate_ended">ended</string>
<!-- CallView -->
<string name="unable_to_open_browser_title">Error opening browser</string>
<string name="unable_to_open_browser_desc">The default web browser is required for calls. Please configure the default browser in the system, and share more information with the developers.</string>
<!-- SimpleXInfo -->
<string name="next_generation_of_private_messaging">The next generation of private messaging</string>
<string name="privacy_redefined">Privacy redefined</string>

View File

@@ -181,7 +181,7 @@
<string name="change_database_passphrase_question">Промяна на паролата на базата данни\?</string>
<string name="rcv_group_event_changed_member_role">променена ролята от %s на %s</string>
<string name="invite_prohibited">Не може да покани контакта!</string>
<string name="rcv_conn_event_switch_queue_phase_completed">променен е адреса за вас</string>
<string name="rcv_conn_event_switch_queue_phase_completed">адреса за изпращане е променен</string>
<string name="change_verb">Промени</string>
<string name="change_member_role_question">Промяна на груповата роля\?</string>
<string name="you_will_still_receive_calls_and_ntfs">Все още ще получавате обаждания и известия от заглушени профили, когато са активни.</string>
@@ -834,7 +834,7 @@
<string name="v4_3_voice_messages_desc">Макс. 40 секунди, получават се незабавно.</string>
<string name="v4_4_live_messages">Съобщения на живо</string>
<string name="live_message">Съобщение на живо!</string>
<string name="verify_security_code">Потвръди кода за сигурност</string>
<string name="verify_security_code">Потвърди кода за сигурност</string>
<string name="no_details">няма подробности</string>
<string name="ok">ОК</string>
<string name="ask_your_contact_to_enable_voice">Моля, попитайте вашия контакт, за да активирате изпращане на гласови съобщения.</string>
@@ -866,7 +866,7 @@
<string name="feature_offered_item_with_param">предлага %s: %2s</string>
<string name="whats_new_read_more">Прочетете още</string>
<string name="v5_2_disappear_one_message">Накарайте едно съобщение да изчезне</string>
<string name="v4_4_verify_connection_security">Потвръди сигурността на връзката</string>
<string name="v4_4_verify_connection_security">Потвърди сигурността на връзката</string>
<string name="v4_5_message_draft">Чернова на съобщение</string>
<string name="v5_2_more_things_descr">- по-стабилна доставка на съобщения.
\n- малко по-добри групи.
@@ -1246,7 +1246,7 @@
<string name="voice_messages_prohibited">Гласовите съобщения са забранени!</string>
<string name="you_need_to_allow_to_send_voice">Трябва да разрешите на вашия контакт да изпраща гласови съобщения, за да можете да ги изпращате.</string>
<string name="you_are_invited_to_group">Поканени сте в групата</string>
<string name="snd_conn_event_switch_queue_phase_completed">променихте адреса</string>
<string name="snd_conn_event_switch_queue_phase_completed">адреса за получаване е променен</string>
<string name="you_can_share_this_address_with_your_contacts">Можете да споделите този адрес с вашите контакти, за да им позволите да се свържат с %s.</string>
<string name="unfavorite_chat">Премахни от любимите</string>
<string name="settings_section_title_you">ВИЕ</string>
@@ -1288,7 +1288,7 @@
<string name="incognito_random_profile">Вашият автоматично генериран профил</string>
<string name="user_unmute">Уведомявай</string>
<string name="you_can_share_your_address">Можете да споделите адреса си като линк или QR код - всеки може да се свърже с вас.</string>
<string name="snd_conn_event_switch_queue_phase_completed_for_member">променихте адреса за %s</string>
<string name="snd_conn_event_switch_queue_phase_completed_for_member">променихте адреса получаване за %s</string>
<string name="group_main_profile_sent">Вашият чат профил ще бъде изпратен на членовете на групата</string>
<string name="your_chat_profile_will_be_sent_to_your_contact">Вашият чат профил ще бъде изпратен
\nдо вашия контакт</string>
@@ -1432,7 +1432,7 @@
<string name="rcv_group_event_1_member_connected">%s свързан</string>
<string name="random_port">Случаен</string>
<string name="linked_desktops">Запомнени настолни устройства</string>
<string name="discover_on_network">Открий през локалната мрежа</string>
<string name="discover_on_network">Откриване през локалната мрежа</string>
<string name="rcv_group_and_other_events">и %d други събития</string>
<string name="connect_plan_connect_via_link">Свърване чрез линк?</string>
<string name="v5_4_incognito_groups">Инкогнито групи</string>
@@ -1485,7 +1485,7 @@
<string name="unblock_member_desc">Съобщенията от %s ще бъдат показани!</string>
<string name="this_device_name_shared_with_mobile">Името на устройството ще бъде споделено със свързания мобилен клиент.</string>
<string name="error_sending_message_contact_invitation">Грешка при изпращане на покана</string>
<string name="verify_code_on_mobile">Потвръди кода на мобилното устройство</string>
<string name="verify_code_on_mobile">Потвърди кода на мобилното устройство</string>
<string name="open_port_in_firewall_title">Отвори порт в защитната стена</string>
<string name="enter_this_device_name">Въведи името на това устройство…</string>
<string name="error">Грешка</string>
@@ -1501,7 +1501,7 @@
<string name="bad_desktop_address">Грешен адрес на настолното устройство</string>
<string name="paste_desktop_address">Постави адрес на настолно устройство</string>
<string name="connect_plan_this_is_your_link_for_group_vName"><![CDATA[Това е вашят линк за група <b>%1$s</b>!]]></string>
<string name="verify_code_with_desktop">Потвръди кода с настолното устройство</string>
<string name="verify_code_with_desktop">Потвърди кода с настолното устройство</string>
<string name="scan_qr_code_from_desktop">Сканирай QR код от настолното устройство</string>
<string name="unblock_member_confirmation">Отблокирай</string>
<string name="devices">Устройства</string>
@@ -1513,12 +1513,12 @@
<string name="connect_plan_you_have_already_requested_connection_via_this_address">Вече сте заявили връзка през този адрес!</string>
<string name="terminal_always_visible">Покажи конзолата в нов прозорец</string>
<string name="scan_from_mobile">Сканиране от мобилно устройство</string>
<string name="verify_connections">Потвръди връзките</string>
<string name="verify_connections">Потвърждение за свързване</string>
<string name="disconnect_desktop_question">Прекъсни връзката с настолното устройство?</string>
<string name="loading_remote_file_desc">Моля, изчакайте, докато файлът се зареди от свързаното мобилно устройство</string>
<string name="block_member_desc">Всички нови съобщения от %s ще бъдат скрити!</string>
<string name="desktop_app_version_is_incompatible">Версията на настолното приложение %s не е съвместима с това приложение.</string>
<string name="verify_connection">Потвръди връзките</string>
<string name="verify_connection">Потвърди връзка</string>
<string name="no_connected_mobile">Няма свързано мобилно устройство</string>
<string name="blocked_item_description">блокиран</string>
<string name="you_can_make_address_visible_via_settings">Можете да го направите видим за вашите контакти в SimpleX чрез Настройки.</string>
@@ -1592,4 +1592,41 @@
<string name="developer_options_section">Опции за разработчици</string>
<string name="show_slow_api_calls">Показване на бавни API заявки</string>
<string name="possible_deadlock_title">Грешка в заключено положение</string>
<string name="v5_5_private_notes_descr">С криптирани файлове и медия.</string>
<string name="v5_5_simpler_connect_ui">Поставете линк, за да се свържете!</string>
<string name="v5_5_private_notes">Лични бележки</string>
<string name="v5_5_message_delivery">Подобрена доставка на съобщения</string>
<string name="v5_5_message_delivery_descr">С намален разход на батерията.</string>
<string name="blocked_by_admin_item_description">блокиран от админ</string>
<string name="blocked_by_admin_items_description">%d съобщения, блокирани от администратора</string>
<string name="error_creating_message">Грешка при създаване на съобщение</string>
<string name="error_deleting_note_folder">Грешка при изтриване на лични бележки</string>
<string name="clear_note_folder_question">Изчистване на лични бележки?</string>
<string name="clear_note_folder_warning">Всички съобщения ще бъдат изтрити - това не може да бъде отменено!</string>
<string name="rcv_group_event_member_blocked">блокиран %s</string>
<string name="rcv_group_event_member_unblocked">отблокиран %s</string>
<string name="snd_group_event_member_blocked">вие блокирахте %s</string>
<string name="snd_group_event_member_unblocked">вие отблокирахте %s</string>
<string name="info_row_created_at">Създаден на</string>
<string name="share_text_created_at">Създаден на: %s</string>
<string name="saved_message_title">Запазено съобщение</string>
<string name="block_for_all_question">Блокиране на член за всички?</string>
<string name="block_for_all">Блокирай за всички</string>
<string name="unblock_for_all_question">Отблокиране на член за всички?</string>
<string name="unblock_for_all">Отблокирай за всички</string>
<string name="member_blocked_by_admin">Блокиран от админ</string>
<string name="member_info_member_blocked">блокиран</string>
<string name="error_blocking_member_for_all">Грешка при блокиране на член за всички</string>
<string name="v5_5_simpler_connect_ui_descr">Лентата за търсене приема линк за връзка.</string>
<string name="v5_5_join_group_conversation">Присъединяване към групи</string>
<string name="v5_5_new_interface_languages">Унгарски и турски потребителски интерфейс</string>
<string name="v5_5_join_group_conversation_descr">Скорошна история и подобрен бот за директорията за групи.</string>
<string name="profile_update_event_member_name_changed">името на члена %1$s е променено на %2$s</string>
<string name="profile_update_event_contact_name_changed">името на контакта %1$s е променено на %2$s</string>
<string name="profile_update_event_removed_picture">премахната профилна снимка</string>
<string name="profile_update_event_set_new_picture">зададена нова профилна снимка</string>
<string name="profile_update_event_removed_address">премахнат адрес за контакт</string>
<string name="profile_update_event_set_new_address">зададен нов адрес за контакт</string>
<string name="profile_update_event_updated_profile">актуализиран профил</string>
<string name="note_folder_local_display_name">Лични бележки</string>
</resources>

View File

@@ -113,4 +113,35 @@
<string name="failed_to_create_user_duplicate_desc">شما یک نمایه گپ با نام نمایشی یکسان دارید، لطفا نام دیگری انتخاب کنید.</string>
<string name="error_creating_address">خطا در ایجاد نشانی</string>
<string name="ensure_xftp_server_address_are_correct_format_and_unique">مطمئن شوید قالب آدرس‌های سرور XFTP صحیح است، در خط‌های جدا نوشته شده و تکرار نشده‌اند.</string>
<string name="error_accepting_contact_request">خطا در پذیرش درخواست مخاطب</string>
<string name="sender_may_have_deleted_the_connection_request">فرستنده ممکن است درخواست اتصال را حذف کرده باشد.</string>
<string name="error_deleting_note_folder">خطا در حذف یادداشت‌های خصوصی</string>
<string name="error_aborting_address_change">خطا در لغو تغییر نشانی</string>
<string name="error_synchronizing_connection">خطا در انطباق زمانی اتصال</string>
<string name="error_smp_test_failed_at_step">آزمایش در گام %s ناموفق بود.</string>
<string name="error_xftp_test_server_auth">سرور برای بارگذازی به اجازه نیاز دارد، گذرواژه را بررسی کنید</string>
<string name="error_smp_test_certificate">احتمال دارد اثر انگشت گواهینامه در نشانی سرور نادرست باشد</string>
<string name="smp_server_test_create_queue">ایجاد صف</string>
<string name="smp_server_test_upload_file">بارگذاری پرونده</string>
<string name="smp_server_test_download_file">بارگیری پرونده</string>
<string name="smp_server_test_compare_file">مقایسه پرونده</string>
<string name="smp_server_test_delete_file">حذف پرونده</string>
<string name="error_deleting_user">خطا در حذف نمایه کاربر</string>
<string name="error_updating_user_privacy">خطا در به‌روزرسانی حریم خصوصی کاربر</string>
<string name="error_deleting_contact">خطا در حذف مخاطب</string>
<string name="error_deleting_group">خطا در حذف گروه</string>
<string name="error_deleting_contact_request">خطا در حذف درخواست مخاطب</string>
<string name="error_deleting_pending_contact_connection">خطا در حذف اتصال معلق مخاطب</string>
<string name="error_changing_address">خطا در تغییر نشانی</string>
<string name="error_setting_address">خطا در تنظیم نشانی</string>
<string name="error_alert_title">خطا</string>
<string name="smp_server_test_connect">اتصال</string>
<string name="smp_server_test_disconnect">قطع اتصال</string>
<string name="smp_server_test_secure_queue">ایمن‌سازی صف</string>
<string name="smp_server_test_delete_queue">حذف صف</string>
<string name="smp_server_test_create_file">ایجاد پرونده</string>
<string name="error_smp_test_server_auth">سرور برای ایجاد صف داده‌ها به اجازه نیاز دارد، گذرواژه را بررسی کنید</string>
<string name="possible_deadlock_title">بن‌بست</string>
<string name="connection_error_auth_desc">مگر اینکه مخاطبتان اتصال را حذف کرده یا این لینک قبلا استفاده شده باشد، ممکن است این یک اشکال باشد - لطفا آن را گزارش دهید.
\nبرای متصل شدن، لطفا از مخاطبتان بخواهید لینک اتصال دیگری ایجاد کند و بررسی کنید که اتصال شبکه باثباتی دارید.</string>
</resources>

View File

@@ -34,7 +34,7 @@
<string name="callstatus_error">hiba a hívásban</string>
<string name="v5_4_block_group_members">Csoporttagok blokkolása</string>
<string name="la_authenticate">Hitelesítés</string>
<string name="empty_chat_profile_is_created">Egy üres chat profil létre lett hozva a megadott névvel és az app normál módon megnyílik.</string>
<string name="empty_chat_profile_is_created">Egy üres csevegési profil létre lett hozva a megadott névvel és az alkalmazás normál módon megnyílik.</string>
<string name="feature_cancelled_item">megszakítva %s</string>
<string name="smp_servers_preset_add">Adj hozzá egyedi szervereket</string>
<string name="calls_prohibited_with_this_contact">A hang- és videóhívások le vannak tiltva.</string>
@@ -50,7 +50,7 @@
<string name="full_backup">App adatmentés</string>
<string name="database_initialization_error_title">Az adatbázis inicializálása sikertelen</string>
<string name="all_your_contacts_will_remain_connected_update_sent">A kapcsolat megmarad az összes Ismerősöddel. Profil változtatások frissítésre kerülnek az ismerőseidnél.</string>
<string name="v4_5_transport_isolation_descr">Chat profile (alap beállítás) avagy kapcsolat által (BÉTA).</string>
<string name="v4_5_transport_isolation_descr">A csevegési profil által (alap beállítás), vagy kapcsolat által (BÉTA).</string>
<string name="connect__a_new_random_profile_will_be_shared">Egy új véletlenszerű profil lesz megosztva.</string>
<string name="allow_voice_messages_only_if">Hangüzenetek küldésének engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string>
<string name="app_version_code">Az alkalmazás build száma: %s</string>
@@ -58,7 +58,7 @@
<string name="network_settings">Haladó hálózati beállítások</string>
<string name="allow_your_contacts_to_send_voice_messages">Ismerőseid küldhetnek hangüzeneteket.</string>
<string name="settings_audio_video_calls">Hang- és videóhívások</string>
<string name="v5_3_encrypt_local_files_descr">Az app titkosítja a helyi fájlokat (a videók kivételével).</string>
<string name="v5_3_encrypt_local_files_descr">Az alkalmazás titkosítja a helyi fájlokat (a videók kivételével).</string>
<string name="answer_call">Hívás fogadása</string>
<string name="allow_your_contacts_to_send_disappearing_messages">Ismerőseid küldhetnek eltűnő üzeneteket.</string>
<string name="connect_plan_already_connecting">Már kapcsolódik!</string>
@@ -79,11 +79,11 @@
<string name="connect_plan_already_joining_the_group">Már csatlakozik a csoporthoz!</string>
<string name="auto_accept_contact">Automatikus elfogadás</string>
<string name="notifications_mode_service_desc">A háttérszolgáltatás mindig fut - az értesítések azonnal megjelennek, amint üzenetek vannak.</string>
<string name="allow_to_delete_messages">Elküldött üzenetek végleges törlésének engedélyezése. (24 óra)</string>
<string name="allow_to_delete_messages">Az elküldött üzenetek végleges törlése engedélyezve van. (24 óra)</string>
<string name="both_you_and_your_contact_can_send_voice">Mindketten, te is és az ismerősöd is küldhet hangüzeneteket.</string>
<string name="alert_title_msg_bad_id">Téves üzenet ID</string>
<string name="allow_your_contacts_adding_message_reactions">Ismerőseid küldhetnek reakciókat az üzenetekre.</string>
<string name="allow_to_send_voice">Hangüzenetek küldése engedélyezve.</string>
<string name="allow_to_send_voice">A hangüzenetek küldése engedélyezve van.</string>
<string name="allow_message_reactions_only_if">Üzenet reakciók engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string>
<string name="back">Vissza</string>
<string name="it_can_disabled_via_settings_notifications_still_shown"><![CDATA[<b>Kikapcsolható a beállításokban</b> az értesítések továbbra is megjelenítésre kerülnek amíg az alkalmazás fut.]]></string>
@@ -97,7 +97,7 @@
<string name="callstatus_calling">hívás…</string>
<string name="color_secondary_variant">További másodlagos</string>
<string name="smp_servers_add_to_another_device">Hozzáadás másik eszközhöz</string>
<string name="allow_message_reactions">Üzenet reakciók engedélyezése.</string>
<string name="allow_message_reactions">Az üzenetekre adott emoji reakciók engedélyezve vannak.</string>
<string name="icon_descr_cancel_file_preview">Fájl előnézet megszakítása</string>
<string name="all_group_members_will_remain_connected">Minden csoporttag kapcsolatban marad.</string>
<string name="onboarding_notifications_mode_service_desc"><![CDATA[<b>Több akkumulátort használ</b>! Háttérszolgáltatás mindig fut - értesítések megjelennek azonnal, ahogy új üzenetek érkeznek.]]></string>
@@ -110,7 +110,7 @@
<string name="v5_2_more_things">Néhány további dolog</string>
<string name="authentication_cancelled">Hitelesítés megszakítva</string>
<string name="allow_to_send_files">A fájlok- és a médiatartalom küldése engedélyezve.</string>
<string name="users_delete_all_chats_deleted">Minden beszélgetés, illetve az összes üzenet törlésre kerül - ezt nem lehet visszavonni!</string>
<string name="users_delete_all_chats_deleted">Minden csevegés, illetve az összes üzenet törlésre kerül - ezt nem lehet visszavonni!</string>
<string name="icon_descr_audio_call">hanghívás</string>
<string name="bold_text">félkövér</string>
<string name="app_passcode_replaced_with_self_destruct">Az alkalmazás jelkód helyettesítésre kerül egy önmegsemmisítő jelkóddal.</string>
@@ -121,7 +121,7 @@
<string name="call_already_ended">A hívás már befejeződött!</string>
<string name="turn_off_battery_optimization_button">Engedélyez</string>
<string name="all_your_contacts_will_remain_connected">A kapcsolat megmarad az összes Ismerősöddel.</string>
<string name="icon_descr_cancel_live_message">Élő chat üzenet megszakítása</string>
<string name="icon_descr_cancel_live_message">Élő csevegési üzenet megszakítása</string>
<string name="allow_irreversible_message_deletion_only_if">Üzenet végleges törlésének engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi. (24 óra)</string>
<string name="v4_6_audio_video_calls">Hang- és videóhívások</string>
<string name="integrity_msg_bad_hash">téves üzenet hash</string>
@@ -141,7 +141,7 @@
<string name="v5_1_better_messages">Jobb üzenetek</string>
<string name="abort_switch_receiving_address_desc">A cím változtatás megszakításra kerül. A régi fogadó cím marad használatban.</string>
<string name="allow_verb">Engedélyez</string>
<string name="bad_desktop_address">Téves számítógép cím</string>
<string name="bad_desktop_address">Hibás asztali kliens cím</string>
<string name="users_add">Profil hozzáadása</string>
<string name="attach">Csatolás</string>
<string name="v5_0_app_passcode">Alkalmazás jelkód</string>
@@ -153,13 +153,13 @@
<string name="allow_your_contacts_to_call">Hang- és videóhívás engedélyezése az ismerőseid számára.</string>
<string name="settings_section_title_icon">ALKALMAZÁS IKON</string>
<string name="v4_3_improved_server_configuration_desc">Szerver hozzáadása QR kód befotózásával.</string>
<string name="allow_to_send_disappearing">Eltűnő üzenetek küldése engedélyezve.</string>
<string name="allow_to_send_disappearing">Az eltűnő üzenetek küldése engedélyezve van.</string>
<string name="allow_disappearing_messages_only_if">Eltűnő üzenetek engedélyezése kizárólag abban az esetben, ha a másik fél is engedélyezi.</string>
<string name="icon_descr_audio_off">Hang kikapcsolva</string>
<string name="allow_direct_messages">A közvetlen üzenetküldés csak a tagok számára engedélyezett.</string>
<string name="allow_direct_messages">A közvetlen üzenetküldés a tagok számára engedélyezve van.</string>
<string name="settings_section_title_app">Alkalmazás</string>
<string name="icon_descr_call_progress">Hívás folyamatban</string>
<string name="both_you_and_your_contact_can_add_message_reactions">Mindketten, te is és az ismerősöd is használhat üzenet reakciókat (emojik).</string>
<string name="both_you_and_your_contact_can_add_message_reactions">Mindketten, te is és az ismerősöd is adhat az üzenetekre emoji reakciókat.</string>
<string name="both_you_and_your_contact_can_make_calls">Mindketten, te is és az ismerősöd is tud hívásokat indítani.</string>
<string name="la_auth_failed">Hitelesítés sikertelen</string>
<string name="block_member_desc">Minden új üzenet %s -tól/től elrejtésre kerül.</string>
@@ -242,7 +242,7 @@
<string name="group_member_status_intro_invitation">csatlakozás (bemutatkozás meghívás)</string>
<string name="create_simplex_address">SimpleX azonosító létrehozása</string>
<string name="rcv_direct_event_contact_deleted">törölt ismerős</string>
<string name="delete_member_message__question">Tag üzenetének törlése?</string>
<string name="delete_member_message__question">Törlöd a tag üzenetét?</string>
<string name="chat_is_running">A chat szolgáltatás működik (fut)</string>
<string name="share_one_time_link">Egyszer használatos meghívó link létrehozása</string>
<string name="delete_link">Link törlése</string>
@@ -279,16 +279,16 @@
<string name="snd_conn_event_switch_queue_phase_changing_for_member">azonosító megváltoztatása %s -ra/re…</string>
<string name="chat_database_imported">Chat adatbázis importálva</string>
<string name="chat_archive_section">CHAT ARCHÍVUM</string>
<string name="delete_messages">Üzenetek törlése?</string>
<string name="delete_messages">Üzenetek törlése</string>
<string name="clear_chat_menu_action">Kiürítés</string>
<string name="icon_descr_close_button">Bezárás gomb</string>
<string name="chat_is_stopped">A chat szolgáltatás leállt (nem fut)</string>
<string name="item_info_current">(jelenlegi)</string>
<string name="v5_1_custom_themes_descr">Színsémák személyreszabása és megosztása</string>
<string name="delete_chat_profile_question">Chat profil törlése?</string>
<string name="delete_chat_profile_question">Törlöd a chat profilt?</string>
<string name="create_group">Titkos csoport létrehozása</string>
<string name="connected_to_desktop">Csatlakozva a számítógéphez</string>
<string name="configure_ICE_servers">ICE sezrverek beállítása</string>
<string name="configure_ICE_servers">ICE szerverek beállítása</string>
<string name="button_delete_group">Csoport törlése</string>
<string name="clear_verification">Hitelesítés törlése</string>
<string name="group_member_status_creator">szerző</string>
@@ -298,7 +298,7 @@
<string name="v5_1_custom_themes">Egyedi színsémák</string>
<string name="group_member_status_accepted">kapcsolódás (elfogadva)</string>
<string name="smp_servers_check_address">Szerver cím ellenőrzése és újrapróbálkozás.</string>
<string name="delete_group_question">Csoport törlése?</string>
<string name="delete_group_question">Törlöd a csoportot?</string>
<string name="confirm_database_upgrades">Adatbázis frissítés megerősítése</string>
<string name="create_your_profile">Saját profil létrehozása</string>
<string name="snd_conn_event_switch_queue_phase_changing">azonosító megváltoztatása…</string>
@@ -313,13 +313,13 @@
<string name="callstate_connecting">kapcsolódás…</string>
<string name="dark_theme">Sötét színséma</string>
<string name="deleted_description">törölve</string>
<string name="users_delete_question">Chat profil törlése?</string>
<string name="users_delete_question">Törlöd a chat profilt?</string>
<string name="chat_with_developers">Chat a SimpleX fejlesztőivel</string>
<string name="delete_link_question">Link törlése?</string>
<string name="delete_link_question">Törlöd a linket?</string>
<string name="server_connecting">kapcsolódás</string>
<string name="send_disappearing_message_custom_time">Személyreszabott idő</string>
<string name="connect_via_link_incognito">Inkognítóban csatlakozva</string>
<string name="settings_section_title_chats">CHATEK</string>
<string name="settings_section_title_chats">CSEVEGÉSEK</string>
<string name="v5_3_new_desktop_app_descr">Új profil létrehozása a számítógépen futó appban. 💻</string>
<string name="group_member_status_announced">kapcsolódás (bejelentve)</string>
<string name="contact_connection_pending">kapcsolódás…</string>
@@ -339,17 +339,17 @@
<string name="smp_server_test_create_file">Fájl létrehozása</string>
<string name="create_secret_group_title">Tikos csoport létrehozása</string>
<string name="clear_contacts_selection_button">Kiürítés</string>
<string name="delete_contact_question">Ismerős törlése?</string>
<string name="delete_contact_question">Törlöd az ismerőst?</string>
<string name="clear_verb">Kiürítés</string>
<string name="create_address_and_let_people_connect">Hozz létre egy azonosítót, hogy az ismerősök kapcsolatba léphessenek veled.</string>
<string name="v4_4_verify_connection_security_desc">Biztonsági kódok ösezhasonlítása az ismerősökkel.</string>
<string name="v4_4_verify_connection_security_desc">Biztonsági kódok összehasonlítása az ismerősökkel.</string>
<string name="smp_server_test_compare_file">Fájl összehasonlítása</string>
<string name="your_chats">Chatek</string>
<string name="delete_message__question">Üzenet törlése?</string>
<string name="delete_pending_connection__question">Függő kapcsolatfelvételi kérés törlése?</string>
<string name="your_chats">Csevegések</string>
<string name="delete_message__question">Törlöd az üzenetet?</string>
<string name="delete_pending_connection__question">Törlöd a függőben lévő kapcsolatfelvételi kérést?</string>
<string name="database_encrypted">Adatbázis titkosítva!</string>
<string name="clear_chat_question">Chat kiürítése?</string>
<string name="database_downgrade">Adatbázis downgrade?</string>
<string name="database_downgrade">Visszatérés a korábbi adatbázis verzióra</string>
<string name="clear_chat_button">Chat kiürítése</string>
<string name="database_passphrase_will_be_updated">Adatbázis titkosítási jelmondat frissítve lesz.</string>
<string name="multicast_connect_automatically">Kapcsolódás automatikusan</string>
@@ -371,15 +371,15 @@
<string name="ttl_week">%d hét</string>
<string name="desktop_address">Számítógép azonosítója</string>
<string name="ttl_s">%dmp</string>
<string name="delivery_receipts_title">Kézbesítési izagolások!</string>
<string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">Eszközhitelesítés nincs bekapcsolva. Bekapcsolhatod a SimpleX zárat a Beállításokon keresztük, miután bekapcsoltad az eszközhitelesítést.</string>
<string name="delivery_receipts_title">Kézbesítési igazolások!</string>
<string name="auth_device_authentication_is_not_enabled_you_can_turn_on_in_settings_once_enabled">Az eszközhitelesítés nincs bekapcsolva. Bekapcsolhatod a SimpleX zárat a Beállításokon keresztül, miután engedélyezted az eszköz hitelesítését.</string>
<string name="decryption_error">Titkosítás visszafejtési hiba</string>
<string name="share_text_disappears_at">Eltűnik ekkor: %s</string>
<string name="icon_descr_edited">szerkesztve</string>
<string name="delete_verb">Törlés</string>
<string name="ttl_hours">%d óra</string>
<string name="ttl_months">%d hónap</string>
<string name="delete_address__question">Azonosító törlése?</string>
<string name="delete_address__question">Törlöd az azonosítót?</string>
<string name="receipts_contacts_title_disable">Letiltod az üzenet kézbesítési jelentéseket?</string>
<string name="passphrase_is_different">Az adatbázis jelmondat eltérő a Keystore-ba elmentettől.</string>
<string name="direct_messages">Közvetlen üzenetek</string>
@@ -392,12 +392,12 @@
<string name="encrypted_with_random_passphrase">Az adatbázis egy véletlenszerű jelmondattal van titkosítva, lecserélheted.</string>
<string name="ttl_h">%dó</string>
<string name="ttl_w">%dhét</string>
<string name="discover_on_network">Felfedezés helyi hálózatomn keresztül</string>
<string name="v5_3_discover_join_groups">Helyi csoportok felfedezése és csatolakozás</string>
<string name="discover_on_network">Felfedezés helyi hálózaton keresztül</string>
<string name="v5_3_discover_join_groups">Helyi csoportok felfedezése és csatlakozás</string>
<string name="moderated_items_description">%1$d üzenet moderálva %2$s által</string>
<string name="disappearing_message">Eltűnő üzenet</string>
<string name="dont_create_address">Ne hozz létre azonosítót</string>
<string name="dont_show_again">Ne mutasd ismét</string>
<string name="dont_show_again">Ne mutasd újra</string>
<string name="auth_disable_simplex_lock">SimpleX Zár kikapcsolása</string>
<string name="status_e2e_encrypted">e2e titkosított</string>
<string name="settings_section_title_device">ESZKÖZ</string>
@@ -408,14 +408,14 @@
<string name="num_contacts_selected">%d ismerős(-ök) kiválasztva</string>
<string name="enable_receipts_all">Engedélyez</string>
<string name="ttl_mth">%dhónap</string>
<string name="direct_messages_are_prohibited_in_chat">A közvetlen üzenetek tagok között titltottak ebben a csoportban.</string>
<string name="direct_messages_are_prohibited_in_chat">Ebben a csoportban tiltott a tagok közötti közvetlen üzenetek küldése.</string>
<string name="ttl_min">%d perc</string>
<string name="set_password_to_export_desc">Az adatbázis egy véletlenszerű jelmondattal van titkosítva. Kérlek cseréld le exportálás előtt!</string>
<string name="receipts_groups_title_disable">Letiltod az üzenet kézbesítés jelentéseket a csoportok számára?</string>
<string name="custom_time_unit_days">nap</string>
<string name="ttl_day">%d nap</string>
<string name="delete_chat_archive_question">Chat archív törlése?</string>
<string name="failed_to_create_user_duplicate_title">Duplikálódott megjelenítési név!</string>
<string name="delete_chat_archive_question">Törlöd a chat archívumot?</string>
<string name="failed_to_create_user_duplicate_title">Duplikált megjelenítési név!</string>
<string name="receipts_contacts_disable_keep_overrides">Letiltás (felülírások megtartásával)</string>
<string name="database_upgrade">Adatbázis fejlesztése</string>
<string name="blocked_items_description">%d üzenet blokkolva</string>
@@ -442,7 +442,7 @@
<string name="receipts_groups_disable_keep_overrides">Letiltás (csoport felülírások megtartásával)</string>
<string name="rcv_group_events_count">%d csoportesemény</string>
<string name="ttl_month">%d hónap</string>
<string name="button_edit_group_profile">Csoport profil szerkesztése</string>
<string name="button_edit_group_profile">A csoport profiljának szerkesztése</string>
<string name="encrypted_audio_call">e2e titkosított hanghívás</string>
<string name="ttl_sec">%d mp</string>
<string name="decentralized">Decentralizált</string>
@@ -457,17 +457,17 @@
<string name="chat_preferences_default">alap (%s)</string>
<string name="integrity_msg_duplicate">duplikálódott üzenet</string>
<string name="disconnect_desktop_question">Számítógép leválasztása?</string>
<string name="desktop_app_version_is_incompatible">A számítógépes app verzió %s inem kompatibilis ezzel az appal.</string>
<string name="desktop_app_version_is_incompatible">Az asztali kliens verziója %s nem kompatibilis ezzel az alkalmazással.</string>
<string name="delivery">Kézbesítés</string>
<string name="total_files_count_and_size">%d fájl %s összméretben</string>
<string name="database_passphrase_is_required">Adatbázis jelmondat szükséges chat megnyitásához.</string>
<string name="ttl_d">%dnap</string>
<string name="receipts_contacts_enable_for_all">Mindenki számára engedélyezve</string>
<string name="delivery_receipts_are_disabled">Kézbesítési izagolások kikapcsolva!</string>
<string name="delivery_receipts_are_disabled">Kézbesítési igazolások kikapcsolva!</string>
<string name="expand_verb">Lenyit</string>
<string name="error_sending_message">Hiba az üzenet küldésekor</string>
<string name="la_enter_app_passcode">Add Meg A Jelkódot</string>
<string name="for_everybody">Mindenkinek</string>
<string name="for_everybody">Mindenkinél</string>
<string name="encryption_renegotiation_error">Titkosítás újra egyeztetési hiba</string>
<string name="error_encrypting_database">Hiba az adatbázis titkosításakor</string>
<string name="error_deleting_group">Hiba a csoport törlésekor</string>
@@ -481,7 +481,7 @@
<string name="error_loading_xftp_servers">Hiba az XFTP szerverek betöltésekor</string>
<string name="error_loading_smp_servers">Hiba az SMP szerverek betöltésekor</string>
<string name="error_setting_network_config">Hiba a hálózat konfigurációjának frissítésekor</string>
<string name="network_option_enable_tcp_keep_alive">TCP életbentartás engedélyezése</string>
<string name="network_option_enable_tcp_keep_alive">TCP életben tartásának engedélyezése</string>
<string name="icon_descr_flip_camera">Kamera megfordítása</string>
<string name="email_invite_body">Szia!
\nCsatlakozz hozzám SimpleX Chaten: %s</string>
@@ -495,23 +495,23 @@
<string name="marked_deleted_items_description">%d üzenet megjelölve törlésre</string>
<string name="conn_event_ratchet_sync_allowed">titkosítás újra egyeztetése engedélyezve</string>
<string name="enable_self_destruct">Önmegsemmisítés engedélyezése</string>
<string name="v5_2_favourites_filter_descr">Olvasatlan és kedvenc chatekre szűrés.</string>
<string name="failed_to_parse_chats_title">Chatek betöltése sikertelen</string>
<string name="v5_2_favourites_filter_descr">Olvasatlan és kedvenc csevegésekre való szűrés.</string>
<string name="failed_to_parse_chats_title">A csevegések betöltése sikertelen</string>
<string name="connect_plan_group_already_exists">A csoport már létezik!</string>
<string name="v4_4_french_interface">Francia kezelőfelület</string>
<string name="v4_2_group_links">Csoport linkek</string>
<string name="v5_1_message_reactions_descr">Végre, megvannak! 🚀</string>
<string name="error_starting_chat">Hiba a chat elindításakor</string>
<string name="error_starting_chat">Hiba a csevegés elindításakor</string>
<string name="group_profile_is_stored_on_members_devices">A csoport profil a tagok eszközein tárolódik, nem a szervereken.</string>
<string name="enter_passphrase">Add meg a jelmondatot…</string>
<string name="error_updating_user_privacy">Hiba a felhasználói beállítások frissítésekor</string>
<string name="encrypt_database">Titkosít</string>
<string name="alert_title_no_group">Csoport nem található!</string>
<string name="error_saving_smp_servers">Hiba az SMP szerverek elmentésekor</string>
<string name="downgrade_and_open_chat">Downgrade és chat megnyitása</string>
<string name="downgrade_and_open_chat">Visszatérés a korábbi verzióra és a chat megnyitása</string>
<string name="icon_descr_group_inactive">A csoport inaktív</string>
<string name="v5_0_large_files_support_descr">Gyors és nincs várakozás a küldő online állapotára!</string>
<string name="error_joining_group">Hiba a csoporthoz csatlakozáskor</string>
<string name="v5_0_large_files_support_descr">Gyors és nem kell várni, amíg a feladó online lesz!</string>
<string name="error_joining_group">Hiba a csoporthoz való csatlakozáskor</string>
<string name="favorite_chat">Kedvenc</string>
<string name="v4_6_group_moderation">Csoport moderáció</string>
<string name="choose_file">Fájl</string>
@@ -521,7 +521,7 @@
<string name="settings_experimental_features">Kísérleti funkciók</string>
<string name="receipts_contacts_enable_keep_overrides">Engedélyezés (felülírások megtartásával)</string>
<string name="enter_correct_passphrase">Helyes jelmondat bevitele.</string>
<string name="delete_group_for_self_cannot_undo_warning">A csoport törlésre kerül számodra -ez visszafordíthatatlan!</string>
<string name="delete_group_for_self_cannot_undo_warning">A csoport törlésre kerül számodra - ez visszafordíthatatlan!</string>
<string name="encrypt_database_question">Adatbázis titkosítása?</string>
<string name="allow_accepting_calls_from_lock_screen">A zárolási képernyőn megjelenő hívások engedélyezése a Beállításokban.</string>
<string name="conn_event_ratchet_sync_agreed">titkosítás egyeztetve</string>
@@ -541,7 +541,7 @@
<string name="fix_connection_question">Kapcsolat javítása?</string>
<string name="files_and_media">Fájlok és médiatartalom</string>
<string name="section_title_for_console">A KONZOL SZÁMÁRA</string>
<string name="alert_text_encryption_renegotiation_failed">Titkosítás újra egyeztetés sikertelen.</string>
<string name="alert_text_encryption_renegotiation_failed">Titkosítás újra egyeztetése sikertelen.</string>
<string name="error_deleting_user">Hiba a felhasználói profil törlésekor</string>
<string name="fix_connection_not_supported_by_group_member">A javítás nem támogatott a csoporttag által</string>
<string name="enter_welcome_message">Írd be az üdvözlő üzenetet…</string>
@@ -551,7 +551,7 @@
<string name="smp_server_test_download_file">Fájl letöltése</string>
<string name="failed_to_parse_chat_title">Chat betöltése sikertelen</string>
<string name="smp_servers_enter_manually">Szerver megadása kézileg</string>
<string name="file_will_be_received_when_contact_is_online">A fájl megérkezik amint az ismerősöd online lesz, kélrlek várj vagy nézz vissza később!</string>
<string name="file_will_be_received_when_contact_is_online">A fájl megérkezik amint az ismerősöd online lesz, kérlek várj vagy nézz vissza később!</string>
<string name="error_creating_link_for_group">Hiba a csoport linkjének létrehozásakor</string>
<string name="from_gallery_button">A Galériából</string>
<string name="receipts_groups_enable_keep_overrides">Engedélyezés (csoport felülírások megtartásával)</string>
@@ -598,13 +598,13 @@
<string name="fix_connection_not_supported_by_contact">A javítás nem támogatott az ismerős által</string>
<string name="file_not_found">Fájl nem található</string>
<string name="smp_server_test_disconnect">Kapcsolat bontása</string>
<string name="group_members_can_add_message_reactions">A csoporttagok reagálhatnak emocikonokkal az üzenetekre.</string>
<string name="group_members_can_add_message_reactions">A csoporttagok reagálhatnak emojikkal az üzenetekre.</string>
<string name="export_database">Adatbázis exportálása</string>
<string name="full_name__field">Teljes név:</string>
<string name="v4_6_reduced_battery_usage">Tovább csökkentett akkumulátor használat</string>
<string name="error_stopping_chat">Hiba a chat megállításakor</string>
<string name="error_stopping_chat">Hiba a csevegés megállításakor</string>
<string name="snd_conn_event_ratchet_sync_ok">titkosítás rendben %s számára</string>
<string name="delete_group_for_all_members_cannot_undo_warning">Csoport törlésre kerül minen tag számára - ez visszafordíthatatlan!</string>
<string name="delete_group_for_all_members_cannot_undo_warning">Csoport törlésre kerül minden tag számára - ez visszafordíthatatlan!</string>
<string name="v5_2_fix_encryption_descr">Titkosítás javítása az adatmentések helyreállítása után.</string>
<string name="error_deleting_database">Hiba a chat adatbázis törlésekor</string>
<string name="simplex_link_mode_full">Teljes link</string>
@@ -614,14 +614,14 @@
<string name="error_with_info">Hiba: %s</string>
<string name="v4_4_disappearing_messages">Eltűnő üzenetek</string>
<string name="auth_enable_simplex_lock">SimpleX Zár engedélyezése</string>
<string name="error_synchronizing_connection">Hiba a kapcsolat szinkronizációjakor</string>
<string name="error_synchronizing_connection">Hiba a kapcsolat szinkronizálása során</string>
<string name="error_creating_address">Hiba az azonosító létrehozásakor</string>
<string name="feature_enabled">engedélyezve</string>
<string name="error_loading_details">Hiba a részletek betöltésekor</string>
<string name="error_accepting_contact_request">Hiba az ismerős kérés elfogadása</string>
<string name="error_accepting_contact_request">Hiba történt a kapcsolatfelvételi kérelem elfogadásakor</string>
<string name="snd_conn_event_ratchet_sync_allowed">%s ismerősöddel való titkosítás újra egyeztetése engedélyezve</string>
<string name="conn_event_ratchet_sync_required">titkosítás újra egyeztetés szükséges</string>
<string name="v4_6_hidden_chat_profiles">Rejtett chat profilok</string>
<string name="v4_6_hidden_chat_profiles">Rejtett csevegési profilok</string>
<string name="files_and_media_section">Fájlok és média</string>
<string name="image_saved">Fotók elmentve a fotóalbumba</string>
<string name="hide_notification">Elrejt</string>
@@ -629,7 +629,7 @@
<string name="files_and_media_prohibited">A fájlok- és a médiatartalom küldése le van tiltva!</string>
<string name="hide_profile">Profil elrejtése</string>
<string name="how_to_use_your_servers">Hogyan használd a szervereidet</string>
<string name="v5_2_favourites_filter">Találd meg a chat üzeneteket gyorsabban</string>
<string name="v5_2_favourites_filter">Találd meg a csevegési üzeneteket gyorsabban</string>
<string name="import_theme">Színséma importálása</string>
<string name="import_theme_error">Hiba a színséma importálásakor</string>
<string name="notification_display_mode_hidden_desc">Ismerős és üzenet elrejtése</string>
@@ -724,7 +724,7 @@
<string name="v5_4_link_mobile_desktop">Társítsd össze a mobil és az asztali alkalmazásokat! 🔗!</string>
<string name="conn_level_desc_indirect">közvetett (%1$s)</string>
<string name="v4_6_reduced_battery_usage_descr">Hamarosan további fejlesztések érkeznek!</string>
<string name="message_reactions_prohibited_in_this_chat">Az üzenetreakciók ebben a csevegésben tilosak.</string>
<string name="message_reactions_prohibited_in_this_chat">Az üzenetreakciók ebben a csevegésben le vannak tiltva.</string>
<string name="incorrect_code">Helytelen biztonsági kód!</string>
<string name="alert_text_fragment_encryption_out_of_sync_old_database">Ez akkor fordulhat elő, ha Te vagy az ismerősöd a régi adatbázis biztonsági másolatát használta.</string>
<string name="v5_3_new_desktop_app">Új asztali alkalmazás!</string>
@@ -732,7 +732,7 @@
\n- törölhetik a tagok üzeneteit.
\n- letilthatnak tagokat (\"megfigyelő\" szerepkör)</string>
<string name="rcv_group_event_member_added">%1$s meghívott</string>
<string name="message_reactions_are_prohibited">Az üzenetreakciók ebben a csoportban tilosak.</string>
<string name="message_reactions_are_prohibited">Az üzenetekre adott emoji reakciók ebben a csoportban le vannak tiltva.</string>
<string name="network_use_onion_hosts_no">Nem</string>
<string name="item_info_no_text">nincs szöveg</string>
<string name="member_info_section_title_member">TAG</string>
@@ -764,7 +764,7 @@
<string name="moderate_verb">Moderál</string>
<string name="chat_preferences_on">be</string>
<string name="v5_1_japanese_portuguese_interface">Japán és Portugál kezelőfelület</string>
<string name="message_deletion_prohibited_in_chat">Ebben a csoportban tilos az üzenetek visszafordíthatatlan törlése.</string>
<string name="message_deletion_prohibited_in_chat">Ebben a csoportban az üzenetek visszafordíthatatlan törlése le van tiltva.</string>
<string name="network_use_onion_hosts_no_desc_in_alert">Onion host-ok nem lesznek használva.</string>
<string name="remote_host_was_disconnected_toast"><![CDATA[A(z) <b>%s</b> eszközzel megszakadt a kapcsolat]]></string>
<string name="custom_time_unit_months">hónap</string>
@@ -774,7 +774,7 @@
<string name="videos_limit_desc">Egyszerre csak 10 videó küldhető el</string>
<string name="only_you_can_add_message_reactions">Csak te adhatsz hozzá üzenetreakciókat.</string>
<string name="group_member_status_left">elhagyta</string>
<string name="message_deletion_prohibited">Ebben a csevegésben tilos az üzenetek visszafordíthatatlan törlése.</string>
<string name="message_deletion_prohibited">Ebben a csevegésben az üzenetek visszafordíthatatlan törlése le van tiltva.</string>
<string name="v4_3_voice_messages_desc">Max 40 másodperc, azonnal fogadható.</string>
<string name="description_via_contact_address_link_incognito">inkognitó a kapcsolattartási címen keresztül</string>
<string name="network_use_onion_hosts_required_desc">A csatlakozáshoz Onion host-okra lesz szükség.
@@ -1090,7 +1090,7 @@
<string name="share_link">Link megosztása</string>
<string name="icon_descr_simplex_team">SimpleX Csapat</string>
<string name="image_descr_profile_image">profilkép</string>
<string name="your_chat_profiles">A te chat profiljaid</string>
<string name="your_chat_profiles">A te csevegési profiljaid</string>
<string name="group_member_role_owner">tulajdonos</string>
<string name="la_notice_turn_on">Bekapcsolás</string>
<string name="rcv_group_event_3_members_connected">%s, %s és %s csatlakozott</string>
@@ -1242,7 +1242,7 @@
<string name="send_verb">Küldés</string>
<string name="la_lock_mode_system">Rendszer hitelesítés</string>
<string name="simplex_link_mode_browser">Böngészőn keresztül</string>
<string name="v4_6_hidden_chat_profiles_descr">A chat profiljaid védelme jelszóval!</string>
<string name="v4_6_hidden_chat_profiles_descr">A csevegési profiljaid védelme jelszóval!</string>
<string name="only_your_contact_can_send_disappearing">Kizárólag az ismerősöd tud eltűnő üzeneteket küldeni.</string>
<string name="your_ICE_servers">A te ICE szervereid</string>
<string name="scan_qr_code_from_desktop">QR-kód beolvasása asztali számítógépről</string>
@@ -1259,7 +1259,7 @@
<string name="share_text_received_at">Fogadva ekkor: %s</string>
<string name="la_notice_title_simplex_lock">SimpleX Zár</string>
<string name="save_and_notify_group_members">Mentés és a csoporttagok értesítése</string>
<string name="reset_verb">Alaphelyzetbe álítás</string>
<string name="reset_verb">Alaphelyzetbe állítás</string>
<string name="only_your_contact_can_add_message_reactions">Kizárólag az ismerősöd tud emoji reakciókat adni az üzenetekre.</string>
<string name="voice_messages">Hangüzenetek</string>
<string name="snd_group_event_user_left">te távoztál</string>
@@ -1407,7 +1407,7 @@
<string name="you_will_still_receive_calls_and_ntfs">Továbbra is kapsz hívásokat és értesítéseket az elnémított profilokból amikor azok aktívak.</string>
<string name="group_main_profile_sent">A saját fő chat profilod megküldésre kerül a csoporttagok számára.</string>
<string name="you_can_enable_delivery_receipts_later_alert">Később engedélyezheted az alkalmazás Adatvédelmi és Biztonsági beállításaiban.</string>
<string name="to_reveal_profile_enter_password">A rejtett profilod felfedéséhez gépeld be a jelszót a kereső mezőbe a Chat profiljaid oldalon!</string>
<string name="to_reveal_profile_enter_password">A rejtett profilod felfedéséhez gépeld be a jelszót a kereső mezőbe az \'A te csevegési profiljaid\' menüben!</string>
<string name="upgrade_and_open_chat">A chat frissítése és megnyitása</string>
<string name="you_need_to_allow_to_send_voice">Ahhoz, hogy hangüzeneteket küldhess, engedélyezned kell az ismerőseidnek is azok küldését.</string>
<string name="you_control_servers_to_receive_your_contacts_to_send"><![CDATA[Te kontrollálod, hogy melyik szerveren(-ken) keresztül <b>fogadod</b>az üzeneteket, míg az ismerőseid a szervereket amelyeken át üzensz nekik.]]></string>
@@ -1539,7 +1539,7 @@
<string name="retry_verb">Újrapróbálkozás</string>
<string name="camera_not_available">A kamera nem elérhető</string>
<string name="enable_sending_recent_history">Utolsó 100 üzenet küldése új tagoknak.</string>
<string name="disable_sending_recent_history">Ne küldjön előzményeket új tagoknak.</string>
<string name="disable_sending_recent_history">Ne küldjön előzményeket az új tagoknak.</string>
<string name="or_show_this_qr_code">Vagy mutassa meg ezt a kódot</string>
<string name="enable_camera_access">Kamera hozzáférés engedélyezése</string>
<string name="keep_unused_invitation_question">Megtartod a fel nem használt meghívót?</string>
@@ -1550,7 +1550,7 @@
<string name="or_scan_qr_code">Vagy QR-kód beolvasása</string>
<string name="invalid_qr_code">Érvénytelen QR-kód</string>
<string name="keep_invitation_link">Megtart</string>
<string name="search_or_paste_simplex_link">Keresés vagy SimpleX link beillesztése</string>
<string name="search_or_paste_simplex_link">Keresés, vagy SimpleX link beillesztése</string>
<string name="show_internal_errors">Belső hibák megjelenítése</string>
<string name="agent_critical_error_title">Kritikus hiba</string>
<string name="agent_internal_error_title">Belső hiba</string>
@@ -1627,4 +1627,8 @@
<string name="unblock_for_all_question">Mindenki számára feloldod ennek a tagnak a letiltását?</string>
<string name="snd_group_event_member_blocked">letiltottad %s-t</string>
<string name="error_blocking_member_for_all">Hiba a tag mindenki számára való letiltása során</string>
<string name="message_too_large">Az üzenet túl nagy</string>
<string name="welcome_message_is_too_long">Az üdvözlő üzenet túl hosszú</string>
<string name="database_migration_in_progress">Az adatbázis migrációja folyamatban van.
\nEz eltarthat néhány percig.</string>
</resources>

View File

@@ -1355,7 +1355,7 @@
<string name="turn_off_system_restriction_button">Apri impostazioni app</string>
<string name="system_restricted_background_in_call_desc">L\'app potrebbe venire chiusa dopo 1 minuto in secondo piano.</string>
<string name="paste_the_link_you_received_to_connect_with_your_contact">Incolla il link che hai ricevuto per connetterti con il contatto…</string>
<string name="connect__your_profile_will_be_shared">Il tuo profilo %1$s verrà condiviso.</string>
<string name="connect__your_profile_will_be_shared">Verrà condiviso il tuo profilo %1$s.</string>
<string name="connect__a_new_random_profile_will_be_shared">Verrà condiviso un nuovo profilo casuale.</string>
<string name="disable_notifications_button">Disattiva le notifiche</string>
<string name="system_restricted_background_in_call_title">Nessuna chiamata in secondo piano</string>
@@ -1632,4 +1632,6 @@
<string name="block_for_all_question">Bloccare il membro per tutti?</string>
<string name="error_blocking_member_for_all">Errore nel blocco del membro per tutti</string>
<string name="snd_group_event_member_blocked">hai bloccato %s</string>
<string name="welcome_message_is_too_long">Il messaggio di benvenuto è troppo lungo</string>
<string name="message_too_large">Messaggio troppo grande</string>
</resources>

View File

@@ -1551,7 +1551,7 @@
<string name="tap_to_scan">Tik om te scannen</string>
<string name="keep_invitation_link">Bewaar</string>
<string name="tap_to_paste_link">Tik om de link te plakken</string>
<string name="search_or_paste_simplex_link">Zoek of plak een SimpleX link</string>
<string name="search_or_paste_simplex_link">Zoeken of plak een SimpleX link</string>
<string name="chat_is_stopped_you_should_transfer_database">De chat is gestopt. Als u deze database al op een ander apparaat heeft gebruikt, moet u deze terugzetten voordat u met chatten begint.</string>
<string name="start_chat_question">Begin chat?</string>
<string name="show_internal_errors">Toon interne fouten</string>

View File

@@ -238,7 +238,7 @@
<string name="icon_descr_call_progress">Arama yapılıyor</string>
<string name="icon_descr_call_rejected">Geri çevrilmiş çağrı</string>
<string name="icon_descr_call_ended">Görüşme bitti.</string>
<string name="alert_text_decryption_error_too_many_skipped">%1$d mesajlar atlanıldı.</string>
<string name="alert_text_decryption_error_too_many_skipped">%1$d mesaj atlanıldı.</string>
<string name="chat_database_deleted">Sohbet veritabanı silindi</string>
<string name="error_with_info">Hata: %s</string>
<string name="unknown_error">Bilinmeyen hata</string>
@@ -1306,7 +1306,7 @@
<string name="receipts_contacts_override_enabled">Alıcılar %d bağlantıları için etkinleştirilecektir</string>
<string name="moderate_message_will_be_marked_warning">Mesaj herkes için yönetilmiş olarak işaretlenecek.</string>
<string name="connect_plan_this_is_your_own_one_time_link">Bu senin kendi tek-kullanımlık bağlantın!</string>
<string name="marked_deleted_items_description">%d mesajları silinmiş olarak işaretlendi</string>
<string name="marked_deleted_items_description">%d mesaj silinmiş olarak işaretlendi</string>
<string name="connect_use_new_incognito_profile">Yeni sahte profil kullan</string>
<string name="chat_is_stopped_you_should_transfer_database">Sohbet durduruldu. Eğer çoktan başka bir cihazda bu veritabanını kullandıysan,sohbeti başlatmadan önce veritabanını geri aktarmalısın.</string>
<string name="send_link_previews">Bağlantı ön izlemelerini gönder</string>
@@ -1359,7 +1359,7 @@
<string name="share_text_sent_at">%s de gönderildi</string>
<string name="enable_sending_recent_history">Yeni katılımcılara 100e kadar son mesajlar gönder</string>
<string name="moderate_verb">Yönet</string>
<string name="moderated_items_description">%1$d mesajları %2$s tarafından yönetildi</string>
<string name="moderated_items_description">%1$d mesaj %2$s tarafından yönetildi</string>
<string name="remove_passphrase_from_settings">Ayarlardaki parola silinsin mi?</string>
<string name="receipts_contacts_title_enable">Alıcılar etkinleştirilsin mi?</string>
<string name="tap_to_start_new_chat">Yeni bir sohbet başlatmak için tıkla</string>
@@ -1429,7 +1429,7 @@
<string name="set_database_passphrase">Veritabanı parolası ayarla</string>
<string name="share_this_1_time_link">Bu tek-kullanımlık davet bağlantısını paylaş</string>
<string name="unblock_member_question">Kişinin engeli kaldırılsın mı?</string>
<string name="blocked_items_description">%d mesajları engellendi</string>
<string name="blocked_items_description">%d mesaj engellendi</string>
<string name="create_group_button_to_create_new_group"><![CDATA[<b>Grup oluştur</b>: yeni bir grup oluşturmak için.]]></string>
<string name="icon_descr_video_asked_to_receive">Videoyu almak için soruldu</string>
<string name="open_port_in_firewall_desc">Telefon uygulamanın bilgisayarına bağlanmasına izin vermek için, güvenlik duvarın etkin ise bu portu aç</string>
@@ -1554,4 +1554,85 @@
<string name="color_received_message">Alınmış mesaj</string>
<string name="rcv_group_event_member_created_contact">doğrudan bağlandı</string>
<string name="blocked_item_description">engellendi</string>
<string name="v5_5_private_notes">Gizli notlar</string>
<string name="v5_5_message_delivery_descr">Azaltılmış pil kullanımı ile birlikte.</string>
<string name="v5_5_message_delivery">İyileştirilmiş mesaj iletimi</string>
<string name="v5_5_new_interface_languages">Macarca ve Türkçe arayüz</string>
<string name="remote_host_error_timeout">Telefona bağlanırken zaman aşımına uğranıldı <b>%s</b></string>
<string name="remote_host_error_disconnected">Telefon <b>%s</b> bağlantısı kesildi</string>
<string name="remote_ctrl_error_disconnected">Masaüstünün bağlantısı kesilmiş</string>
<string name="blocked_by_admin_item_description">yönetici tarafından engellendi</string>
<string name="blocked_by_admin_items_description">%d mesaj yönetici tarafından engellendi</string>
<string name="clear_note_folder_question">Gizli notlar temizlensin mi?</string>
<string name="clear_note_folder_warning">Tüm mesajlar silinecektir - bu geri alınamaz!</string>
<string name="developer_options_section">Geliştirici seçenekleri</string>
<string name="show_internal_errors">Dahili hataları göster</string>
<string name="show_slow_api_calls">Yavaş API aramalarını göster</string>
<string name="rcv_group_event_member_blocked">engellendi %s</string>
<string name="rcv_group_event_member_unblocked">engeli kaldırıldı %s</string>
<string name="group_member_status_unknown_short">bilinmeyen</string>
<string name="group_member_status_unknown">bilinmeyen durum</string>
<string name="snd_group_event_member_blocked">engelledin %s</string>
<string name="snd_group_event_member_unblocked">engeli kaldırdın %s</string>
<string name="past_member_vName">Geçmiş üye %1$s</string>
<string name="member_blocked_by_admin">Yönetici tarafından engellendi</string>
<string name="block_for_all">Herkes için engelle</string>
<string name="info_row_created_at">Şurada oluşturuldu</string>
<string name="share_text_created_at">Şurada oluşturuldu: %s</string>
<string name="error_blocking_member_for_all">Üye herkes için engellenirken hata oluştu</string>
<string name="unblock_for_all">Herkes için engelini kaldır</string>
<string name="saved_message_title">Kaydedilmiş mesaj</string>
<string name="remote_host_was_disconnected_title">Bağlantı durduruldu</string>
<string name="remote_host_error_bad_state">Telefona bağlantı <b>%s</b> kötü durumda</string>
<string name="remote_host_disconnected_from">Telefon bağlantısı <b>%s</b> şu nedenle kesildi: %s</string>
<string name="remote_ctrl_disconnected_with_reason">Nedeniyle birlikte bağlantı kesildi: %s</string>
<string name="v5_5_private_notes_descr">Şifrelenmiş dosyalar ve medya ile birlikte.</string>
<string name="v5_5_join_group_conversation">Grup sohbetlerine katıl</string>
<string name="v5_5_simpler_connect_ui">Bağlanmak için bağlantıyı yapıştır!</string>
<string name="remote_ctrl_error_timeout">Masaüstüne bağlanırken zaman aşımına ulaşıldı</string>
<string name="v5_5_join_group_conversation_descr">Yakın tarih ve geliştirilmiş dizin botu.</string>
<string name="v5_5_simpler_connect_ui_descr">Arama çubuğu davet bağlantılarını kabul eder.</string>
<string name="member_info_member_blocked">engellendi</string>
<string name="block_for_all_question">Üye herkes için engellensin mi?</string>
<string name="unblock_for_all_question">Üyenin engeli herkes için kaldırılsın mı?</string>
<string name="remote_host_error_bad_version">Mobil <b>%s</b> desteklenmeyen bir sürüme sahip. Lütfen her iki cihazda da aynı sürümü kullandığınızdan emin olun</string>
<string name="remote_host_error_busy">Telefon <b>%s</b> meşgul</string>
<string name="remote_host_error_inactive">Telefon <b>%s</b> aktif değil</string>
<string name="remote_host_error_missing">Telefon <b>%s</b> kayıp</string>
<string name="remote_ctrl_error_inactive">Masaüstü aktif değil</string>
<string name="remote_ctrl_error_bad_state">Masaüstüne bağlantı kötü durumda</string>
<string name="remote_ctrl_error_busy">Masaüstü meşgul</string>
<string name="remote_ctrl_error_bad_version">Masaüstü desteklenmeyen bir sürüme sahiptir. Lütfen her iki cihazda da aynı sürümü kullandığınızdan emin olun</string>
<string name="agent_critical_error_title">Kritik hata</string>
<string name="remote_ctrl_error_bad_invitation">Masaüstünün yanlış davetiye kodu var</string>
<string name="agent_internal_error_title">Dahili hata</string>
<string name="agent_internal_error_desc">Lütfen geliştiricilere bildir:
\n
\n%s</string>
<string name="agent_critical_error_desc">Lütfen geliştiricilere bildir:
\n
\n%s
\n
\nUygulamayı yeniden başlatmak önerilir.</string>
<string name="restart_chat_button">Sohbeti yeniden başlat</string>
<string name="failed_to_create_user_invalid_desc">Bu görünen ad geçersiz.
\nLütfen başka bir ad seç.</string>
<string name="failed_to_create_user_invalid_title">Geçersiz görünen ad!</string>
<string name="remote_ctrl_was_disconnected_title">Bağlantı durduruldu</string>
<string name="possible_deadlock_title">Kördüğüm</string>
<string name="possible_deadlock_desc">Kodun yürütülmesi çok uzun zaman alıyor: %1$d saniye. Muhtemelen uygulama dondu: %2$s</string>
<string name="possible_slow_function_desc">İşlevin yürütülmesi çok uzun zaman alıyor: %1$d saniye: %2$s</string>
<string name="possible_slow_function_title">Yavaş fonksiyon</string>
<string name="profile_update_event_contact_name_changed">kişi %1$s olarak değişti %2$s</string>
<string name="profile_update_event_updated_profile">güncellenmiş profil</string>
<string name="profile_update_event_member_name_changed">üye %1$s olarak değişti %2$s</string>
<string name="profile_update_event_set_new_address">yeni kişi adresi ayarla</string>
<string name="profile_update_event_set_new_picture">yeni profil fotoğrafı ayarla</string>
<string name="profile_update_event_removed_address">kişi adresi silindi</string>
<string name="profile_update_event_removed_picture">profil fotoğrafı silindi</string>
<string name="error_creating_message">Mesaj oluşturulurken hata</string>
<string name="error_deleting_note_folder">Gizli notlar silinirken hata</string>
<string name="note_folder_local_display_name">Gizli notlar</string>
<string name="welcome_message_is_too_long">Hoşgeldin mesajı çok uzun</string>
<string name="message_too_large">Mesaj çok büyük</string>
</resources>

View File

@@ -1632,4 +1632,8 @@
<string name="member_info_member_blocked">已封禁</string>
<string name="snd_group_event_member_blocked">你封禁了 %s</string>
<string name="snd_group_event_member_unblocked">你解封了 %s</string>
<string name="welcome_message_is_too_long">欢迎消息太大了</string>
<string name="database_migration_in_progress">正在进行数据库迁移。
\n可能需要几分钟时间。</string>
<string name="message_too_large">消息太大了</string>
</resources>

View File

@@ -8,7 +8,6 @@
<body>
<video
id="remote-video-stream"
class="inline"
autoplay
playsinline
poster="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAEUlEQVR42mNk+M+AARiHsiAAcCIKAYwFoQ8AAAAASUVORK5CYII="
@@ -16,7 +15,6 @@
></video>
<video
id="local-video-stream"
class="inline"
muted
autoplay
playsinline

View File

@@ -5,14 +5,14 @@ body {
background-color: black;
}
#remote-video-stream.inline {
#remote-video-stream {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
#local-video-stream.inline {
#local-video-stream {
position: absolute;
width: 30%;
max-width: 30%;
@@ -23,20 +23,6 @@ body {
right: 0;
}
#remote-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
#local-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
*::-webkit-media-controls {
display: none !important;
-webkit-appearance: none !important;

View File

@@ -11,12 +11,6 @@ var VideoCamera;
VideoCamera["User"] = "user";
VideoCamera["Environment"] = "environment";
})(VideoCamera || (VideoCamera = {}));
var LayoutType;
(function (LayoutType) {
LayoutType["Default"] = "default";
LayoutType["LocalVideo"] = "localVideo";
LayoutType["RemoteVideo"] = "remoteVideo";
})(LayoutType || (LayoutType = {}));
// for debugging
// var sendMessageToNative = ({resp}: WVApiMessage) => console.log(JSON.stringify({command: resp}))
var sendMessageToNative = (msg) => console.log(JSON.stringify(msg));
@@ -325,10 +319,6 @@ const processCommand = (function () {
localizedDescription = command.description;
resp = { type: "ok" };
break;
case "layout":
changeLayout(command.layout);
resp = { type: "ok" };
break;
case "end":
endCall();
resp = { type: "ok" };
@@ -617,28 +607,6 @@ function toggleMedia(s, media) {
}
return res;
}
function changeLayout(layout) {
const local = document.getElementById("local-video-stream");
const remote = document.getElementById("remote-video-stream");
switch (layout) {
case LayoutType.Default:
local.className = "inline";
remote.className = "inline";
local.style.visibility = "visible";
remote.style.visibility = "visible";
break;
case LayoutType.LocalVideo:
local.className = "fullscreen";
local.style.visibility = "visible";
remote.style.visibility = "hidden";
break;
case LayoutType.RemoteVideo:
remote.className = "fullscreen";
local.style.visibility = "hidden";
remote.style.visibility = "visible";
break;
}
}
// Cryptography function - it is loaded both in the main window and in worker context (if the worker is used)
function callCryptoFunction() {
const initialPlainTextRequired = {

View File

@@ -9,7 +9,6 @@
<body>
<video
id="remote-video-stream"
class="inline"
autoplay
playsinline
poster="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAEUlEQVR42mNk+M+AARiHsiAAcCIKAYwFoQ8AAAAASUVORK5CYII="
@@ -17,7 +16,6 @@
></video>
<video
id="local-video-stream"
class="inline"
muted
autoplay
playsinline

View File

@@ -5,14 +5,14 @@ body {
background-color: black;
}
#remote-video-stream.inline {
#remote-video-stream {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
#local-video-stream.inline {
#local-video-stream {
position: absolute;
width: 20%;
max-width: 20%;
@@ -23,20 +23,6 @@ body {
right: 0;
}
#remote-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
#local-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
*::-webkit-media-controls {
display: none !important;
-webkit-appearance: none !important;

View File

@@ -17,14 +17,14 @@ import javax.imageio.stream.MemoryCacheImageOutputStream
import kotlin.math.sqrt
private fun errorBitmap(): ImageBitmap =
ImageIO.read(ByteArrayInputStream(Base64.getMimeDecoder().decode("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAKVJREFUeF7t1kENACEUQ0FQhnVQ9lfGO+xggITQdvbMzArPey+8fa3tAfwAEdABZQspQStgBssEcgAIkSAJkiAJljtEgiRIgmUCSZAESZAESZAEyx0iQRIkwTKBJEiCv5fgvTd1wDmn7QAP4AeIgA4oW0gJWgEzWCZwbQ7gAA7ggLKFOIADOKBMIAeAEAmSIAmSYLlDJEiCJFgmkARJkARJ8N8S/ADTZUewBvnTOQAAAABJRU5ErkJggg=="))).toComposeImageBitmap()
ImageIO.read(ByteArrayInputStream(Base64.getDecoder().decode("iVBORw0KGgoAAAANSUhEUgAAAEAAAABACAYAAACqaXHeAAAAAXNSR0IArs4c6QAAAKVJREFUeF7t1kENACEUQ0FQhnVQ9lfGO+xggITQdvbMzArPey+8fa3tAfwAEdABZQspQStgBssEcgAIkSAJkiAJljtEgiRIgmUCSZAESZAESZAEyx0iQRIkwTKBJEiCv5fgvTd1wDmn7QAP4AeIgA4oW0gJWgEzWCZwbQ7gAA7ggLKFOIADOKBMIAeAEAmSIAmSYLlDJEiCJFgmkARJkARJ8N8S/ADTZUewBvnTOQAAAABJRU5ErkJggg=="))).toComposeImageBitmap()
actual fun base64ToBitmap(base64ImageString: String): ImageBitmap {
val imageString = base64ImageString
.removePrefix("data:image/png;base64,")
.removePrefix("data:image/jpg;base64,")
return try {
ImageIO.read(ByteArrayInputStream(Base64.getMimeDecoder().decode(imageString))).toComposeImageBitmap()
ImageIO.read(ByteArrayInputStream(Base64.getDecoder().decode(imageString))).toComposeImageBitmap()
} catch (e: IOException) {
Log.e(TAG, "base64ToBitmap error: $e")
errorBitmap()
@@ -77,7 +77,7 @@ actual fun compressImageStr(bitmap: ImageBitmap): String {
return try {
val encoded = Base64.getEncoder().encodeToString(compressImageData(bitmap, usePng).toByteArray())
"data:image/$ext;base64,$encoded"
} catch (e: Exception) {
} catch (e: IOException) {
Log.e(TAG, "resizeImageToStrSize error: $e")
throw e
}

View File

@@ -146,21 +146,8 @@ private fun SendStateUpdates() {
@Composable
fun WebRTCController(callCommand: SnapshotStateList<WCallCommand>, onResponse: (WVAPIMessage) -> Unit) {
val uriHandler = LocalUriHandler.current
val endCall = {
val call = chatModel.activeCall.value
if (call != null) withBGApi { chatModel.callManager.endCall(call) }
}
val server = remember {
try {
uriHandler.openUri("http://${SERVER_HOST}:$SERVER_PORT/simplex/call/")
} catch (e: Exception) {
Log.e(TAG, "Unable to open browser: ${e.stackTraceToString()}")
AlertManager.shared.showAlertMsg(
title = generalGetString(MR.strings.unable_to_open_browser_title),
text = generalGetString(MR.strings.unable_to_open_browser_desc)
)
endCall()
}
uriHandler.openUri("http://${SERVER_HOST}:$SERVER_PORT/simplex/call/")
startServer(onResponse)
}
fun processCommand(cmd: WCallCommand) {

View File

@@ -3,6 +3,7 @@ package chat.simplex.common.views.chatlist
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.Icon
import androidx.compose.material.MaterialTheme
import androidx.compose.runtime.*
@@ -12,7 +13,6 @@ import androidx.compose.ui.graphics.Color
import androidx.compose.ui.unit.dp
import chat.simplex.common.platform.*
import chat.simplex.common.ui.theme.*
import chat.simplex.common.views.call.Call
import chat.simplex.common.views.call.CallMediaType
import chat.simplex.common.views.chat.item.ItemAction
import chat.simplex.common.views.helpers.*
@@ -22,9 +22,10 @@ import dev.icerock.moko.resources.compose.stringResource
import kotlinx.coroutines.flow.MutableStateFlow
@Composable
actual fun ActiveCallInteractiveArea(call: Call, newChatSheetState: MutableStateFlow<AnimatedViewState>) {
// if (call.callState == CallState.Connected && !newChatSheetState.collectAsState().value.isVisible()) {
if (!newChatSheetState.collectAsState().value.isVisible()) {
actual fun DesktopActiveCallOverlayLayout(newChatSheetState: MutableStateFlow<AnimatedViewState>) {
val call = remember { chatModel.activeCall}.value
// if (call?.callState == CallState.Connected && !newChatSheetState.collectAsState().value.isVisible()) {
if (call != null && !newChatSheetState.collectAsState().value.isVisible()) {
val showMenu = remember { mutableStateOf(false) }
val media = call.peerMedia ?: call.localMedia
CompositionLocalProvider(

View File

@@ -25,11 +25,11 @@ android.nonTransitiveRClass=true
android.enableJetifier=true
kotlin.mpp.androidSourceSetLayoutVersion=2
android.version_name=5.5.3
android.version_code=181
android.version_name=5.5
android.version_code=175
desktop.version_name=5.5.3
desktop.version_code=29
desktop.version_name=5.5
desktop.version_code=26
kotlin.version=1.8.20
gradle.plugin.version=7.4.2

View File

@@ -12,7 +12,7 @@ constraints: zip +disable-bzip2 +disable-zstd
source-repository-package
type: git
location: https://github.com/simplex-chat/simplexmq.git
tag: e64b6cba4b7e4107f78ae596ab2a6a28ef24ff78
tag: 7a0cd8041bbb7d7ab2f089395a244dc4af0f9e3b
source-repository-package
type: git

695
flake.lock generated
View File

@@ -16,21 +16,6 @@
"type": "github"
}
},
"blank": {
"locked": {
"lastModified": 1625557891,
"narHash": "sha256-O8/MWsPBGhhyPoPLHZAuoZiiHo9q6FLlEeIDEXuj6T4=",
"owner": "divnix",
"repo": "blank",
"rev": "5a5d2684073d9f563072ed07c871d577a6c614a8",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "blank",
"type": "github"
}
},
"cabal-32": {
"flake": false,
"locked": {
@@ -98,64 +83,6 @@
"type": "github"
}
},
"devshell": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1663445644,
"narHash": "sha256-+xVlcK60x7VY1vRJbNUEAHi17ZuoQxAIH4S4iUFUGBA=",
"owner": "numtide",
"repo": "devshell",
"rev": "e3dc3e21594fe07bdb24bdf1c8657acaa4cb8f66",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "devshell",
"type": "github"
}
},
"dmerge": {
"inputs": {
"nixlib": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
],
"yants": [
"haskellNix",
"tullia",
"std",
"yants"
]
},
"locked": {
"lastModified": 1659548052,
"narHash": "sha256-fzI2gp1skGA8mQo/FBFrUAtY0GQkAIAaV/V127TJPyY=",
"owner": "divnix",
"repo": "data-merge",
"rev": "d160d18ce7b1a45b88344aa3f13ed1163954b497",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "data-merge",
"type": "github"
}
},
"flake-compat": {
"flake": false,
"locked": {
@@ -173,74 +100,34 @@
"type": "github"
}
},
"flake-compat_2": {
"flake": false,
"flake-parts": {
"inputs": {
"nixpkgs-lib": "nixpkgs-lib"
},
"locked": {
"lastModified": 1650374568,
"narHash": "sha256-Z+s0J8/r907g149rllvwhb4pKi8Wam5ij0st8PwAh+E=",
"owner": "edolstra",
"repo": "flake-compat",
"rev": "b4a34015c698c7793d592d66adbab377907a2be8",
"lastModified": 1698579227,
"narHash": "sha256-KVWjFZky+gRuWennKsbo6cWyo7c/z/VgCte5pR9pEKg=",
"owner": "hercules-ci",
"repo": "flake-parts",
"rev": "f76e870d64779109e41370848074ac4eaa1606ec",
"type": "github"
},
"original": {
"owner": "edolstra",
"repo": "flake-compat",
"owner": "hercules-ci",
"repo": "flake-parts",
"type": "github"
}
},
"flake-utils": {
"locked": {
"lastModified": 1676283394,
"narHash": "sha256-XX2f9c3iySLCw54rJ/CZs+ZK6IQy7GXNY4nSOyu2QG4=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "3db36a8b464d0c4532ba1c7dda728f4576d6d073",
"type": "github"
"inputs": {
"systems": "systems"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_2": {
"locked": {
"lastModified": 1667395993,
"narHash": "sha256-nuEHfE/LcWyuSWnS8t12N1wc105Qtau+/OdUAjtQ0rA=",
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "5aed5285a952e0b949eb3ba02c12fa4fcfef535f",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_4": {
"locked": {
"lastModified": 1659877975,
"narHash": "sha256-zllb8aq3YO3h8B/U0/J1WBgAL8EX5yWf5pMj3G0NAmc=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "c0e246b9b83f637f4681389ecabcb2681b4f3af0",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"type": "github"
},
"original": {
@@ -266,33 +153,51 @@
"type": "github"
}
},
"gomod2nix": {
"inputs": {
"nixpkgs": "nixpkgs_2",
"utils": "utils"
},
"ghc98X": {
"flake": false,
"locked": {
"lastModified": 1655245309,
"narHash": "sha256-d/YPoQ/vFn1+GTmSdvbSBSTOai61FONxB4+Lt6w/IVI=",
"owner": "tweag",
"repo": "gomod2nix",
"rev": "40d32f82fc60d66402eb0972e6e368aeab3faf58",
"type": "github"
"lastModified": 1696643148,
"narHash": "sha256-E02DfgISH7EvvNAu0BHiPvl1E5FGMDi0pWdNZtIBC9I=",
"ref": "ghc-9.8",
"rev": "443e870d977b1ab6fc05f47a9a17bc49296adbd6",
"revCount": 61642,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"owner": "tweag",
"repo": "gomod2nix",
"type": "github"
"ref": "ghc-9.8",
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"ghc99": {
"flake": false,
"locked": {
"lastModified": 1697054644,
"narHash": "sha256-kKarOuXUaAH3QWv7ASx+gGFMHaHKe0pK5Zu37ky2AL4=",
"ref": "refs/heads/master",
"rev": "f383a242c76f90bcca8a4d7ee001dcb49c172a9a",
"revCount": 62040,
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
},
"original": {
"submodules": true,
"type": "git",
"url": "https://gitlab.haskell.org/ghc/ghc"
}
},
"hackage": {
"flake": false,
"locked": {
"lastModified": 1702340598,
"narHash": "sha256-CC0HI+6iKPtH+8r/ZfcpW5v/OYvL7zMwpr0xfkXV1zU=",
"lastModified": 1702513363,
"narHash": "sha256-kloro9uEe8aYhPMoMjVNq2rfrXNgMOZhOPwVH5DH2K0=",
"owner": "input-output-hk",
"repo": "hackage.nix",
"rev": "24617c569995e38bf3b83b48eec6628a50fdb4fb",
"rev": "a9d931d0398da67846fa257922a924829233cb91",
"type": "github"
},
"original": {
@@ -309,33 +214,40 @@
"cabal-36": "cabal-36",
"cardano-shell": "cardano-shell",
"flake-compat": "flake-compat",
"flake-utils": "flake-utils_2",
"ghc-8.6.5-iohk": "ghc-8.6.5-iohk",
"ghc98X": "ghc98X",
"ghc99": "ghc99",
"hackage": [
"hackage"
],
"hls-1.10": "hls-1.10",
"hls-2.0": "hls-2.0",
"hls-2.2": "hls-2.2",
"hls-2.3": "hls-2.3",
"hls-2.4": "hls-2.4",
"hpc-coveralls": "hpc-coveralls",
"hydra": "hydra",
"iserv-proxy": "iserv-proxy",
"nixpkgs": [
"nixpkgs"
"haskellNix",
"nixpkgs-unstable"
],
"nixpkgs-2003": "nixpkgs-2003",
"nixpkgs-2105": "nixpkgs-2105",
"nixpkgs-2111": "nixpkgs-2111",
"nixpkgs-2205": "nixpkgs-2205",
"nixpkgs-2211": "nixpkgs-2211",
"nixpkgs-2305": "nixpkgs-2305",
"nixpkgs-unstable": "nixpkgs-unstable",
"old-ghc-nix": "old-ghc-nix",
"stackage": "stackage",
"tullia": "tullia"
"stackage": "stackage"
},
"locked": {
"lastModified": 1677975916,
"narHash": "sha256-dbe8lEEPyfzjdRwpePClv7J9p9lQg7BwbBqAMCw4RLw=",
"lastModified": 1701163700,
"narHash": "sha256-sOrewUS3LnzV09nGr7+3R6Q6zsgU4smJc61QsHq+4DE=",
"owner": "input-output-hk",
"repo": "haskell.nix",
"rev": "ab5efd87ce3fd8ade38a01d97693d29a4f1ae7e4",
"rev": "2808bfe3e62e9eb4ee8974cd623a00e1611f302b",
"type": "github"
},
"original": {
@@ -345,6 +257,91 @@
"type": "github"
}
},
"hls-1.10": {
"flake": false,
"locked": {
"lastModified": 1680000865,
"narHash": "sha256-rc7iiUAcrHxwRM/s0ErEsSPxOR3u8t7DvFeWlMycWgo=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b08691db779f7a35ff322b71e72a12f6e3376fd9",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "1.10.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.0": {
"flake": false,
"locked": {
"lastModified": 1687698105,
"narHash": "sha256-OHXlgRzs/kuJH8q7Sxh507H+0Rb8b7VOiPAjcY9sM1k=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "783905f211ac63edf982dd1889c671653327e441",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.0.0.1",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.2": {
"flake": false,
"locked": {
"lastModified": 1693064058,
"narHash": "sha256-8DGIyz5GjuCFmohY6Fa79hHA/p1iIqubfJUTGQElbNk=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "b30f4b6cf5822f3112c35d14a0cba51f3fe23b85",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.2.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.3": {
"flake": false,
"locked": {
"lastModified": 1695910642,
"narHash": "sha256-tR58doOs3DncFehHwCLczJgntyG/zlsSd7DgDgMPOkI=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "458ccdb55c9ea22cd5d13ec3051aaefb295321be",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.3.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hls-2.4": {
"flake": false,
"locked": {
"lastModified": 1696939266,
"narHash": "sha256-VOMf5+kyOeOmfXTHlv4LNFJuDGa7G3pDnOxtzYR40IU=",
"owner": "haskell",
"repo": "haskell-language-server",
"rev": "362fdd1293efb4b82410b676ab1273479f6d17ee",
"type": "github"
},
"original": {
"owner": "haskell",
"ref": "2.4.0.0",
"repo": "haskell-language-server",
"type": "github"
}
},
"hpc-coveralls": {
"flake": false,
"locked": {
@@ -384,37 +381,14 @@
"type": "indirect"
}
},
"incl": {
"inputs": {
"nixlib": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1669263024,
"narHash": "sha256-E/+23NKtxAqYG/0ydYgxlgarKnxmDbg6rCMWnOBqn9Q=",
"owner": "divnix",
"repo": "incl",
"rev": "ce7bebaee048e4cd7ebdb4cee7885e00c4e2abca",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "incl",
"type": "github"
}
},
"iserv-proxy": {
"flake": false,
"locked": {
"lastModified": 1670983692,
"narHash": "sha256-avLo34JnI9HNyOuauK5R69usJm+GfW3MlyGlYxZhTgY=",
"lastModified": 1691634696,
"narHash": "sha256-MZH2NznKC/gbgBu8NgIibtSUZeJ00HTLJ0PlWKCBHb0=",
"ref": "hkm/remote-iserv",
"rev": "50d0abb3317ac439a4e7495b185a64af9b7b9300",
"revCount": 10,
"rev": "43a979272d9addc29fbffc2e8542c5d96e993d73",
"revCount": 14,
"type": "git",
"url": "https://gitlab.haskell.org/hamishmack/iserv-proxy.git"
},
@@ -440,32 +414,22 @@
"type": "github"
}
},
"n2c": {
"mac2ios": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
"flake-parts": "flake-parts",
"nixpkgs": "nixpkgs_2"
},
"locked": {
"lastModified": 1665039323,
"narHash": "sha256-SAh3ZjFGsaCI8FRzXQyp56qcGdAqgKEfJWPCQ0Sr7tQ=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "b008fe329ffb59b67bf9e7b08ede6ee792f2741a",
"lastModified": 1699767871,
"narHash": "sha256-kxeCUfwC/Vgh2FvVMlBUq0eVx1JvfHyN+5MPKUik9mE=",
"owner": "zw3rk",
"repo": "mobile-core-tools",
"rev": "4dcb77d5ea896d749381806dfab5358851b08951",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"owner": "zw3rk",
"repo": "mobile-core-tools",
"type": "github"
}
},
@@ -490,95 +454,6 @@
"type": "github"
}
},
"nix-nomad": {
"inputs": {
"flake-compat": "flake-compat_2",
"flake-utils": [
"haskellNix",
"tullia",
"nix2container",
"flake-utils"
],
"gomod2nix": "gomod2nix",
"nixpkgs": [
"haskellNix",
"tullia",
"nixpkgs"
],
"nixpkgs-lib": [
"haskellNix",
"tullia",
"nixpkgs"
]
},
"locked": {
"lastModified": 1658277770,
"narHash": "sha256-T/PgG3wUn8Z2rnzfxf2VqlR1CBjInPE0l1yVzXxPnt0=",
"owner": "tristanpemble",
"repo": "nix-nomad",
"rev": "054adcbdd0a836ae1c20951b67ed549131fd2d70",
"type": "github"
},
"original": {
"owner": "tristanpemble",
"repo": "nix-nomad",
"type": "github"
}
},
"nix2container": {
"inputs": {
"flake-utils": "flake-utils_3",
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1658567952,
"narHash": "sha256-XZ4ETYAMU7XcpEeAFP3NOl9yDXNuZAen/aIJ84G+VgA=",
"owner": "nlewo",
"repo": "nix2container",
"rev": "60bb43d405991c1378baf15a40b5811a53e32ffa",
"type": "github"
},
"original": {
"owner": "nlewo",
"repo": "nix2container",
"type": "github"
}
},
"nixago": {
"inputs": {
"flake-utils": [
"haskellNix",
"tullia",
"std",
"flake-utils"
],
"nixago-exts": [
"haskellNix",
"tullia",
"std",
"blank"
],
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1661824785,
"narHash": "sha256-/PnwdWoO/JugJZHtDUioQp3uRiWeXHUdgvoyNbXesz8=",
"owner": "nix-community",
"repo": "nixago",
"rev": "8c1f9e5f1578d4b2ea989f618588d62a335083c3",
"type": "github"
},
"original": {
"owner": "nix-community",
"repo": "nixago",
"type": "github"
}
},
"nixpkgs": {
"locked": {
"lastModified": 1657693803,
@@ -645,11 +520,11 @@
},
"nixpkgs-2205": {
"locked": {
"lastModified": 1672580127,
"narHash": "sha256-3lW3xZslREhJogoOkjeZtlBtvFMyxHku7I/9IVehhT8=",
"lastModified": 1685573264,
"narHash": "sha256-Zffu01pONhs/pqH07cjlF10NnMDLok8ix5Uk4rhOnZQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "0874168639713f547c05947c76124f78441ea46c",
"rev": "380be19fbd2d9079f677978361792cb25e8a3635",
"type": "github"
},
"original": {
@@ -661,11 +536,11 @@
},
"nixpkgs-2211": {
"locked": {
"lastModified": 1675730325,
"narHash": "sha256-uNvD7fzO5hNlltNQUAFBPlcEjNG5Gkbhl/ROiX+GZU4=",
"lastModified": 1688392541,
"narHash": "sha256-lHrKvEkCPTUO+7tPfjIcb7Trk6k31rz18vkyqmkeJfY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "b7ce17b1ebf600a72178f6302c77b6382d09323f",
"rev": "ea4c80b39be4c09702b0cb3b42eab59e2ba4f24b",
"type": "github"
},
"original": {
@@ -675,6 +550,40 @@
"type": "github"
}
},
"nixpkgs-2305": {
"locked": {
"lastModified": 1695416179,
"narHash": "sha256-610o1+pwbSu+QuF3GE0NU5xQdTHM3t9wyYhB9l94Cd8=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "715d72e967ec1dd5ecc71290ee072bcaf5181ed6",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-23.05-darwin",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-lib": {
"locked": {
"dir": "lib",
"lastModified": 1696019113,
"narHash": "sha256-X3+DKYWJm93DRSdC5M6K5hLqzSya9BjibtBsuARoPco=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "f5892ddac112a1e9b3612c39af1b72987ee5783a",
"type": "github"
},
"original": {
"dir": "lib",
"owner": "NixOS",
"ref": "nixos-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs-regression": {
"locked": {
"lastModified": 1643052045,
@@ -693,11 +602,11 @@
},
"nixpkgs-unstable": {
"locked": {
"lastModified": 1675758091,
"narHash": "sha256-7gFSQbSVAFUHtGCNHPF7mPc5CcqDk9M2+inlVPZSneg=",
"lastModified": 1695318763,
"narHash": "sha256-FHVPDRP2AfvsxAdc+AsgFJevMz5VBmnZglFUMlxBkcY=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "747927516efcb5e31ba03b7ff32f61f6d47e7d87",
"rev": "e12483116b3b51a185a33a272bf351e357ba9a99",
"type": "github"
},
"original": {
@@ -709,82 +618,20 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1653581809,
"narHash": "sha256-Uvka0V5MTGbeOfWte25+tfRL3moECDh1VwokWSZUdoY=",
"lastModified": 1698434055,
"narHash": "sha256-Phxi5mUKSoL7A0IYUiYtkI9e8NcGaaV5PJEaJApU1Ko=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "83658b28fe638a170a19b8933aa008b30640fbd1",
"rev": "1a3c95e3b23b3cdb26750621c08cc2f1560cb883",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixos-unstable",
"ref": "nixos-23.05",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_3": {
"locked": {
"lastModified": 1654807842,
"narHash": "sha256-ADymZpr6LuTEBXcy6RtFHcUZdjKTBRTMYwu19WOx17E=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "fc909087cc3386955f21b4665731dbdaceefb1d8",
"type": "github"
},
"original": {
"owner": "NixOS",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_4": {
"locked": {
"lastModified": 1665087388,
"narHash": "sha256-FZFPuW9NWHJteATOf79rZfwfRn5fE0wi9kRzvGfDHPA=",
"owner": "nixos",
"repo": "nixpkgs",
"rev": "95fda953f6db2e9496d2682c4fc7b82f959878f7",
"type": "github"
},
"original": {
"owner": "nixos",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"nixpkgs_5": {
"locked": {
"lastModified": 1676726892,
"narHash": "sha256-M7OYVR6dKmzmlebIjybFf3l18S2uur8lMyWWnHQooLY=",
"owner": "angerman",
"repo": "nixpkgs",
"rev": "729469087592bdea58b360de59dadf6d58714c42",
"type": "github"
},
"original": {
"owner": "angerman",
"ref": "release-22.11",
"repo": "nixpkgs",
"type": "github"
}
},
"nosys": {
"locked": {
"lastModified": 1667881534,
"narHash": "sha256-FhwJ15uPLRsvaxtt/bNuqE/ykMpNAPF0upozFKhTtXM=",
"owner": "divnix",
"repo": "nosys",
"rev": "2d0d5207f6a230e9d0f660903f8db9807b54814f",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "nosys",
"type": "github"
}
},
"old-ghc-nix": {
"flake": false,
"locked": {
@@ -807,17 +654,21 @@
"flake-utils": "flake-utils",
"hackage": "hackage",
"haskellNix": "haskellNix",
"nixpkgs": "nixpkgs_5"
"mac2ios": "mac2ios",
"nixpkgs": [
"haskellNix",
"nixpkgs-2305"
]
}
},
"stackage": {
"flake": false,
"locked": {
"lastModified": 1677888571,
"narHash": "sha256-YkhRNOaN6QVagZo1cfykYV8KqkI8/q6r2F5+jypOma4=",
"lastModified": 1699834215,
"narHash": "sha256-g/JKy0BCvJaxPuYDl3QVc4OY8cFEomgG+hW/eEV470M=",
"owner": "input-output-hk",
"repo": "stackage.nix",
"rev": "cb50e6fabdfb2d7e655059039012ad0623f06a27",
"rev": "47aacd04abcce6bad57f43cbbbd133538380248e",
"type": "github"
},
"original": {
@@ -826,110 +677,18 @@
"type": "github"
}
},
"std": {
"inputs": {
"arion": [
"haskellNix",
"tullia",
"std",
"blank"
],
"blank": "blank",
"devshell": "devshell",
"dmerge": "dmerge",
"flake-utils": "flake-utils_4",
"incl": "incl",
"makes": [
"haskellNix",
"tullia",
"std",
"blank"
],
"microvm": [
"haskellNix",
"tullia",
"std",
"blank"
],
"n2c": "n2c",
"nixago": "nixago",
"nixpkgs": "nixpkgs_4",
"nosys": "nosys",
"yants": "yants"
},
"systems": {
"locked": {
"lastModified": 1674526466,
"narHash": "sha256-tMTaS0bqLx6VJ+K+ZT6xqsXNpzvSXJTmogkraBGzymg=",
"owner": "divnix",
"repo": "std",
"rev": "516387e3d8d059b50e742a2ff1909ed3c8f82826",
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "std",
"type": "github"
}
},
"tullia": {
"inputs": {
"nix-nomad": "nix-nomad",
"nix2container": "nix2container",
"nixpkgs": [
"haskellNix",
"nixpkgs"
],
"std": "std"
},
"locked": {
"lastModified": 1675695930,
"narHash": "sha256-B7rEZ/DBUMlK1AcJ9ajnAPPxqXY6zW2SBX+51bZV0Ac=",
"owner": "input-output-hk",
"repo": "tullia",
"rev": "621365f2c725608f381b3ad5b57afef389fd4c31",
"type": "github"
},
"original": {
"owner": "input-output-hk",
"repo": "tullia",
"type": "github"
}
},
"utils": {
"locked": {
"lastModified": 1653893745,
"narHash": "sha256-0jntwV3Z8//YwuOjzhV2sgJJPt+HY6KhU7VZUL0fKZQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "1ed9fb1935d260de5fe1c2f7ee0ebaae17ed2fa1",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"yants": {
"inputs": {
"nixpkgs": [
"haskellNix",
"tullia",
"std",
"nixpkgs"
]
},
"locked": {
"lastModified": 1667096281,
"narHash": "sha256-wRRec6ze0gJHmGn6m57/zhz/Kdvp9HS4Nl5fkQ+uIuA=",
"owner": "divnix",
"repo": "yants",
"rev": "d18f356ec25cb94dc9c275870c3a7927a10f8c3c",
"type": "github"
},
"original": {
"owner": "divnix",
"repo": "yants",
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}

299
flake.nix
View File

@@ -1,15 +1,15 @@
{
description = "nix flake for simplex-chat";
inputs.nixpkgs.url = "github:angerman/nixpkgs/release-22.11";
inputs.haskellNix.url = "github:input-output-hk/haskell.nix/armv7a";
inputs.haskellNix.inputs.nixpkgs.follows = "nixpkgs";
inputs.nixpkgs.follows = "haskellNix/nixpkgs-2305";
inputs.mac2ios.url = "github:zw3rk/mobile-core-tools";
inputs.hackage = {
url = "github:input-output-hk/hackage.nix";
flake = false;
};
inputs.haskellNix.inputs.hackage.follows = "hackage";
inputs.flake-utils.url = "github:numtide/flake-utils";
outputs = { self, haskellNix, nixpkgs, flake-utils, ... }:
outputs = { self, haskellNix, nixpkgs, flake-utils, mac2ios, ... }:
let systems = [ "x86_64-linux" "x86_64-darwin" "aarch64-linux" "aarch64-darwin" ]; in
flake-utils.lib.eachSystem systems (system:
# this android26 overlay makes the pkgsCross.{aarch64-android,armv7a-android-prebuilt} to set stdVer to 26 (Android 8).
@@ -30,7 +30,7 @@
# `appendOverlays` with a singleton is identical to `extend`.
let pkgs = haskellNix.legacyPackages.${system}.appendOverlays [android26]; in
let drv' = { extra-modules, pkgs', ... }: pkgs'.haskell-nix.project {
compiler-nix-name = "ghc8107";
compiler-nix-name = "ghc963";
index-state = "2023-12-12T00:00:00Z";
# We need this, to specify we want the cabal project.
# If the stack.yaml was dropped, this would not be necessary.
@@ -40,9 +40,12 @@
src = ./.;
};
sha256map = import ./scripts/nix/sha256map.nix;
modules = [{
modules = [
({ pkgs, lib, ...}: lib.mkIf (!pkgs.stdenv.hostPlatform.isWindows) {
# This patch adds `dl` as an extra-library to direct-sqlciper, which is needed
# on pretty much all unix platforms, but then blows up on windows m(
packages.direct-sqlcipher.patches = [ ./scripts/nix/direct-sqlcipher-2.3.27.patch ];
}
})
({ pkgs,lib, ... }: lib.mkIf (pkgs.stdenv.hostPlatform.isAndroid) {
packages.simplex-chat.components.library.ghcOptions = [ "-pie" ];
})] ++ extra-modules;
@@ -64,6 +67,9 @@
}); in
let iosPostInstall = bundleName: ''
${pkgs.tree}/bin/tree $out
mkdir tmp
find ./dist -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
mkdir -p $out/_pkg
# copy over includes, we might want those, but maybe not.
# cp -r $out/lib/*/*/include $out/_pkg/
@@ -74,6 +80,18 @@
find ${pkgs.gmp6.override { withStatic = true; }}/lib -name "*.a" -exec cp {} $out/_pkg \;
# There is no static libc
${pkgs.tree}/bin/tree $out/_pkg
for pkg in $out/_pkg/*.a; do
chmod +w $pkg
${mac2ios.packages.${system}.mac2ios}/bin/mac2ios $pkg
chmod -w $pkg
done
mkdir tmp
find $out/_pkg -name "libHS*-ghc*.a" -exec cp {} tmp \;
(cd tmp; ${pkgs.tree}/bin/tree .; ar x libHS*.a; for o in *.o; do if /usr/bin/otool -xv $o|grep ldadd ; then echo $o; fi; done; cd ..; rm -fR tmp)
sha256sum $out/_pkg/*.a
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${bundleName}.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
@@ -119,13 +137,149 @@
hardeningDisable = [ "fortify" ];
}
);in {
# STATIC x86_64-linux
"${pkgs.pkgsCross.musl64.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.musl64).simplex-chat.components.exes.simplex-chat;
"${pkgs.pkgsCross.musl32.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.musl32).simplex-chat.components.exes.simplex-chat;
# STATIC i686-linux
"${pkgs.pkgsCross.musl32.hostPlatform.system}-static:exe:simplex-chat" = (drv' {
pkgs' = pkgs.pkgsCross.musl32;
extra-modules = [{
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).simplex-chat.components.exes.simplex-chat;
# WINDOWS x86_64-mingwW64
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:exe:simplex-chat" = (drv' {
pkgs' = pkgs.pkgsCross.mingwW64;
extra-modules = [{
packages.direct-sqlcipher.flags.openssl = true;
packages.bitvec.flags.simd = false;
packages.direct-sqlcipher.patches = [
./scripts/nix/direct-sqlcipher-2.3.27-win.patch
];
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(pkgs.pkgsCross.mingwW64.openssl) #.override) # { static = true; enableKTLS = false; })
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.exes.simplex-chat.override {
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp $out/bin/* $out/_pkg
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/${pkgs.pkgsCross.mingwW64.hostPlatform.system}-simplex-chat.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"${pkgs.pkgsCross.mingwW64.hostPlatform.system}:lib:simplex-chat" = (drv' rec {
pkgs' = pkgs.pkgsCross.mingwW64;
extra-modules = [{
packages.direct-sqlcipher.flags.openssl = true;
# simd will try to read __cpu_model, which we don't expose
# from the rts (yet!).
packages.bitvec.flags.simd = false;
packages.direct-sqlcipher.patches = [
./scripts/nix/direct-sqlcipher-2.3.27-win.patch
];
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
pkgs.pkgsCross.mingwW64.openssl
];
packages.unix-time.postPatch = ''
sed -i 's/mingwex//g' unix-time.cabal
'';
}];
}).simplex-chat.components.library
.override (p: {
# enableShared = false;
setupBuildFlags = p.component.setupBuildFlags ++ map (x: "--ghc-option=${x}") [
"-shared"
"-threaded"
"-o" "libsimplex.dll"
# "-optl-lHSrts_thr"
"-optl-lffi"
# "-optl-static-libgcc"
# We can't do -optl-static-libstdc++ with gcc. g++ might
# but then we are chaning the compiler altogether.
"${./libsimplex.dll.def}"
];
postInstall = ''
set -x
function deps() {
${pkgs.binutils}/bin/strings "$1" | grep '.\.dll'|grep -v -E 'Winsock|ADVAPI32|dbghelp|KERNEL32|msvcrt|ntdll|ole32|RPCRT4|SHELL32|USER32|WINMM|WS2_32|kernel32|GDI32'|grep -v "$1"
}
${pkgs.tree}/bin/tree $out
mkdir -p $out/_pkg
cp libsimplex.dll $out/_pkg
cp libsimplex.dll.a $out/_pkg
mkdir $out/libs
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.openssl} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.libffi} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.gmp} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.stdenv.cc.cc} -name "*.dll" -exec cp {} $out/libs \;
find ${pkgs.lib.getBin pkgs.pkgsCross.mingwW64.windows.mcfgthreads} -name "*.dll" -exec cp {} $out/libs \;
pushd $out/_pkg
function copyDeps() {
for dep in $(deps "$1"); do
if [ ! -f "$dep" ]; then
if [ ! -f ../libs/"$dep" ]; then
echo "WARN: $1 -> $dep not found!"
else
cp ../libs/"$dep" .
copyDeps "$dep"
fi
fi
done
}
copyDeps libsimplex.dll
popd
${pkgs.tree}/bin/tree $out/_pkg
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-${pkgs.pkgsCross.mingwW64.hostPlatform.system}-libsimplex.zip *)
rm -fR $out/_pkg
mkdir -p $out/nix-support
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
});
# "${pkgs.pkgsCross.muslpi.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.muslpi).simplex-chat.components.exes.simplex-chat;
# STATIC aarch64-linux
"${pkgs.pkgsCross.aarch64-multiplatform-musl.hostPlatform.system}-static:exe:simplex-chat" = (drv pkgs.pkgsCross.aarch64-multiplatform-musl).simplex-chat.components.exes.simplex-chat;
"armv7a-android:lib:support" = (drv android32Pkgs).android-support.components.library.override {
smallAddressSpace = true; enableShared = false;
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
"armv7a-android:lib:support" = (drv android32Pkgs).android-support.components.library.override (p: {
smallAddressSpace = true;
# we won't want -dyamic (see aarch64-android:lib:simplex-chat)
enableShared = false;
# we also do not want to have any dependencies listed (especially no rts!)
enableStatic = false;
# This used to work with 8.10.7...
# setupBuildFlags = p.component.setupBuildFlags ++ map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
# ... but now with 9.6+
# we have to do the -shared thing by hand.
postBuild = ''
armv7a-unknown-linux-androideabi-ghc -shared -o libsupport.so \
-optl-Wl,-u,setLineBuffering \
-optl-Wl,-u,pipe_std_to_socket \
dist/build/*.a
'';
postInstall = ''
mkdir -p $out/_pkg
@@ -138,14 +292,29 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
"aarch64-android:lib:support" = (drv androidPkgs).android-support.components.library.override {
smallAddressSpace = true; enableShared = false;
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsupport.so" ];
});
# The android-support package is at
# https://github.com/simplex-chat/android-support
"aarch64-android:lib:support" = (drv androidPkgs).android-support.components.library.override (p: {
smallAddressSpace = true;
# no -dynamic
enableShared = false;
# but also no -staticlib
enableStatic = false;
# we have to do the -shared thing by hand.
postBuild = ''
aarch64-unknown-linux-android-ghc -shared -o libsupport.so \
-optl-Wl,-u,setLineBuffering \
-optl-Wl,-u,pipe_std_to_socket \
dist/build/*.a
'';
postInstall = ''
mkdir -p $out/_pkg
cp libsupport.so $out/_pkg
ls -lah $out/_pkg/*
${pkgs.patchelf}/bin/patchelf --remove-needed libunwind.so.1 $out/_pkg/libsupport.so
(cd $out/_pkg; ${pkgs.zip}/bin/zip -r -9 $out/pkg-aarch64-android-libsupport.zip *)
rm -fR $out/_pkg
@@ -154,10 +323,11 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
"armv7a-android:lib:simplex-chat" = (drv' {
pkgs' = android32Pkgs;
extra-modules = [{
packages.text.flags.simdutf = false;
packages.direct-sqlcipher.flags.openssl = true;
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
@@ -168,13 +338,55 @@
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(android32Pkgs.openssl.override { static = true; enableKTLS = false; })
];
# 32 bit patches
packages.basement.patches = [
./scripts/nix/basement-pr-573.patch
];
packages.memory.patches = [
./scripts/nix/memory-pr-99.patch
];
}];
}).simplex-chat.components.library.override {
smallAddressSpace = true; enableShared = false;
}).simplex-chat.components.library.override (p: {
smallAddressSpace = true;
# we want -shared, but not -dyanmic, hence `enableShared = false`.
enableShared = false;
# we _do_ want rts, and other libs. Hence `enableStatic = true`.
enableStatic = true;
# for android we build a shared library, passing these arguments is a bit tricky, as
# we want only the threaded rts (HSrts_thr) and ffi to be linked, but not fed into iserv for
# template haskell cross compilation. Thus we just pass them as linker options (-optl).
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsimplex.so" "-optl-lHSrts_thr" "-optl-lffi"];
setupBuildFlags = p.component.setupBuildFlags
# flags to tell GHC we want to produce a -shared object, and we want to also link
# - the ffi library (ffi)
++ map (x: "--ghc-option=${x}") [
"-shared" "-o" "libsimplex.so"
"-threaded"
# "-debug"
"-optl-lffi"
]
# This is fairly idiotic. LLD will strip out foreign exported
# symbols (a GHC bug? Codegen bug?). So we need to pass `-u <sym>`
# to ensure they stay in the produced library. Having them
# _undefined_ and _lazy_ (lld will tell with -y <sym> that the
# symbol is lazy), makes them _defined_. m(
++ map (sym: "--ghc-option=-optl-Wl,-u,${sym}") [
"chat_close_store"
"chat_decrypt_file"
"chat_decrypt_media"
"chat_encrypt_file"
"chat_encrypt_media"
"chat_migrate_init"
"chat_parse_markdown"
"chat_parse_server"
"chat_password_hash"
"chat_read_file"
"chat_recv_msg"
"chat_recv_msg_wait"
"chat_send_cmd"
"chat_send_remote_cmd"
"chat_valid_name"
"chat_write_file"
];
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
@@ -218,10 +430,11 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
"aarch64-android:lib:simplex-chat" = (drv' {
pkgs' = androidPkgs;
extra-modules = [{
packages.text.flags.simdutf = false;
packages.direct-sqlcipher.flags.openssl = true;
packages.direct-sqlcipher.components.library.libs = pkgs.lib.mkForce [
(androidPkgs.openssl.override { static = true; })
@@ -233,12 +446,49 @@
(androidPkgs.openssl.override { static = true; })
];
}];
}).simplex-chat.components.library.override {
smallAddressSpace = true; enableShared = false;
}).simplex-chat.components.library.override (p: {
smallAddressSpace = true;
# we do not want a dynamically linked object, even though we _do_
# want to produce a _shared_ object. But `shared` implied -dyanmic
# with cabal, so we disable and pass `-shared` explicitly.
enableShared = false;
# we do want static (e.g. pass all dependencies in, so we get -staticlib)
enableStatic = true;
# for android we build a shared library, passing these arguments is a bit tricky, as
# we want only the threaded rts (HSrts_thr) and ffi to be linked, but not fed into iserv for
# template haskell cross compilation. Thus we just pass them as linker options (-optl).
setupBuildFlags = map (x: "--ghc-option=${x}") [ "-shared" "-o" "libsimplex.so" "-optl-lHSrts_thr" "-optl-lffi"];
setupBuildFlags = p.component.setupBuildFlags
# flags to tell GHC we want to produce a -shared object, and we want to also link
# - the ffi library (ffi)
++ map (x: "--ghc-option=${x}") [
"-shared" "-o" "libsimplex.so"
"-threaded"
# "-debug"
"-optl-lffi"
]
# This is fairly idiotic. LLD will strip out foreign exported
# symbols (a GHC bug? Codegen bug?). So we need to pass `-u <sym>`
# to ensure they stay in the produced library. Having them
# _undefined_ and _lazy_ (lld will tell with -y <sym> that the
# symbol is lazy), makes them _defined_. m(
++ map (sym: "--ghc-option=-optl-Wl,-u,${sym}") [
"chat_close_store"
"chat_decrypt_file"
"chat_decrypt_media"
"chat_encrypt_file"
"chat_encrypt_media"
"chat_migrate_init"
"chat_parse_markdown"
"chat_parse_server"
"chat_password_hash"
"chat_read_file"
"chat_recv_msg"
"chat_recv_msg_wait"
"chat_send_cmd"
"chat_send_remote_cmd"
"chat_valid_name"
"chat_write_file"
];
postInstall = ''
set -x
${pkgs.tree}/bin/tree $out
@@ -282,7 +532,7 @@
echo "file binary-dist \"$(echo $out/*.zip)\"" \
> $out/nix-support/hydra-build-products
'';
};
});
};
# builds for iOS and iOS simulator
@@ -296,7 +546,8 @@
packages.direct-sqlcipher.flags.commoncrypto = true;
packages.entropy.flags.DoNotGetEntropy = true;
packages.simplexmq.components.library.libs = pkgs.lib.mkForce [
(pkgs.openssl.override { static = true; })
# TODO: have a cross override for iOS, that sets this.
((pkgs.openssl.override { static = true; }).overrideDerivation (old: { CFLAGS = "-mcpu=apple-a7 -march=armv8-a+norcpc" ;}))
];
}];
}).simplex-chat.components.library.override (

View File

@@ -12,7 +12,6 @@ EXPORTS
chat_parse_server
chat_password_hash
chat_valid_name
chat_json_length
chat_encrypt_media
chat_decrypt_media
chat_write_file

View File

@@ -1,5 +1,5 @@
name: simplex-chat
version: 5.5.3.0
version: 5.5.1.0
#synopsis:
#description:
homepage: https://github.com/simplex-chat/simplex-chat#readme
@@ -36,6 +36,7 @@ dependencies:
- network >= 3.1.2.7 && < 3.2
- network-transport == 0.5.6
- optparse-applicative >= 0.15 && < 0.17
- process == 1.6.*
- random >= 1.1 && < 1.3
- record-hasfield == 1.0.*
- simple-logger == 0.1.*
@@ -63,13 +64,11 @@ when:
- condition: impl(ghc >= 9.6.2)
dependencies:
- bytestring == 0.11.*
- process == 1.6.*
- template-haskell == 2.20.*
- text >= 2.0.1 && < 2.2
- condition: impl(ghc < 9.6.2)
dependencies:
- bytestring == 0.10.*
- process >= 1.6 && < 1.6.18
- template-haskell == 2.16.*
- text >= 1.2.3.0 && < 1.3
@@ -126,19 +125,13 @@ tests:
- apps/simplex-broadcast-bot/src
- apps/simplex-directory-service/src
main: Test.hs
when:
- condition: impl(ghc >= 9.6.2)
dependencies:
- hspec == 2.11.*
- condition: impl(ghc < 9.6.2)
dependencies:
- hspec == 2.7.*
dependencies:
- QuickCheck == 2.14.*
- simplex-chat
- async == 2.2.*
- deepseq == 1.4.*
- generic-random == 1.5.*
- hspec == 2.11.*
- network == 3.1.*
- silently == 1.2.*
- stm == 2.5.*

View File

@@ -8,7 +8,6 @@
<body>
<video
id="remote-video-stream"
class="inline"
autoplay
playsinline
poster="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAEUlEQVR42mNk+M+AARiHsiAAcCIKAYwFoQ8AAAAASUVORK5CYII="
@@ -16,7 +15,6 @@
></video>
<video
id="local-video-stream"
class="inline"
muted
autoplay
playsinline

View File

@@ -5,14 +5,14 @@ body {
background-color: black;
}
#remote-video-stream.inline {
#remote-video-stream {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
#local-video-stream.inline {
#local-video-stream {
position: absolute;
width: 30%;
max-width: 30%;
@@ -23,20 +23,6 @@ body {
right: 0;
}
#remote-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
#local-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
*::-webkit-media-controls {
display: none !important;
-webkit-appearance: none !important;

View File

@@ -16,7 +16,6 @@ type WCallCommand =
| WCEnableMedia
| WCToggleCamera
| WCDescription
| WCLayout
| WCEndCall
type WCallResponse =
@@ -32,7 +31,7 @@ type WCallResponse =
| WRError
| WCAcceptOffer
type WCallCommandTag = "capabilities" | "start" | "offer" | "answer" | "ice" | "media" | "camera" | "description" | "layout" | "end"
type WCallCommandTag = "capabilities" | "start" | "offer" | "answer" | "ice" | "media" | "camera" | "description" | "end"
type WCallResponseTag = "capabilities" | "offer" | "answer" | "ice" | "connection" | "connected" | "end" | "ended" | "ok" | "error"
@@ -46,12 +45,6 @@ enum VideoCamera {
Environment = "environment",
}
enum LayoutType {
Default = "default",
LocalVideo = "localVideo",
RemoteVideo = "remoteVideo",
}
interface IWCallCommand {
type: WCallCommandTag
}
@@ -122,11 +115,6 @@ interface WCDescription extends IWCallCommand {
description: string
}
interface WCLayout extends IWCallCommand {
type: "layout"
layout: LayoutType
}
interface WRCapabilities extends IWCallResponse {
type: "capabilities"
capabilities: CallCapabilities
@@ -527,10 +515,6 @@ const processCommand = (function () {
localizedDescription = command.description
resp = {type: "ok"}
break
case "layout":
changeLayout(command.layout)
resp = {type: "ok"}
break
case "end":
endCall()
resp = {type: "ok"}
@@ -840,29 +824,6 @@ function toggleMedia(s: MediaStream, media: CallMediaType): boolean {
return res
}
function changeLayout(layout: LayoutType) {
const local = document.getElementById("local-video-stream")!
const remote = document.getElementById("remote-video-stream")!
switch (layout) {
case LayoutType.Default:
local.className = "inline"
remote.className = "inline"
local.style.visibility = "visible"
remote.style.visibility = "visible"
break
case LayoutType.LocalVideo:
local.className = "fullscreen"
local.style.visibility = "visible"
remote.style.visibility = "hidden"
break
case LayoutType.RemoteVideo:
remote.className = "fullscreen"
local.style.visibility = "hidden"
remote.style.visibility = "visible"
break
}
}
type TransformFrameFunc = (key: CryptoKey) => (frame: RTCEncodedVideoFrame, controller: TransformStreamDefaultController) => Promise<void>
interface CallCrypto {

View File

@@ -9,7 +9,6 @@
<body>
<video
id="remote-video-stream"
class="inline"
autoplay
playsinline
poster="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAoAAAAKCAQAAAAnOwc2AAAAEUlEQVR42mNk+M+AARiHsiAAcCIKAYwFoQ8AAAAASUVORK5CYII="
@@ -17,7 +16,6 @@
></video>
<video
id="local-video-stream"
class="inline"
muted
autoplay
playsinline

View File

@@ -5,14 +5,14 @@ body {
background-color: black;
}
#remote-video-stream.inline {
#remote-video-stream {
position: absolute;
width: 100%;
height: 100%;
object-fit: cover;
}
#local-video-stream.inline {
#local-video-stream {
position: absolute;
width: 20%;
max-width: 20%;
@@ -23,20 +23,6 @@ body {
right: 0;
}
#remote-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
#local-video-stream.fullscreen {
position: absolute;
height: 100%;
width: 100%;
object-fit: cover;
}
*::-webkit-media-controls {
display: none !important;
-webkit-appearance: none !important;

View File

@@ -2,7 +2,7 @@
set -e
trap "rm apps/multiplatform/local.properties || true; rm local.properties || true; rm /tmp/simplex.keychain || true" EXIT
trap "rm apps/multiplatform/local.properties 2> /dev/null || true; rm local.properties 2> /dev/null || true; rm /tmp/simplex.keychain" EXIT
echo "desktop.mac.signing.identity=Developer ID Application: SimpleX Chat Ltd (5NN7GUYB6T)" >> apps/multiplatform/local.properties
echo "desktop.mac.signing.keychain=/tmp/simplex.keychain" >> apps/multiplatform/local.properties
echo "desktop.mac.notarization.apple_id=$APPLE_SIMPLEX_NOTARIZATION_APPLE_ID" >> apps/multiplatform/local.properties
@@ -10,6 +10,10 @@ echo "desktop.mac.notarization.password=$APPLE_SIMPLEX_NOTARIZATION_PASSWORD" >>
echo "desktop.mac.notarization.team_id=5NN7GUYB6T" >> apps/multiplatform/local.properties
echo "$APPLE_SIMPLEX_SIGNING_KEYCHAIN" | base64 --decode - > /tmp/simplex.keychain
security unlock-keychain -p "" /tmp/simplex.keychain
# Adding keychain to the list of keychains.
# Otherwise, it can find cert but exits while signing with "error: The specified item could not be found in the keychain."
security list-keychains -s `security list-keychains | xargs` /tmp/simplex.keychain
scripts/desktop/build-lib-mac.sh
cd apps/multiplatform
./gradlew packageDmg

View File

@@ -0,0 +1,10 @@
#!/bin/bash
security create-keychain -p "" simplex.keychain
security set-keychain-settings -u simplex.keychain
security add-certificates -k simplex.keychain "Developer ID Application: SimpleX Chat Ltd (5NN7GUYB6T).cer"
security add-certificates -k simplex.keychain "Developer ID Certification Authority.cer"
# Private key with access from any app
security import "SimpleX Chat.p12" -P "" -k simplex.keychain -A
# Public key
security import "SimpleX Chat.pem" -k simplex.keychain

View File

@@ -8,7 +8,7 @@ function readlink() {
OS=linux
ARCH=${1:-`uname -a | rev | cut -d' ' -f2 | rev`}
GHC_VERSION=8.10.7
GHC_VERSION=9.6.3
if [ "$ARCH" == "aarch64" ]; then
COMPOSE_ARCH=arm64
@@ -20,12 +20,8 @@ root_dir="$(dirname "$(dirname "$(readlink "$0")")")"
cd $root_dir
BUILD_DIR=dist-newstyle/build/$ARCH-$OS/ghc-${GHC_VERSION}/simplex-chat-*
exports=( $(sed 's/foreign export ccall "chat_migrate_init_key"//' src/Simplex/Chat/Mobile.hs | sed 's/foreign export ccall "chat_reopen_store"//' |grep "foreign export ccall" | cut -d '"' -f2) )
for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc -l); if [ $count -ne 1 ]; then echo Wrong exports in libsimplex.dll.def. Add \"$elem\" to that file; exit 1; fi ; done
for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done
rm -rf $BUILD_DIR
cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN' --ghc-options="-optl-L$(ghc --print-libdir)/rts -optl-Wl,--as-needed,-lHSrts_thr-ghc$GHC_VERSION"
cabal build lib:simplex-chat --ghc-options='-optl-Wl,-rpath,$ORIGIN -flink-rts -threaded'
cd $BUILD_DIR/build
#patchelf --add-needed libHSrts_thr-ghc${GHC_VERSION}.so libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so
#patchelf --add-rpath '$ORIGIN' libHSsimplex-chat-*-inplace-ghc${GHC_VERSION}.so

View File

@@ -5,31 +5,41 @@ set -e
OS=mac
ARCH="${1:-`uname -a | rev | cut -d' ' -f1 | rev`}"
COMPOSE_ARCH=$ARCH
GHC_VERSION=8.10.7
GHC_VERSION=9.6.3
if [ "$ARCH" == "arm64" ]; then
ARCH=aarch64
else
COMPOSE_ARCH=x64
fi
LIB_EXT=dylib
LIB=libHSsimplex-chat-*-inplace-ghc*.$LIB_EXT
GHC_LIBS_DIR=$(ghc --print-libdir)
BUILD_DIR=dist-newstyle/build/$ARCH-*/ghc-*/simplex-chat-*
exports=( $(sed 's/foreign export ccall "chat_migrate_init_key"//' src/Simplex/Chat/Mobile.hs | sed 's/foreign export ccall "chat_reopen_store"//' |grep "foreign export ccall" | cut -d '"' -f2) )
for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc -l); if [ $count -ne 1 ]; then echo Wrong exports in libsimplex.dll.def. Add \"$elem\" to that file; exit 1; fi ; done
for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done
rm -rf $BUILD_DIR
cabal build lib:simplex-chat lib:simplex-chat --ghc-options="-optl-Wl,-rpath,@loader_path -optl-Wl,-L$GHC_LIBS_DIR/rts -optl-lHSrts_thr-ghc8.10.7 -optl-lffi"
cabal build lib:simplex-chat lib:simplex-chat --ghc-options="-optl-Wl,-rpath,@loader_path -optl-Wl,-L$GHC_LIBS_DIR/$ARCH-osx-ghc-$GHC_VERSION -optl-lHSrts_thr-ghc$GHC_VERSION -optl-lffi"
cd $BUILD_DIR/build
mkdir deps 2> /dev/null || true
# It's not included by default for some reason. Compiled lib tries to find system one but it's not always available
cp $GHC_LIBS_DIR/rts/libffi.dylib ./deps
#cp $GHC_LIBS_DIR/libffi.dylib ./deps
(
BUILD=$PWD
cp /tmp/libffi-3.4.4/*-apple-darwin*/.libs/libffi.dylib $BUILD/deps || \
( \
cd /tmp && \
curl --tlsv1.2 "https://gitlab.haskell.org/ghc/libffi-tarballs/-/raw/libffi-3.4.4/libffi-3.4.4.tar.gz?inline=false" -o libffi.tar.gz && \
tar -xzvf libffi.tar.gz && \
cd "libffi-3.4.4" && \
./configure && \
make && \
cp *-apple-darwin*/.libs/libffi.dylib $BUILD/deps \
)
)
DYLIBS=`otool -L $LIB | grep @rpath | tail -n +2 | cut -d' ' -f 1 | cut -d'/' -f2`
RPATHS=`otool -l $LIB | grep "path "| cut -d' ' -f11`
@@ -70,6 +80,8 @@ function copy_deps() {
}
copy_deps $LIB
# Special case
cp $(ghc --print-libdir)/$ARCH-osx-ghc-$GHC_VERSION/libHSghc-boot-th-$GHC_VERSION-ghc$GHC_VERSION.dylib deps
rm deps/`basename $LIB`
cd -

View File

@@ -17,10 +17,6 @@ fi
BUILD_DIR=dist-newstyle/build/$ARCH-$OS/ghc-*/simplex-chat-*
exports=( $(sed 's/foreign export ccall "chat_migrate_init_key"//' src/Simplex/Chat/Mobile.hs | sed 's/foreign export ccall "chat_reopen_store"//' |grep "foreign export ccall" | cut -d '"' -f2) )
for elem in "${exports[@]}"; do count=$(grep -R "$elem$" libsimplex.dll.def | wc -l); if [ $count -ne 1 ]; then echo Wrong exports in libsimplex.dll.def. Add \"$elem\" to that file; exit 1; fi ; done
for elem in "${exports[@]}"; do count=$(grep -R "\"$elem\"" flake.nix | wc -l); if [ $count -ne 2 ]; then echo Wrong exports in flake.nix. Add \"$elem\" in two places of the file; exit 1; fi ; done
# IMPORTANT: in order to get a working build you should use x86_64 MinGW with make, cmake, gcc.
# 100% working MinGW is https://github.com/brechtsanders/winlibs_mingw/releases/download/13.1.0-16.0.5-11.0.0-ucrt-r5/winlibs-x86_64-posix-seh-gcc-13.1.0-mingw-w64ucrt-11.0.0-r5.zip
# Many other distributions I tested don't work in some cases or don't have required tools.

View File

@@ -0,0 +1,242 @@
From 38be2c93acb6f459d24ed6c626981c35ccf44095 Mon Sep 17 00:00:00 2001
From: Sylvain Henry <sylvain@haskus.fr>
Date: Thu, 16 Feb 2023 15:40:45 +0100
Subject: [PATCH] Fix build on 32-bit architectures
---
Basement/Bits.hs | 4 ++++
Basement/From.hs | 24 -----------------------
Basement/Numerical/Additive.hs | 4 ++++
Basement/Numerical/Conversion.hs | 20 +++++++++++++++++++
Basement/PrimType.hs | 6 +++++-
Basement/Types/OffsetSize.hs | 22 +++++++++++++++++++--
6 files changed, 53 insertions(+), 27 deletions(-)
diff --git a/Basement/Bits.hs b/Basement/Bits.hs
index 7eeea0f5..24520ed7 100644
--- a/Basement/Bits.hs
+++ b/Basement/Bits.hs
@@ -54,8 +54,12 @@ import GHC.Int
import Basement.Compat.Primitive
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | operation over finite bits
class FiniteBitsOps bits where
diff --git a/Basement/From.hs b/Basement/From.hs
index 7bbe141c..80014b3e 100644
--- a/Basement/From.hs
+++ b/Basement/From.hs
@@ -272,23 +272,11 @@ instance (NatWithinBound (CountOf ty) n, KnownNat n, PrimType ty)
tryFrom = BlockN.toBlockN . UArray.toBlock . BoxArray.mapToUnboxed id
instance (KnownNat n, NatWithinBound Word8 n) => From (Zn64 n) Word8 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word16 n) => From (Zn64 n) Word16 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word32 n) => From (Zn64 n) Word32 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . unZn64 where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . unZn64 where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# w))
-#endif
instance From (Zn64 n) Word64 where
from = unZn64
instance From (Zn64 n) Word128 where
@@ -297,23 +285,11 @@ instance From (Zn64 n) Word256 where
from = from . unZn64
instance (KnownNat n, NatWithinBound Word8 n) => From (Zn n) Word8 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W8# (wordToWord8# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word16 n) => From (Zn n) Word16 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W16# (wordToWord16# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word32 n) => From (Zn n) Word32 where
-#if __GLASGOW_HASKELL__ >= 904
- from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# (GHC.Prim.word64ToWord# w)))
-#else
from = narrow . naturalToWord64 . unZn where narrow (W64# w) = W32# (wordToWord32# (word64ToWord# w))
-#endif
instance (KnownNat n, NatWithinBound Word64 n) => From (Zn n) Word64 where
from = naturalToWord64 . unZn
instance (KnownNat n, NatWithinBound Word128 n) => From (Zn n) Word128 where
diff --git a/Basement/Numerical/Additive.hs b/Basement/Numerical/Additive.hs
index d0dfb973..8ab65aa0 100644
--- a/Basement/Numerical/Additive.hs
+++ b/Basement/Numerical/Additive.hs
@@ -30,8 +30,12 @@ import qualified Basement.Types.Word128 as Word128
import qualified Basement.Types.Word256 as Word256
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | Represent class of things that can be added together,
-- contains a neutral element and is commutative.
diff --git a/Basement/Numerical/Conversion.hs b/Basement/Numerical/Conversion.hs
index db502c07..fddc8232 100644
--- a/Basement/Numerical/Conversion.hs
+++ b/Basement/Numerical/Conversion.hs
@@ -26,8 +26,12 @@ import GHC.Word
import Basement.Compat.Primitive
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
intToInt64 :: Int -> Int64
#if WORD_SIZE_IN_BITS == 64
@@ -96,11 +100,22 @@ int64ToWord64 (I64# i) = W64# (int64ToWord64# i)
#endif
#if WORD_SIZE_IN_BITS == 64
+#if __GLASGOW_HASKELL__ >= 904
+word64ToWord# :: Word64# -> Word#
+word64ToWord# i = word64ToWord# i
+#else
word64ToWord# :: Word# -> Word#
word64ToWord# i = i
+#endif
{-# INLINE word64ToWord# #-}
#endif
+#if WORD_SIZE_IN_BITS < 64
+word64ToWord32# :: Word64# -> Word32#
+word64ToWord32# i = wordToWord32# (word64ToWord# i)
+{-# INLINE word64ToWord32# #-}
+#endif
+
-- | 2 Word32s
data Word32x2 = Word32x2 {-# UNPACK #-} !Word32
{-# UNPACK #-} !Word32
@@ -113,9 +128,14 @@ word64ToWord32s (W64# w64) = Word32x2 (W32# (wordToWord32# (uncheckedShiftRL# (G
word64ToWord32s (W64# w64) = Word32x2 (W32# (wordToWord32# (uncheckedShiftRL# w64 32#))) (W32# (wordToWord32# w64))
#endif
#else
+#if __GLASGOW_HASKELL__ >= 904
+word64ToWord32s :: Word64 -> Word32x2
+word64ToWord32s (W64# w64) = Word32x2 (W32# (word64ToWord32# (uncheckedShiftRL64# w64 32#))) (W32# (word64ToWord32# w64))
+#else
word64ToWord32s :: Word64 -> Word32x2
word64ToWord32s (W64# w64) = Word32x2 (W32# (word64ToWord# (uncheckedShiftRL64# w64 32#))) (W32# (word64ToWord# w64))
#endif
+#endif
wordToChar :: Word -> Char
wordToChar (W# word) = C# (chr# (word2Int# word))
diff --git a/Basement/PrimType.hs b/Basement/PrimType.hs
index f8ca2926..a888ec91 100644
--- a/Basement/PrimType.hs
+++ b/Basement/PrimType.hs
@@ -54,7 +54,11 @@ import Basement.Nat
import qualified Prelude (quot)
#if WORD_SIZE_IN_BITS < 64
-import GHC.IntWord64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
+import GHC.IntWord64
+#endif
#endif
#ifdef FOUNDATION_BOUNDS_CHECK
diff --git a/Basement/Types/OffsetSize.hs b/Basement/Types/OffsetSize.hs
index cd944927..1ea80dad 100644
--- a/Basement/Types/OffsetSize.hs
+++ b/Basement/Types/OffsetSize.hs
@@ -70,8 +70,12 @@ import Data.List (foldl')
import qualified Prelude
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+import GHC.Exts
+#else
import GHC.IntWord64
#endif
+#endif
-- | File size in bytes
newtype FileSize = FileSize Word64
@@ -225,20 +229,26 @@ countOfRoundUp alignment (CountOf n) = CountOf ((n + (alignment-1)) .&. compleme
csizeOfSize :: CountOf Word8 -> CSize
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+csizeOfSize (CountOf (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
+#else
csizeOfSize (CountOf (I# sz)) = CSize (W32# (int2Word# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
csizeOfSize (CountOf (I# sz)) = CSize (W64# (wordToWord64# (int2Word# sz)))
-
#else
csizeOfSize (CountOf (I# sz)) = CSize (W64# (int2Word# sz))
-
#endif
#endif
csizeOfOffset :: Offset8 -> CSize
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+csizeOfOffset (Offset (I# sz)) = CSize (W32# (wordToWord32# (int2Word# sz)))
+#else
csizeOfOffset (Offset (I# sz)) = CSize (W32# (int2Word# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
csizeOfOffset (Offset (I# sz)) = CSize (W64# (wordToWord64# (int2Word# sz)))
@@ -250,7 +260,11 @@ csizeOfOffset (Offset (I# sz)) = CSize (W64# (int2Word# sz))
sizeOfCSSize :: CSsize -> CountOf Word8
sizeOfCSSize (CSsize (-1)) = error "invalid size: CSSize is -1"
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# (int32ToInt# sz))
+#else
sizeOfCSSize (CSsize (I32# sz)) = CountOf (I# sz)
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# (int64ToInt# sz))
@@ -261,7 +275,11 @@ sizeOfCSSize (CSsize (I64# sz)) = CountOf (I# sz)
sizeOfCSize :: CSize -> CountOf Word8
#if WORD_SIZE_IN_BITS < 64
+#if __GLASGOW_HASKELL__ >= 904
+sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# (word32ToWord# sz)))
+#else
sizeOfCSize (CSize (W32# sz)) = CountOf (I# (word2Int# sz))
+#endif
#else
#if __GLASGOW_HASKELL__ >= 904
sizeOfCSize (CSize (W64# sz)) = CountOf (I# (word2Int# (word64ToWord# sz)))

View File

@@ -0,0 +1,12 @@
diff --git a/direct-sqlcipher.cabal b/direct-sqlcipher.cabal
index 728ba3e..c63745e 100644
--- a/direct-sqlcipher.cabal
+++ b/direct-sqlcipher.cabal
@@ -84,6 +84,8 @@ library
cc-options: -DSQLITE_TEMP_STORE=2
-DSQLITE_HAS_CODEC
+ extra-libraries: ws2_32
+
if !os(windows) && !os(android)
extra-libraries: pthread

View File

@@ -0,0 +1,36 @@
From 2738929ce15b4c8704bbbac24a08539b5d4bf30e Mon Sep 17 00:00:00 2001
From: sternenseemann <sternenseemann@systemli.org>
Date: Mon, 14 Aug 2023 10:51:30 +0200
Subject: [PATCH] Data.Memory.Internal.CompatPrim64: fix 32 bit with GHC >= 9.4
Since 9.4, GHC.Prim exports Word64# operations like timesWord64# even on
i686 whereas GHC.IntWord64 no longer exists. Therefore, we can just use
the ready made solution.
Closes #98, as it should be the better solution.
---
Data/Memory/Internal/CompatPrim64.hs | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/Data/Memory/Internal/CompatPrim64.hs b/Data/Memory/Internal/CompatPrim64.hs
index b9eef8a..a134c88 100644
--- a/Data/Memory/Internal/CompatPrim64.hs
+++ b/Data/Memory/Internal/CompatPrim64.hs
@@ -150,6 +150,7 @@ w64# :: Word# -> Word# -> Word# -> Word64#
w64# w _ _ = w
#elif WORD_SIZE_IN_BITS == 32
+#if __GLASGOW_HASKELL__ < 904
import GHC.IntWord64
import GHC.Prim (Word#)
@@ -158,6 +159,9 @@ timesWord64# a b =
let !ai = word64ToInt64# a
!bi = word64ToInt64# b
in int64ToWord64# (timesInt64# ai bi)
+#else
+import GHC.Prim
+#endif
w64# :: Word# -> Word# -> Word# -> Word64#
w64# _ hw lw =

View File

@@ -1,5 +1,5 @@
{
"https://github.com/simplex-chat/simplexmq.git"."e64b6cba4b7e4107f78ae596ab2a6a28ef24ff78" = "0fxgklq65bh2f4kx36vjicdxqmi88m91xs601hm81v5pn6kk0ppd";
"https://github.com/simplex-chat/simplexmq.git"."7a0cd8041bbb7d7ab2f089395a244dc4af0f9e3b" = "0jxf9dnsg14ffd1y3i7md2ninrds4daq1fmpnd6j5z99im07ns52";
"https://github.com/simplex-chat/hs-socks.git"."a30cc7a79a08d8108316094f8f2f82a0c5e1ac51" = "0yasvnr7g91k76mjkamvzab2kvlb1g5pspjyjn2fr6v83swjhj38";
"https://github.com/simplex-chat/direct-sqlcipher.git"."f814ee68b16a9447fbb467ccc8f29bdd3546bfd9" = "1ql13f4kfwkbaq7nygkxgw84213i0zm7c1a8hwvramayxl38dq5d";
"https://github.com/simplex-chat/sqlcipher-simple.git"."a46bd361a19376c5211f1058908fc0ae6bf42446" = "1z0r78d8f0812kxbgsm735qf6xx8lvaz27k1a0b4a2m0sshpd5gl";

View File

@@ -5,7 +5,7 @@ cabal-version: 1.12
-- see: https://github.com/sol/hpack
name: simplex-chat
version: 5.5.3.0
version: 5.5.1.0
category: Web, System, Services, Cryptography
homepage: https://github.com/simplex-chat/simplex-chat#readme
author: simplex.chat
@@ -197,6 +197,7 @@ library
, network >=3.1.2.7 && <3.2
, network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17
, process ==1.6.*
, random >=1.1 && <1.3
, record-hasfield ==1.0.*
, simple-logger ==0.1.*
@@ -216,13 +217,11 @@ library
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, process ==1.6.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, process >=1.6 && <1.6.18
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
@@ -257,6 +256,7 @@ executable simplex-bot
, network >=3.1.2.7 && <3.2
, network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17
, process ==1.6.*
, random >=1.1 && <1.3
, record-hasfield ==1.0.*
, simple-logger ==0.1.*
@@ -277,13 +277,11 @@ executable simplex-bot
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, process ==1.6.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, process >=1.6 && <1.6.18
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
@@ -318,6 +316,7 @@ executable simplex-bot-advanced
, network >=3.1.2.7 && <3.2
, network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17
, process ==1.6.*
, random >=1.1 && <1.3
, record-hasfield ==1.0.*
, simple-logger ==0.1.*
@@ -338,13 +337,11 @@ executable simplex-bot-advanced
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, process ==1.6.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, process >=1.6 && <1.6.18
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
@@ -381,6 +378,7 @@ executable simplex-broadcast-bot
, network >=3.1.2.7 && <3.2
, network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17
, process ==1.6.*
, random >=1.1 && <1.3
, record-hasfield ==1.0.*
, simple-logger ==0.1.*
@@ -401,13 +399,11 @@ executable simplex-broadcast-bot
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, process ==1.6.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, process >=1.6 && <1.6.18
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
@@ -443,6 +439,7 @@ executable simplex-chat
, network ==3.1.*
, network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17
, process ==1.6.*
, random >=1.1 && <1.3
, record-hasfield ==1.0.*
, simple-logger ==0.1.*
@@ -464,13 +461,11 @@ executable simplex-chat
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, process ==1.6.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, process >=1.6 && <1.6.18
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
@@ -510,6 +505,7 @@ executable simplex-directory-service
, network >=3.1.2.7 && <3.2
, network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17
, process ==1.6.*
, random >=1.1 && <1.3
, record-hasfield ==1.0.*
, simple-logger ==0.1.*
@@ -530,13 +526,11 @@ executable simplex-directory-service
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, process ==1.6.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, process >=1.6 && <1.6.18
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
@@ -598,6 +592,7 @@ test-suite simplex-chat-test
, exceptions ==0.10.*
, filepath ==1.4.*
, generic-random ==1.5.*
, hspec ==2.11.*
, http-types ==0.12.*
, http2 >=4.2.2 && <4.3
, memory ==0.18.*
@@ -605,6 +600,7 @@ test-suite simplex-chat-test
, network ==3.1.*
, network-transport ==0.5.6
, optparse-applicative >=0.15 && <0.17
, process ==1.6.*
, random >=1.1 && <1.3
, record-hasfield ==1.0.*
, silently ==1.2.*
@@ -626,18 +622,10 @@ test-suite simplex-chat-test
if impl(ghc >= 9.6.2)
build-depends:
bytestring ==0.11.*
, process ==1.6.*
, template-haskell ==2.20.*
, text >=2.0.1 && <2.2
if impl(ghc < 9.6.2)
build-depends:
bytestring ==0.10.*
, process >=1.6 && <1.6.18
, template-haskell ==2.16.*
, text >=1.2.3.0 && <1.3
if impl(ghc >= 9.6.2)
build-depends:
hspec ==2.11.*
if impl(ghc < 9.6.2)
build-depends:
hspec ==2.7.*