Compare commits

..

159 Commits

Author SHA1 Message Date
adbenitez bdfeddecd5 add "get it on google play" 2025-01-31 14:19:32 +01:00
adbenitez d4f83cd38b Merge remote-tracking branch 'upstream/main' 2025-01-30 02:03:47 +01:00
adbenitez 9eca5f518e disable location streaming for now 2025-01-30 02:02:42 +01:00
B. Petersen d17bed02e6 update translations 2025-01-29 14:47:03 +01:00
B. Petersen b4b194a59b add app-picker-strings needed for iOS 2025-01-29 14:47:03 +01:00
adb c6f62a2b81 Merge pull request #3565 from deltachat/prep-1.52.1
Prep 1.52.1
2025-01-28 17:24:22 +01:00
adbenitez e3a9f42a56 update changelog 2025-01-28 17:23:56 +01:00
adb 323bcef1fe Update CHANGELOG.md
Co-authored-by: Hocuri <hocuri@gmx.de>
2025-01-28 17:13:54 +01:00
adbenitez 095b92b498 bump version number 2025-01-28 16:50:46 +01:00
adbenitez 18c2ccd66c update changelog 2025-01-28 16:36:39 +01:00
adb 28fdeac01c Merge pull request #3564 from deltachat/update-core-and-stuff-28/1/25
Update translations and core to 1.155.1
2025-01-28 16:31:11 +01:00
adbenitez a7e4267b9b update translations 2025-01-28 16:28:24 +01:00
adbenitez d6837aa121 update deltachat-core-rust to 'chore(release): prepare for 1.155.1' of 'v1.155.1' 2025-01-28 16:25:23 +01:00
adbenitez 5a2913b36f delete unused file 2025-01-28 02:37:25 +01:00
adbenitez 20180fa89c Merge remote-tracking branch 'upstream/main' 2025-01-27 22:06:04 +01:00
Hocuri c6b89055d8 File deduplication, Android part (#3513) 2025-01-27 18:40:44 +01:00
adb bfda7ab2c3 Merge pull request #3562 from deltachat/adb/remove-android-crop-dep
remove unused com.soundcloud.android:android-crop dependency
2025-01-27 18:13:04 +01:00
adb 953ce32bea Merge branch 'main' into adb/remove-android-crop-dep 2025-01-27 17:40:34 +01:00
adbenitez 961fa5ffe6 remove unused com.soundcloud.android:android-crop dependency 2025-01-27 17:37:14 +01:00
adbenitez b1b2959bcb add .github/FUNDING.yml 2025-01-26 05:23:27 +01:00
link2xt 70ef715dc6 build(nix): update build tools from 33.0.1 to 34.0.0 2025-01-25 13:48:41 +00:00
adbenitez ffa58aae34 update bots index 2025-01-24 22:09:54 +01:00
adbenitez 24f5209c03 always create protected groups 2025-01-24 20:34:49 +01:00
adbenitez 7fd96732d6 Merge remote-tracking branch 'upstream/main' 2025-01-24 20:27:40 +01:00
adb 6e0759f719 Merge pull request #3560 from deltachat/prep-1.52.0
prepare 1.52.0
2025-01-23 23:37:01 +01:00
adbenitez 63434e1e2f prepare 1.52.0 2025-01-23 20:03:59 +01:00
adb 9c17bc412a Merge pull request #3559 from deltachat/update-core-and-stuff-23/1/25
Update core and stuff 23/1/25
2025-01-23 19:21:15 +01:00
adb d40144d50c Merge branch 'main' into update-core-and-stuff-23/1/25 2025-01-23 19:19:43 +01:00
adbenitez 131c0f5a37 update strings 2025-01-23 19:17:18 +01:00
adbenitez 7086314d8b update deltachat-core-rust to 'chore(release): prepare for 1.155.0' of 'v1.155.0' 2025-01-23 19:11:11 +01:00
adb d75b2c2bb7 Merge pull request #3558 from deltachat/adb/issue-3557
pass account ID in chat shortcuts and properly switch to account
2025-01-23 13:23:00 +01:00
adbenitez c46d174869 update strings 2025-01-23 05:37:55 +01:00
adbenitez 17e03f2903 update buid.gradle 2025-01-23 04:38:58 +01:00
adbenitez 2c12a34051 improve instant onboarding 2025-01-23 04:33:23 +01:00
adbenitez 2d3dde2101 pass account ID in chat shortcuts and properly switch to account 2025-01-23 03:45:57 +01:00
adbenitez d539f5ecf2 Merge remote-tracking branch 'upstream/main' 2025-01-23 02:45:56 +01:00
adbenitez b17d6be4fc update build.gradle 2025-01-23 00:52:48 +01:00
B. Petersen 3c737f2360 streamline help menu
- use clear "Delta Chat Homepage" for opening our homepage
  (instead of unclear "Learn more about Delta Chat",
  which is esp. weird, when used from inside the help)

- do not "promote" GitHub in our menu entry,
  instead of "Contribute on GitHub", just say "Contribute".
  destination URL is our contribute page then -
  that is also more useful for ppl doing eg. translations
2025-01-23 00:51:06 +01:00
adb 9ac5e714b8 Merge pull request #3555 from deltachat/adb/update-deps-22/1/25
update some dependencies
2025-01-22 13:40:08 +01:00
adbenitez 94defa3091 update some dependencies 2025-01-22 01:43:21 +01:00
adbenitez 052ada221e update some deps 2025-01-22 01:42:21 +01:00
adbenitez 1d5e4cf2a9 update README 2025-01-22 00:54:00 +01:00
adbenitez c46aef3ea0 Merge remote-tracking branch 'upstream/main' 2025-01-22 00:52:57 +01:00
adb d30e141693 Merge pull request #3554 from deltachat/adb/issue-3542
avoid crash in MediaPreviewActivity.onPageUnselected
2025-01-21 20:09:51 +01:00
adb 305940396e Merge branch 'main' into adb/issue-3542 2025-01-21 19:39:33 +01:00
adbenitez 2ab567a9d3 use Log instead of stack trace 2025-01-21 19:38:43 +01:00
adb a9c488ff03 Merge pull request #3365 from deltachat/adb/issue-3361
revert #3177
2025-01-21 19:01:18 +01:00
adbenitez 8817b50c95 avoid crash in MediaPreviewActivity.onPageUnselected 2025-01-21 18:56:59 +01:00
adb 84c3710a35 Merge pull request #3553 from deltachat/adb/issue-3550
avoid ANR in ConversationFragment.manageMessageSeenState()
2025-01-21 18:51:00 +01:00
adbenitez be7be9bba4 avoid ANR in ConversationFragment.manageMessageSeenState() 2025-01-21 18:13:54 +01:00
adb b50ae284fb Merge pull request #3551 from deltachat/adb/issue-3549
fix: make animated webp animated again
2025-01-21 17:38:52 +01:00
adbenitez 97716d5c26 fix: make animated webp animated again 2025-01-21 16:57:03 +01:00
bjoern e77253c843 update translations (#3548)
* add string 'Unsave'

* pull translations
2025-01-20 15:14:54 +01:00
adbenitez 6aed8d003f deprecate string 2025-01-18 20:53:56 +01:00
adbenitez 0083e60c49 revert #3177 2025-01-18 20:53:56 +01:00
adbenitez 0fc79fd845 Merge remote-tracking branch 'upstream/main' 2025-01-18 20:39:03 +01:00
B. Petersen a7c3bc7ac5 add missing desktop strings 2025-01-17 17:40:35 +01:00
B. Petersen 83b16e5f4b do not force ppl to create blank issues
see https://github.com/deltachat/deltachat-ios/pull/2525
for screenshots and reasoning
2025-01-17 10:39:10 +01:00
adbenitez ee17c6d75e Merge remote-tracking branch 'upstream/main' 2025-01-16 21:10:25 +01:00
adb c0525ac69c Merge pull request #3544 from deltachat/adb/issue-3543
avoid null in attachment filename
2025-01-16 20:42:41 +01:00
adbenitez e9d2a39098 avoid null in attachment filename 2025-01-16 20:03:43 +01:00
adb 4d6fd16767 Merge pull request #3541 from deltachat/adb/issue-3540
avoid race condition in onPlayerStateChanged inside AudioSlidePlayer.requestDuration
2025-01-16 14:55:07 +01:00
adb b398870823 Merge pull request #3535 from deltachat/adb/issue-3534
fix IntentUtils.showBrowserIntent() and use it everywhere
2025-01-15 21:02:01 +01:00
adbenitez e68c50d614 avoid race condition in onPlayerStateChanged inside AudioSlidePlayer.requestDuration 2025-01-15 20:56:32 +01:00
adbenitez f6a27718a2 rename showBrowserIntent to showInBrowser 2025-01-15 20:33:16 +01:00
Hocuri f136fa3e3a Update the core submodule so that we can have nightlies again (#3539)
* Remove jsonrpc feature

* Update submodule to latest main
2025-01-15 16:18:43 +00:00
Hocuri 8e55a3dbf3 fix: Use getFilename() instead of the actual filename on disk (#3521)
* fix: Use msg.getFilename() instead of the file's name in some cases

* fix: Use msg.getFilename() instead of the file's name in initializeDraft()

* fix: Use msg.getFilename() instead of the file's name in MediaItem

* fix: Use the correct file name in MediaView

* refactor: `msg` param of `getManuallyCalculatedSlideInfo()` was always null

* Improve comment

* Revert "refactor: `msg` param of `getManuallyCalculatedSlideInfo()` was always null"

We will unfortunately need getManuallyCalculatedSlideInfo() with `msg`
param

This reverts commit 60e8248db32dc22812d3f23da194bab644802045.

* fix: Fix drafting images

This fixes a bug introduced in 14f69f87e8b11a7d0568e58593946a1f1c01e75e:
When you drafted an image, pressed Back, and opened the chat again, then
the height of the drafted image was wrong and tapping the image opened a
preview for the wrong image.

I do think that theoretically it would be nicer to use getSlideForMsg
here, because we already have a DcMsg, but this didn't work because a)
the width and height wasn't gotten from the msg and instead 0 was passed
and b) the code tries to save a msgId instead of the message instead,
and loading the message from the database fails later since it's just a
draft.

I didn't want to try and fix these things, because they might be bigger
refactorings and I don't know the code.

* fix: Use the original message's filemime if there is one

...instead of trying to guess the mimetype from the uri
2025-01-15 16:40:23 +01:00
B. Petersen 923227a0e8 update translations 2025-01-14 11:49:07 +01:00
adbenitez 14ecafe0e2 fix IntentUtils.showBrowserIntent() and use it everywhere 2025-01-11 19:45:37 +01:00
adb b93f8323ab Merge pull request #3532 from deltachat/prep-1.50.5
prepare 1.50.5 release
2025-01-10 19:37:38 +01:00
adbenitez 77f43cde9a prepare 1.50.5 release 2025-01-10 18:48:53 +01:00
adb e4d018393d Merge pull request #3531 from deltachat/adb/update-translations-10/01/25
update translations
2025-01-10 18:44:58 +01:00
adbenitez 9a816090de Merge remote-tracking branch 'upstream/main' 2025-01-10 18:44:47 +01:00
adbenitez 4b04aa65be update translations 2025-01-10 18:42:31 +01:00
B. Petersen 489bb55788 detach Android and iOS releases 2025-01-10 17:26:16 +01:00
adb 9d244611bc Merge pull request #3526 from deltachat/adb/issue-3525
use synchronized block to avoid IllegalMonitorStateException
2025-01-10 16:06:13 +01:00
Hocuri 3533916149 Put the synchronized around the whole while loop 2025-01-10 11:05:44 +01:00
adbenitez 46bc3e7f72 Merge remote-tracking branch 'upstream/main' 2025-01-10 01:36:50 +01:00
adbenitez ed0f0107e3 update to new gplay app id and key 2025-01-10 01:31:42 +01:00
adbenitez a855d7043a fix FetchForegroundService 2025-01-10 00:49:30 +01:00
adbenitez 66fd795763 try to fix CI 2025-01-09 19:06:15 +01:00
B. Petersen 05da43484f remove deprecated strings 2025-01-09 19:03:21 +01:00
adbenitez a58de2278b use synchronized block to avoid IllegalMonitorStateException 2025-01-09 18:36:12 +01:00
adbenitez 6743df23e9 update google-services.json 2025-01-09 18:01:16 +01:00
bjoern 35ec0d05e2 update translations (#3524)
* add new iOS notification strings

* update translations
2025-01-09 16:08:18 +01:00
bjoern 6ead7207ec update translations (#3522)
* update translations

* add new iOS widget strings

* add hints for terms 'Shortcut' and 'Widget'

* update translations
2025-01-09 15:26:42 +01:00
adbenitez 0d5223036d Merge remote-tracking branch 'upstream/main' 2025-01-07 16:36:45 +01:00
adbenitez 640fc433b8 add gdpr.md 2025-01-07 16:29:03 +01:00
adbenitez 35d814c3f6 update build.gradle 2025-01-06 21:26:22 +01:00
adbenitez f8b9d2b0d9 update core 2025-01-06 20:50:30 +01:00
adb 3390b865e0 Merge pull request #3519 from deltachat/prep-1.50.4
Prep 1.50.4
2025-01-06 15:40:55 +01:00
adbenitez 883486da9c tweak changelog 2025-01-06 15:26:49 +01:00
adbenitez d048203f45 update version number 2025-01-06 15:19:17 +01:00
adbenitez f9d70d1196 update changelog 2025-01-06 15:18:54 +01:00
adb 4413b7b4fb Merge pull request #3518 from deltachat/update-core-and-stuff-6/1/25
Update translations and core to v1.153.0
2025-01-06 14:58:14 +01:00
adbenitez 7a4f263a62 update translations 2025-01-06 14:55:55 +01:00
adbenitez 1a360d5282 update deltachat-core-rust to 'chore(release): prepare for 1.153.0' of 'v1.153.0' 2025-01-06 14:16:09 +01:00
Hocuri dc785fc116 fix: Remove long stacktrace that flooded the logcat (#3512)
Everytime I attached an image, I got a super long stacktrace in the
logcat. I found it to be [this problem](https://stackoverflow.com/questions/71746801/getting-failed-to-inflate-colorstatelist-leaving-it-to-the-framework-when-usi)
and applied the fix described there.
2025-01-04 19:13:45 +01:00
adbenitez 009593f7cc remove dead code 2025-01-04 16:06:40 +01:00
adb 884be3a93e Merge pull request #3516 from deltachat/adb/avoid-npe-in-reactions
avoid NullPointerException when using result of Rpc.getMsgReactions
2025-01-04 16:02:49 +01:00
adbenitez 9a25328787 avoid NullPointerException when using result of Rpc.getMsgReactions 2025-01-04 12:50:25 +01:00
adbenitez 2d8ec490b1 Merge remote-tracking branch 'upstream/main' 2025-01-04 12:21:28 +01:00
B. Petersen 3b19ca99e1 simpler copyright, it is anyways questionable by law, it is just a hint, that there is 'sth', this will do also without year 2025-01-03 19:58:55 +01:00
B. Petersen f751a48568 update local help 2025-01-03 16:48:52 +01:00
B. Petersen 4549989a63 update translations 2025-01-03 16:48:52 +01:00
B. Petersen 19e2c4e051 add info string that is shown by iOS system when asking for accessing Face ID 2025-01-03 15:03:54 +01:00
adbenitez 6f5e90be53 update build.gradle 2024-12-21 03:11:47 +01:00
adbenitez 34fa0620ab update full_description 2024-12-21 03:04:53 +01:00
adbenitez fe37af1a3f allow to jump to POI 2024-12-21 02:54:54 +01:00
adbenitez 3459802d67 update core 2024-12-20 19:52:40 +01:00
adbenitez b8bf847941 fix contact selection list 2024-12-20 19:51:59 +01:00
adbenitez 5b6024584a force sending sticker 2024-12-20 17:47:45 +01:00
adb 4833a44542 Merge pull request #3509 from deltachat/adb/issue-3488
try to avoid FILL500 getting stuck in some devices
2024-12-20 12:40:59 +01:00
adbenitez eb93e2bb7e add comment 2024-12-19 16:39:52 +01:00
adbenitez 291700dfc7 update lastOpenTime in onDestroy() 2024-12-19 16:30:58 +01:00
adbenitez 7a4913b394 tweak code 2024-12-19 15:52:16 +01:00
adbenitez 0dae71f4b7 try to avoid FILL500 getting stuck in some devices 2024-12-19 15:48:57 +01:00
Hocuri 08e4229533 Make the attachment background the same as the input bar background (#3477)
* Make the attachment background the same as the input bar background

Two different users recently complained that they find drafting images confusing. One of them thought that they had already sent it, the other one didn't know how to send it (both of them figured it out after ~10s, but still, it's nicer to avoid such confusion). In both cases, the problem was that the background of the attached file is the same as the chat background, not the same as the input bar, even though the attached file belongs to the input bar and not to the chat.

* Add a stroke around the to-be attachment
2024-12-19 13:30:24 +01:00
adbenitez 101a31628d lowercase Bot string for English and Spanish 2024-12-18 19:34:29 +01:00
adbenitez 2a2ce883b4 Merge remote-tracking branch 'upstream/main' 2024-12-18 19:33:04 +01:00
adbenitez 5a0e26bdb5 show last-seen status in contact list 2024-12-18 19:20:34 +01:00
B. Petersen 0c9277dfd0 remove email-address unconditionally from title
the email-address was removed for guaranteed-e2ee chats quite a while ago
(https://github.com/deltachat/deltachat-android/pull/2916) reason was, among others,
that these addresses are often chatmail and therefore random.
(despite expecting otherwise, that was fine for most users).

this PR removes the email-adress unconditionally:

- having the email-address sometimes shown and sometimes not is confusing,
  and easily looks like a bug.
  this has become worse with the added vcard-support
  (before, there were rare non-guaranteed chats in chatmail) -
  resulting in more random addresses being shown

- _always_ protect against over-the-shoulder attacks

- better privacy in screenshots sent around without thinking much before
  (cmp. https://github.com/deltachat/deltachat-ios/pull/2329)

- wrt impersonation attacks:
  the pure email address in the subtitle did never protect against impersonation,
  one could always get sth. trustworthy looking there,
  it is better to check the profile with additional information (eg. other chats) if in doubt

- general cleaner, uncluttered layout

- pave the way of the upcoming multi-addresses

drawback is that sometimes one more tap is needed to access the email-address -
however, as it is _always_ one tap away now,
this can also go easily to the finger memory.
2024-12-18 18:31:43 +01:00
adb 37886cf296 Merge pull request #3506 from deltachat/adb/issue-3502
run SendRelayedMessageUtil.sendMultipleMsgs() in background
2024-12-18 17:19:34 +01:00
adbenitez df5ba2eced call SendRelayedMessageUtil.sendMultipleMsgs() in background 2024-12-18 17:17:46 +01:00
adbenitez 3c2ddb96b3 update full_description 2024-12-18 16:04:30 +01:00
Hocuri e2a825dfb2 fix(ANR): Mark messages as seen asynchronously (#3505)
Mark messages as seen in a background thread instead of on the UI
thread in order to fix #3504.
2024-12-18 15:41:44 +01:00
Hocuri 8d49c7e595 fix: Fetch synchronously in the background if no foreground service is allowed (#3501)
Fix #3500.
2024-12-18 13:19:47 +01:00
B. Petersen 966d5dac24 do not lowercase string 'Bot'
it is regarded as a bug
and esp. weird in translations.

it was regarded to be a bit 'nerdy' that time to write it lowercase,
but it seems we have to get more serious now.
2024-12-17 17:43:21 +01:00
adb 7f684f4d2e Merge pull request #3499 from deltachat/adb/issue-3498
avoid IllegalArgumentException dismissing dialog
2024-12-17 17:07:03 +01:00
adb 1510f7f3a8 Merge pull request #3497 from deltachat/adb/issue-3496
avoid NPE in ConversationListActivity.onNewIntent()
2024-12-17 16:32:45 +01:00
adbenitez 6916becf7f avoid IllegalArgumentException dismissing dialog 2024-12-17 16:13:37 +01:00
adbenitez ad5b496f5c avoid NPE in ConversationListActivity.onNewIntent() 2024-12-17 15:00:25 +01:00
adb e647401db4 Merge pull request #3491 from deltachat/adb/issue-3490
improve emoji pickers
2024-12-17 14:47:43 +01:00
adbenitez 3113f9c3ab optimize onConfigurationChanged() 2024-12-16 17:19:34 +01:00
adbenitez a1e47865c5 improve emoji pickers 2024-12-16 15:27:13 +01:00
adbenitez 3a5f9b3fed update app name to avoid confusion in f-droid 2024-12-13 22:48:31 +01:00
adbenitez 5ffbc19d03 Merge remote-tracking branch 'upstream/main' 2024-12-13 22:42:20 +01:00
adb d9db4b818a Merge pull request #3487 from deltachat/prep-1.50.3
Prepare 1.50.3
2024-12-13 20:12:04 +01:00
adbenitez 693efdbd0f add back device message 2024-12-13 20:10:45 +01:00
adbenitez 399b783437 update changelog 2024-12-13 19:30:34 +01:00
adbenitez 4bc574dfbe change version name 2024-12-13 19:29:47 +01:00
adbenitez 294af0981d disable previous version's device message 2024-12-13 18:28:25 +01:00
adbenitez e8c7014993 update changelog 2024-12-13 18:27:25 +01:00
adbenitez 0edc8303c1 update version number 2024-12-13 14:21:20 +01:00
adb 8c89c3e225 Merge pull request #3484 from deltachat/adb/issue-3479
download .xdc files in background
2024-12-13 14:12:42 +01:00
adb a93c8ab055 Merge pull request #3485 from deltachat/adb/issue-3481
add missing webxdc api
2024-12-13 14:00:12 +01:00
adbenitez c5cb79d116 add missing webxdc api 2024-12-13 13:42:39 +01:00
adbenitez b3c50b9571 download .xdc files in background 2024-12-13 13:18:40 +01:00
adb 41579de502 Merge pull request #3483 from deltachat/update-core-and-stuff-13/12/24
Update core to 1.152.0
2024-12-13 12:50:54 +01:00
adbenitez e6f735b8bc update scripts/update-core.sh 2024-12-13 12:50:24 +01:00
adbenitez 70b6f2cdfa update strings 2024-12-13 12:36:09 +01:00
adbenitez c1e716d6a3 update deltachat-core-rust to 'chore(release): prepare for 1.152.0' of 'v1.152.0' 2024-12-13 12:36:09 +01:00
adb dde59b4673 Merge pull request #3482 from deltachat/link2xt/update-rust-1.83
Update Rust to 1.83.0
2024-12-13 12:33:51 +01:00
link2xt 9d77920adf build: update Rust to 1.83.0 2024-12-12 13:28:33 +00:00
link2xt 6f50ee0cfb build(nix): remove ndk-bundle 2024-12-12 13:28:33 +00:00
link2xt 4c86d6d49e chore: nix flake update 2024-12-12 12:47:08 +00:00
Hocuri 963327dd64 Remove prepareMsg (and OUT_PREPARING message state) (#3468)
This PR removes prepareMsg, which put messages into the OUT_PREPARING state and was used while videos were recoded. It also removes the now-unused method isIncreation().
- It was buggy because when you forwarded a message while it was InPreparation, or when the app was killed while a message is InPreparation, the message would stay InPreparation forever.
- Android is the only UI using this InPreparation (according to @r10s, I didn't check this myself), so we can simplify some things in core, which will also make it easier to deduplicate blob files.
2024-12-11 13:53:36 +01:00
adbenitez 5cba1ccd98 remove duplicate realtime preference 2024-12-09 11:57:51 +01:00
adbenitez de8e6b6852 remove store from main menu 2024-12-07 17:37:01 +01:00
141 changed files with 2631 additions and 2297 deletions
+3
View File
@@ -0,0 +1,3 @@
ko_fi: adbenitez
liberapay: adbenitez
custom: "https://arcanechat.myspreadshop.net"
+1 -1
View File
@@ -1 +1 @@
blank_issues_enabled: true
blank_issues_enabled: false
+1 -1
View File
@@ -51,7 +51,7 @@ jobs:
run: ./gradlew --no-daemon -PABI_FILTER=armeabi-v7a assembleFossDebug
- name: Upload APK
uses: actions/upload-artifact@v3
uses: actions/upload-artifact@v4
with:
name: app-preview.apk
path: 'build/outputs/apk/foss/debug/*.apk'
+7 -6
View File
@@ -49,11 +49,12 @@ jobs:
- name: Build APK
run: |
mkdir -p ~/.gradle
echo -n ${{ secrets.SIGNING_KEY }} | base64 -d >> ~/app.keystore
echo "DC_RELEASE_STORE_FILE=$HOME/app.keystore" >> ~/.gradle/gradle.properties
echo "DC_RELEASE_STORE_PASSWORD=${{ secrets.KEY_STORE_PASSWORD }}" >> ~/.gradle/gradle.properties
echo "DC_RELEASE_KEY_ALIAS=${{ secrets.ALIAS }}" >> ~/.gradle/gradle.properties
echo "DC_RELEASE_KEY_PASSWORD=${{ secrets.KEY_PASSWORD }}" >> ~/.gradle/gradle.properties
echo -n ${{ secrets.KEYSTORE_FILE }} | base64 -d >> ~/keystore.jks
echo "DC_RELEASE_STORE_FILE=$HOME/keystore.jks" >> ~/.gradle/gradle.properties
echo "DC_RELEASE_STORE_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> ~/.gradle/gradle.properties
echo "DC_RELEASE_KEY_ALIAS_FDROID=${{ secrets.ALIAS_FDROID }}" >> ~/.gradle/gradle.properties
echo "DC_RELEASE_KEY_ALIAS_GPLAY=${{ secrets.ALIAS_GPLAY }}" >> ~/.gradle/gradle.properties
echo "DC_RELEASE_KEY_PASSWORD=${{ secrets.KEYSTORE_PASSWORD }}" >> ~/.gradle/gradle.properties
./gradlew assembleFossRelease
rm build/outputs/apk/foss/release/*universal*
./gradlew assembleGplayRelease
@@ -63,7 +64,7 @@ jobs:
uses: softprops/action-gh-release@v1
with:
token: "${{ secrets.GITHUB_TOKEN }}"
body: '[<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite) [<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
body: '[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat) [<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite) [<img src="store/get-it-on-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite) [<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/chat.delta.lite) [<img src="store/get-it-on-github.png" alt="Get it on GitHub" height="48">](https://github.com/ArcaneChat/android/releases/latest/download/ArcaneChat-gplay.apk)'
prerelease: ${{ contains(github.event.ref, '-beta') }}
fail_on_unmatched_files: true
files: build/outputs/apk/foss/release/*.apk
+51
View File
@@ -1,5 +1,56 @@
# ArcaneChat Android Changelog
## v1.52.1 Testrun
2025-01
* the app now requires less storage on your SD card by deduplicating newly received/sent files
* some small bug fixes
* update translations
* update to core 1.155.1
## v1.52.0
2025-01
* new group consistency algorithm
* fix: don't show animated .webp stickers as static stickers
* fix the chat shortcuts (created via long-press in launcher) to properly support multi-profile
* fix some small bugs in certain android versions and special situations
* avoid the app freezing in slow phones in some situations
* improve menu in the help screen
* update translations
* update to core 1.155.0
## v1.50.5
2025-01
* fix push-notifications handling for certain devices where it was not working correctly
* update translations
* using core 1.153.0
## v1.50.4
2025-01
* properly send as animated stickers GIF files selected from keyboard
* improve emoji picker in landscape mode and when changing from landscape to portrait
* avoid crash when receiving push notifications if the user restricted the app from working in background
* improve UI when attaching a file or image to easily recognize it is attached but not sent yet
* avoid slow loading of in-chat apps in some devices when quickly re-opening an app after closing it
* allow to select multiple images at once in the media picker via "Gallery" button
* mark holiday notice messages as bot-generated
* don't mark contacts as bot when receiving location-only and sync messages
* prefer to encrypt even if peers have their preference to "no preference"
* start ephemeral messages timers when the chat is archived or noticed
* several bug fixes and updated translations
* update to core 1.153.0
## v1.50.3
2024-12
* Add in-chat apps picker to attachments options
* Notify replies and reactions to your messages in muted chats (can be disabled in settings)
* Cache HTTP GET requests (ex. when loading images from HTML messages)
* update to core 1.152.0
## v1.50.2
2024-12
+2 -1
View File
@@ -1,7 +1,8 @@
## ArcaneChat Android Client
A [Delta Chat](https://delta.chat/) client for Android.
A [Delta Chat](https://delta.chat/) client for Android. Learn more at: https://arcanechat.me
[<img src="store/get-it-on-gplay.png" alt="Get it on Google Play" height="48">](https://play.google.com/store/apps/details?id=com.github.arcanechat)
[<img src="store/get-it-on-fdroid.png" alt="Get it on F-Droid" height="48">](https://f-droid.org/packages/chat.delta.lite)
[<img src="store/get-it-on-IzzyOnDroid.png" alt="Get it on IzzyOnDroid" height="48">](https://apt.izzysoft.de/fdroid/index/apk/chat.delta.lite)
[<img src="store/get-it-on-apklis.png" alt="Disponible en Apklis" height="48">](https://www.apklis.cu/application/chat.delta.lite)
+43 -25
View File
@@ -1,5 +1,5 @@
plugins {
id 'com.android.application' version '8.1.4'
id 'com.android.application' version '8.5.2'
id 'com.google.gms.google-services' version '4.4.1'
}
@@ -33,8 +33,8 @@ android {
useLibrary 'org.apache.http.legacy'
defaultConfig {
versionCode 30000699
versionName "1.50.3"
versionCode 30000707
versionName "1.52.1"
applicationId "chat.delta.lite"
multiDexEnabled true
@@ -87,15 +87,45 @@ android {
storeFile file(DC_DEBUG_STORE_FILE )
}
}
release {
releaseFdroid {
// can be defined at `~/.gradle/gradle.properties` or at "Build/Generate signed APK"
if(project.hasProperty("DC_RELEASE_STORE_FILE")) {
storeFile file(DC_RELEASE_STORE_FILE)
storePassword DC_RELEASE_STORE_PASSWORD
keyAlias DC_RELEASE_KEY_ALIAS
keyAlias DC_RELEASE_KEY_ALIAS_FDROID
keyPassword DC_RELEASE_KEY_PASSWORD
}
}
releaseApk {
// can be defined at `~/.gradle/gradle.properties` or at "Build/Generate signed APK"
if(project.hasProperty("DC_RELEASE_STORE_FILE")) {
storeFile file(DC_RELEASE_STORE_FILE)
storePassword DC_RELEASE_STORE_PASSWORD
keyAlias DC_RELEASE_KEY_ALIAS_GPLAY
keyPassword DC_RELEASE_KEY_PASSWORD
}
}
releaseBundle {
if(project.hasProperty("DC_BUNDLE_STORE_FILE")) {
storeFile file(DC_BUNDLE_STORE_FILE)
storePassword DC_BUNDLE_STORE_PASSWORD
keyAlias DC_BUNDLE_KEY_ALIAS
keyPassword DC_BUNDLE_STORE_PASSWORD
}
}
}
productFlavors {
foss {
dimension "none"
buildConfigField "boolean", "USE_PLAY_SERVICES", "false"
}
gplay {
dimension "none"
apply plugin: "com.google.gms.google-services"
buildConfigField "boolean", "USE_PLAY_SERVICES", "true"
applicationId "com.github.arcanechat"
}
}
buildTypes {
@@ -114,23 +144,12 @@ android {
// nb: it is highly recommended to use the same settings in debug+release -
// otherwise problems might be noticed delayed only
minifyEnabled true
signingConfig signingConfigs.release
productFlavors.foss.signingConfig signingConfigs.releaseFdroid
productFlavors.gplay.signingConfig signingConfigs.releaseApk
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
productFlavors {
foss {
dimension "none"
buildConfigField "boolean", "USE_PLAY_SERVICES", "false"
}
gplay {
dimension "none"
apply plugin: "com.google.gms.google-services"
buildConfigField "boolean", "USE_PLAY_SERVICES", "true"
}
}
if(!project.hasProperty("ABI_FILTER")) {
splits {
abi {
@@ -190,7 +209,7 @@ dependencies {
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
implementation 'androidx.sharetarget:sharetarget:1.2.0'
implementation 'androidx.webkit:webkit:1.11.0'
implementation 'androidx.webkit:webkit:1.12.1'
implementation 'androidx.multidex:multidex:2.0.1'
implementation 'androidx.appcompat:appcompat:1.7.0'
implementation 'com.google.android.material:material:1.12.0'
@@ -210,7 +229,7 @@ dependencies {
implementation 'com.google.guava:guava:31.1-android'
implementation 'com.google.android.exoplayer:exoplayer-core:2.19.1' // plays video and audio
implementation 'com.google.android.exoplayer:exoplayer-ui:2.19.1'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
implementation 'androidx.constraintlayout:constraintlayout:2.2.0'
implementation 'com.google.zxing:core:3.3.0' // fixed version to support SDK<24
implementation ('com.journeyapps:zxing-android-embedded:4.3.0') { transitive = false } // QR Code scanner
implementation 'com.fasterxml.jackson.core:jackson-databind:2.11.1' // used as JSON library
@@ -218,14 +237,13 @@ dependencies {
implementation "me.leolin:ShortcutBadger:1.1.16" // display messagecount on the home screen icon.
implementation 'com.jpardogo.materialtabstrip:library:1.0.9' // used in the emoji selector for the tab selection.
implementation 'com.github.chrisbanes:PhotoView:2.1.3' // does the zooming on photos / media
implementation 'com.github.penfeizhou.android.animation:glide-plugin:2.25.0' // APNG & animated webp support.
implementation 'com.github.penfeizhou.android.animation:glide-plugin:3.0.2' // APNG & animated webp support.
implementation 'com.caverock:androidsvg-aar:1.4' // SVG support.
implementation 'com.github.bumptech.glide:glide:4.12.0'
annotationProcessor 'com.github.bumptech.glide:compiler:4.12.0'
annotationProcessor 'androidx.annotation:annotation:1.8.2'
annotationProcessor 'androidx.annotation:annotation:1.9.1'
implementation 'com.makeramen:roundedimageview:2.1.0' // crops the avatars to circles
implementation 'com.pnikosis:materialish-progress:1.5' // used only in the "Progress Wheel" in Share Activity.
implementation 'com.soundcloud.android:android-crop:1.0.1@aar' // used for profile and group avatar selection in Android SDK<19
implementation 'com.github.amulyakhare:TextDrawable:558677ea31' // number of unread messages,
// the one-letter circle for the contacts (when there is not avatar) and a white background.
implementation 'com.googlecode.mp4parser:isoparser:1.0.6' // MP4 recoding; upgrading eg. to 1.1.22 breaks recoding, however, i have not investigated further, just reset to 1.0.6
@@ -240,7 +258,7 @@ dependencies {
// <https://github.com/cketti/SafeContentResolver>
implementation 'de.cketti.safecontentresolver:safe-content-resolver-v14:1.0.0'
gplayImplementation('com.google.firebase:firebase-messaging:24.0.0') { // for PUSH notifications
gplayImplementation('com.google.firebase:firebase-messaging:24.1.0') { // for PUSH notifications
exclude group: 'com.google.firebase', module: 'firebase-core'
exclude group: 'com.google.firebase', module: 'firebase-analytics'
exclude group: 'com.google.firebase', module: 'firebase-measurement-connector'
@@ -254,7 +272,7 @@ dependencies {
testImplementation 'org.powermock:powermock-module-junit4-rule:1.6.1'
testImplementation 'org.powermock:powermock-classloading-xstream:1.6.1'
androidTestImplementation 'androidx.test:runner:1.6.1'
androidTestImplementation 'androidx.test:runner:1.6.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.6.1'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.6.1'
androidTestImplementation 'androidx.test:rules:1.6.1'
@@ -17,19 +17,21 @@ ArcaneChat is a Delta Chat client and was created with a focus on usability, goo
<b>Main differences with official Delta Chat client:</b>
<ul>
<li>Basic markdown support (bold, italic, strike, etc.)</li>
<li>Support for some markdown styles in text messages (bold, italic, strike, etc.)</li>
<li>Support for displaying Telegram's animated stickers (.tgs files)</li>
<li>Support for SVG images previews</li>
<li>Multiple color themes/skins</li>
<li>It is possible to disable accounts to completely disconnect them to save data/bandwidth</li>
<li>It is possible to disable profiles to completely disconnect them saving data/bandwidth</li>
<li>You can easily see the connection status of all your profiles in the profile switcher</li>
<li>A videochat instance is set by default</li>
<li>Replies to your messages in muted groups trigger notifications</li>
<li>Location streaming feature enabled by default and extra option to share location for 12 hours</li>
<li>Clicking on a message with a POI location, will open the POI on the map</li>
<li>Last-seen status of contacts is shown in your contact list, like in WhatsApp, Telegram, etc.</li>
<li>Videos are played in loop, useful for short GIF videos</li>
<li>Verified icon is shown in the chat list for the "Device Messages" chat</li>
<li>Voice messages have more aggressive compression in "worse quality" mode to save data plan</li>
<li>Automatic download of messages limited to 640KB by default</li>
<li>Account's display name is always shown in the app's title bar instead of the name of the app</li>
<li>Profile's display name is always shown in the app's title bar instead of the name of the app</li>
<li>Your avatar is visible to other users in Mailing Lists</li>
<li>Can be selected as app to open .xdc files</li>
<li>For mini-apps developers: there are some extra features in the WebXDC API, check https://github.com/ArcaneChat/android/#webxdc</li>
Generated
+26 -60
View File
@@ -3,15 +3,15 @@
"android": {
"inputs": {
"devshell": "devshell",
"flake-utils": "flake-utils_2",
"flake-utils": "flake-utils",
"nixpkgs": "nixpkgs"
},
"locked": {
"lastModified": 1720988215,
"narHash": "sha256-nQ0Zx0vAWJo0IOGNFjCOdIkDSgOpMa//GalR8tbTl3A=",
"lastModified": 1733948466,
"narHash": "sha256-o/uq/tU458Ykudi8Zk3sRga5iazkuSczt9wDOCUDOSU=",
"owner": "tadfisher",
"repo": "android-nixpkgs",
"rev": "5a052c62cdb51b210bc0717177d5bd014cba3df1",
"rev": "0bf99ffaea6a7c0948ae10cf2e40c2905e4e4d6b",
"type": "github"
},
"original": {
@@ -22,18 +22,17 @@
},
"devshell": {
"inputs": {
"flake-utils": "flake-utils",
"nixpkgs": [
"android",
"nixpkgs"
]
},
"locked": {
"lastModified": 1717408969,
"narHash": "sha256-Q0OEFqe35fZbbRPPRdrjTUUChKVhhWXz3T9ZSKmaoVY=",
"lastModified": 1728330715,
"narHash": "sha256-xRJ2nPOXb//u1jaBnDP56M7v5ldavjbtR6lfGqSvcKg=",
"owner": "numtide",
"repo": "devshell",
"rev": "1ebbe68d57457c8cae98145410b164b5477761f4",
"rev": "dd6b80932022cea34a019e2bb32f6fa9e494dfef",
"type": "github"
},
"original": {
@@ -47,11 +46,11 @@
"systems": "systems"
},
"locked": {
"lastModified": 1701680307,
"narHash": "sha256-kAuep2h5ajznlPMD9rnQyffWG8EM/C73lejGofXvdM8=",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "4022d587cbbfd70fe950c1e2083a02621806a725",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
@@ -65,29 +64,11 @@
"systems": "systems_2"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"lastModified": 1731533236,
"narHash": "sha256-l0KFg5HjrsfsO/JpG+r7fRrqm12kzFHyUHqHCVpMMbI=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"type": "github"
},
"original": {
"owner": "numtide",
"repo": "flake-utils",
"type": "github"
}
},
"flake-utils_3": {
"inputs": {
"systems": "systems_3"
},
"locked": {
"lastModified": 1710146030,
"narHash": "sha256-SZ5L6eA7HJ/nmkzGG7/ISclqe6oZdOZTNoesiInkXPQ=",
"owner": "numtide",
"repo": "flake-utils",
"rev": "b1d9ab70662946ef0850d488da1c9019f3a9752a",
"rev": "11707dc2f618dd54ca8739b309ec4fc024de578b",
"type": "github"
},
"original": {
@@ -98,11 +79,11 @@
},
"nixpkgs": {
"locked": {
"lastModified": 1720768451,
"narHash": "sha256-EYekUHJE2gxeo2pM/zM9Wlqw1Uw2XTJXOSAO79ksc4Y=",
"lastModified": 1733759999,
"narHash": "sha256-463SNPWmz46iLzJKRzO3Q2b0Aurff3U1n0nYItxq7jU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "7e7c39ea35c5cdd002cd4588b03a3fb9ece6fad9",
"rev": "a73246e2eef4c6ed172979932bc80e1404ba2d56",
"type": "github"
},
"original": {
@@ -114,11 +95,11 @@
},
"nixpkgs_2": {
"locked": {
"lastModified": 1723221148,
"narHash": "sha256-7pjpeQlZUNQ4eeVntytU3jkw9dFK3k1Htgk2iuXjaD8=",
"lastModified": 1733749988,
"narHash": "sha256-+5qdtgXceqhK5ZR1YbP1fAUsweBIrhL38726oIEAtDs=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "154bcb95ad51bc257c2ce4043a725de6ca700ef6",
"rev": "bc27f0fde01ce4e1bfec1ab122d72b7380278e68",
"type": "github"
},
"original": {
@@ -130,11 +111,11 @@
},
"nixpkgs_3": {
"locked": {
"lastModified": 1718428119,
"narHash": "sha256-WdWDpNaq6u1IPtxtYHHWpl5BmabtpmLnMAx0RdJ/vo8=",
"lastModified": 1728538411,
"narHash": "sha256-f0SBJz1eZ2yOuKUr5CA9BHULGXVSn6miBuUWdTyhUhU=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "e6cea36f83499eb4e9cd184c8a8e823296b50ad5",
"rev": "b69de56fac8c2b6f8fd27f2eca01dcda8e0a4221",
"type": "github"
},
"original": {
@@ -147,7 +128,7 @@
"root": {
"inputs": {
"android": "android",
"flake-utils": "flake-utils_3",
"flake-utils": "flake-utils_2",
"nixpkgs": "nixpkgs_2",
"rust-overlay": "rust-overlay"
}
@@ -157,11 +138,11 @@
"nixpkgs": "nixpkgs_3"
},
"locked": {
"lastModified": 1723429325,
"narHash": "sha256-4x/32xTCd+xCwFoI/kKSiCr5LQA2ZlyTRYXKEni5HR8=",
"lastModified": 1733970833,
"narHash": "sha256-sPEKtSaZk2CtfF9cdhtbY93S6qGq+d2PKI1fcoDfDaI=",
"owner": "oxalica",
"repo": "rust-overlay",
"rev": "65e3dc0fe079fe8df087cd38f1fe6836a0373aad",
"rev": "f7f4c59ccdf1bec3f1547d27398e9589aa94e3e8",
"type": "github"
},
"original": {
@@ -199,21 +180,6 @@
"repo": "default",
"type": "github"
}
},
"systems_3": {
"locked": {
"lastModified": 1681028828,
"narHash": "sha256-Vy1rq5AaRuLzOxct8nz4T6wlgyUR7zLU309k9mBC768=",
"owner": "nix-systems",
"repo": "default",
"rev": "da67096a3b9bf56a91d16901293e51ba5b49a27e",
"type": "github"
},
"original": {
"owner": "nix-systems",
"repo": "default",
"type": "github"
}
}
},
"root": "root",
+1 -2
View File
@@ -15,9 +15,8 @@
pkgs = import nixpkgs { inherit system overlays; };
android-sdk = android.sdk.${system} (sdkPkgs:
with sdkPkgs; [
build-tools-33-0-1
build-tools-34-0-0
cmdline-tools-latest
ndk-bundle
platform-tools
platforms-android-34
ndk-27-0-11902837
+4 -4
View File
@@ -28,7 +28,7 @@
"client_info": {
"mobilesdk_app_id": "1:922391085500:android:6f54e2c4e49405673e2bb9",
"android_client_info": {
"package_name": "chat.delta.lite.beta"
"package_name": "com.github.arcanechat.beta"
}
},
"oauth_client": [],
@@ -47,7 +47,7 @@
"client_info": {
"mobilesdk_app_id": "1:922391085500:android:aff82fbc40c8172e3e2bb9",
"android_client_info": {
"package_name": "chat.delta.lite"
"package_name": "com.github.arcanechat"
}
},
"oauth_client": [],
@@ -66,7 +66,7 @@
"client_info": {
"mobilesdk_app_id": "1:922391085500:android:92b4cf12669cc2083e2bb9",
"android_client_info": {
"package_name": "com.github.arcanechat"
"package_name": "chat.delta.lite"
}
},
"oauth_client": [],
@@ -85,7 +85,7 @@
"client_info": {
"mobilesdk_app_id": "1:922391085500:android:228a205b8aa2bacc3e2bb9",
"android_client_info": {
"package_name": "com.github.arcanechat.beta"
"package_name": "chat.delta.lite.beta"
}
},
"oauth_client": [],
+2 -2
View File
@@ -1,7 +1,7 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionSha256Sum=ff7bf6a86f09b9b2c40bb8f48b25fc19cf2b2664fd1d220cd7ab833ec758d0d7
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0.2-bin.zip
distributionSha256Sum=544c35d6bd849ae8a5ed0bcea39ba677dc40f49df7d1835561582da2009b961d
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
networkTimeout=10000
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
+27 -18
View File
@@ -702,12 +702,6 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcContext_resendMsgs(JNIEnv *env, job
}
JNIEXPORT jint Java_com_b44t_messenger_DcContext_prepareMsg(JNIEnv *env, jobject obj, jint chat_id, jobject msg)
{
return dc_prepare_msg(get_dc_context(env, obj), chat_id, get_dc_msg(env, msg));
}
JNIEXPORT jint Java_com_b44t_messenger_DcContext_sendMsg(JNIEnv *env, jobject obj, jint chat_id, jobject msg)
{
return dc_send_msg(get_dc_context(env, obj), chat_id, get_dc_msg(env, msg));
@@ -1370,12 +1364,6 @@ JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getId(JNIEnv *env, jobject obj)
return dc_msg_get_id(get_dc_msg(env, obj));
}
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isOutgoing(JNIEnv *env, jobject obj)
{
return (jboolean)(dc_msg_is_outgoing(get_dc_msg(env, obj))!=0);
}
JNIEXPORT jint Java_com_b44t_messenger_DcMsg_getSenderColor(JNIEnv *env, jobject obj)
{
return dc_msg_get_sender_color(get_dc_msg(env, obj));
@@ -1588,12 +1576,6 @@ JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isForwarded(JNIEnv *env, jobjec
}
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isIncreation(JNIEnv *env, jobject obj)
{
return dc_msg_is_increation(get_dc_msg(env, obj))!=0;
}
JNIEXPORT jboolean Java_com_b44t_messenger_DcMsg_isInfo(JNIEnv *env, jobject obj)
{
return dc_msg_is_info(get_dc_msg(env, obj))!=0;
@@ -1670,6 +1652,33 @@ JNIEXPORT void Java_com_b44t_messenger_DcMsg_setFile(JNIEnv *env, jobject obj, j
}
JNIEXPORT void Java_com_b44t_messenger_DcMsg_forceSticker(JNIEnv *env, jobject obj)
{
dc_msg_force_sticker(get_dc_msg(env, obj));
}
JNIEXPORT jstring Java_com_b44t_messenger_DcMsg_getPOILocation(JNIEnv *env, jobject obj)
{
char* temp = dc_msg_get_poi_location(get_dc_msg(env, obj));
jstring ret = JSTRING_NEW(temp);
dc_str_unref(temp);
return ret;
}
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setFileAndDeduplicate(JNIEnv *env, jobject obj, jstring file, jstring name, jstring filemime)
{
CHAR_REF(file);
CHAR_REF(name);
CHAR_REF(filemime);
dc_msg_set_file_and_deduplicate(get_dc_msg(env, obj), filePtr, namePtr, filemimePtr);
CHAR_UNREF(filemime);
CHAR_UNREF(name);
CHAR_UNREF(file);
}
JNIEXPORT void Java_com_b44t_messenger_DcMsg_setDimension(JNIEnv *env, jobject obj, int width, int height)
{
dc_msg_set_dimension(get_dc_msg(env, obj), width, height);
+4 -4
View File
@@ -126,7 +126,7 @@ if test -z $1 || test $1 = armeabi-v7a; then
TARGET_CC="$TOOLCHAIN/bin/armv7a-linux-androideabi21-clang" \
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
cargo build $RELEASEFLAG --target armv7-linux-androideabi -p deltachat_ffi --features jsonrpc
cargo build $RELEASEFLAG --target armv7-linux-androideabi -p deltachat_ffi
cp $CARGO_TARGET_DIR/armv7-linux-androideabi/$RELEASE/libdeltachat.a $jnidir/armeabi-v7a
fi
@@ -135,7 +135,7 @@ if test -z $1 || test $1 = arm64-v8a; then
TARGET_CC="$TOOLCHAIN/bin/aarch64-linux-android21-clang" \
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
cargo build $RELEASEFLAG --target aarch64-linux-android -p deltachat_ffi --features jsonrpc
cargo build $RELEASEFLAG --target aarch64-linux-android -p deltachat_ffi
cp $CARGO_TARGET_DIR/aarch64-linux-android/$RELEASE/libdeltachat.a $jnidir/arm64-v8a
fi
@@ -144,7 +144,7 @@ if test -z $1 || test $1 = x86; then
TARGET_CC="$TOOLCHAIN/bin/i686-linux-android21-clang" \
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
cargo build $RELEASEFLAG --target i686-linux-android -p deltachat_ffi --features jsonrpc
cargo build $RELEASEFLAG --target i686-linux-android -p deltachat_ffi
cp $CARGO_TARGET_DIR/i686-linux-android/$RELEASE/libdeltachat.a $jnidir/x86
fi
@@ -153,7 +153,7 @@ fi
TARGET_CC="$TOOLCHAIN/bin/x86_64-linux-android21-clang" \
TARGET_AR="$TOOLCHAIN/bin/llvm-ar" \
TARGET_RANLIB="$TOOLCHAIN/bin/llvm-ranlib" \
cargo build $RELEASEFLAG --target x86_64-linux-android -p deltachat_ffi --features jsonrpc
cargo build $RELEASEFLAG --target x86_64-linux-android -p deltachat_ffi
cp $CARGO_TARGET_DIR/x86_64-linux-android/$RELEASE/libdeltachat.a $jnidir/x86_64
fi
+1 -1
View File
@@ -1 +1 @@
1.77.0
1.83.0
+1
View File
@@ -4,3 +4,4 @@ find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/github.com
find ./src/main/assets/help/ -type f -name '*.html' | xargs sed -i 's/ArcaneChat/Delta Chat/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/github.com\/ArcaneChat/get.delta.chat/g'
find ./src/ -type f -name 'strings.xml' | xargs sed -i 's/ArcaneChat/Delta Chat/g'
sed -i 's/>Delta Chat</>ArcaneChat</g' ./src/main/res/values/strings.xml
+2
View File
@@ -1,3 +1,5 @@
#!/usr/bin/env bash
set -e # stop on all errors
git submodule update --init --recursive
-1
View File
@@ -30,7 +30,6 @@ echo ""
echo "and now: here is Delta Chat $VERSION - choose your flavour and mind your backups:"
echo "- 🍋 https://download.delta.chat/android/beta/deltachat-gplay-release-$VERSION.apk (google play candidate, overwrites existing installs, should keep data)"
echo "- 🍉 https://download.delta.chat/android/beta/deltachat-foss-debug-$VERSION.apk (f-droid candidate, can be installed beside google play)"
echo "- 🍏 https://testflight.apple.com/join/uEMc1NxS (ios, update to $VERSION may take a day or so)"
echo ""
echo "what to test: PLEASE_FILL_OUT"
@@ -93,7 +93,7 @@ public class SharingTest {
}
}
Uri uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(pngImage));
DcHelper.sharedFiles.put("/" + pngImage, 1);
DcHelper.sharedFiles.put(pngImage, 1);
Intent i = new Intent(Intent.ACTION_SEND);
i.setType("image/png");
-3
View File
@@ -20,7 +20,6 @@
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" android:maxSdkVersion="29" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />
@@ -329,8 +328,6 @@
android:theme="@style/TextSecure.ScribbleTheme"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name="com.soundcloud.android.crop.CropImageActivity" />
<activity android:name=".InstantOnboardingActivity"
android:theme="@style/TextSecure.LightTheme"
android:windowSoftInputMode="stateHidden|adjustResize"
+9 -8
View File
@@ -599,16 +599,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -621,14 +621,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+48 -48
View File
@@ -30,14 +30,14 @@
<li><a href="#was-sind-push-benachrichtigungen-wie-kann-ich-nachrichten-sofort-erhalten">Was sind Push-Benachrichtigungen? Wie kann ich Nachrichten sofort erhalten?</a></li>
<li><a href="#sind-push-benachrichtigungen-auf-ios-geräten-aktiviert-gibt-es-alternativen">Sind Push-Benachrichtigungen auf iOS-Geräten aktiviert? Gibt es Alternativen?</a></li>
<li><a href="#android-push">Sind Push-Benachrichtigungen auf Android-Geräten aktiviert/erforderlich?</a></li>
<li><a href="#privacy-notifications">Wie privat sind Delta Chat Push-Benachrichtigungen?</a></li>
<li><a href="#privacy-notifications">Wie privat sind Delta-Chat-Push-Benachrichtigungen?</a></li>
<li><a href="#warum-integriert-sich-delta-chat-in-zentralisierte-proprietäre-applegoogle-push-dienste">Warum integriert sich Delta Chat in zentralisierte, proprietäre Apple/Google-Push-Dienste?</a></li>
</ul>
</li>
<li><a href="#verschlüsselung-und-sicherheit">Verschlüsselung und Sicherheit</a>
<ul>
<li><a href="#welche-standards-werden-für-die-ende-zu-ende-verschlüsselung-verwendet">Welche Standards werden für die Ende-zu-Ende-Verschlüsselung verwendet?</a></li>
<li><a href="#whene2e">Wie kann ich wissen, ob Nachrichten Ende-zu-Ende verschlüsselt sind?</a></li>
<li><a href="#whene2e">Wie kann ich wissen, ob Nachrichten Ende-zu-Ende-verschlüsselt sind?</a></li>
<li><a href="#howtoe2ee">Wie kann ich garantierte Ende-zu-Ende-Verschlüsselung und grüne Häkchen erhalten?</a></li>
<li><a href="#e2eeguarantee">Was bedeuten das “Grüne Häkchen” und die “garantierte Ende-zu-Ende-Verschlüsselung”?</a></li>
<li><a href="#nocryptanymore">Ein Kontakt hat eine Nachricht von einem anderen Gerät gesendet”, was kann ich tun?</a></li>
@@ -65,10 +65,10 @@
<li><a href="#kann-ich-delta-chat-auf-mehreren-geräten-zur-selben-zeit-verwenden">Kann ich Delta Chat auf mehreren Geräten zur selben Zeit verwenden?</a></li>
<li><a href="#fehlersuche">Fehlersuche</a></li>
<li><a href="#backup">Manueller Transfer</a></li>
<li><a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung">Gibt es Pläne für eine Delta Chat Web-Anwendung?</a></li>
<li><a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung">Gibt es Pläne für eine Delta-Chat-Web-Anwendung?</a></li>
</ul>
</li>
<li><a href="#webxdc">Webxdc Apps</a>
<li><a href="#webxdc">Webxdc-Apps</a>
<ul>
<li><a href="#wie-privat-sind-webxdc-apps">Wie privat sind Webxdc Apps?</a></li>
<li><a href="#wo-bekomme-ich-webxdc-apps">Wo bekomme ich Webxdc Apps?</a></li>
@@ -153,7 +153,7 @@ auch wenn der Empfänger Delta Chat nicht benutzt.</p>
die sofortige Push-Benachrichtigungen für iOS- und Android-Geräte bieten.</p>
</li>
<li>
<p>Durchgängige <a href="#multiple-accounts">Multi-Profil</a> und Multi-Geräte-Unterstützung auf allen Plattformen.</p>
<p>Durchgängige <a href="#multiple-accounts">Multi-Profil-</a> und Multi-Geräte-Unterstützung auf allen Plattformen.</p>
</li>
<li>
<p>Interaktive <a href="https://webxdc.org/apps">Webanwendungen in Chats</a> für Spiele und für die Zusammenarbeit</p>
@@ -304,7 +304,7 @@ unter dem Text Ihrer Nachrichten.</p>
<li>entweder weil der Kontakt Ihnen direkt eine Nachricht gesendet hat,</li>
<li>weil der Kontakt etwas an eine Gruppe geschrieben hat, in der sie beide Mitglied sind,</li>
<li>weil der Kontakt Ihnen eine Lesebestätigung für eine von Ihnen geschriebene Nachricht gesendet hat</li>
<li>oder weil der Kontakt Daten mithilfe einer <a href="#webxdc">Webxdc App</a> an Ihre Delta Chat-App gesendet hat.</li>
<li>oder weil der Kontakt Daten mithilfe einer <a href="#webxdc">Webxdc-App</a> an Ihre Delta-Chat-App gesendet hat.</li>
</ul>
</li>
<li>Dies ist also kein Echtzeit-Online-Status - und wenn jemand nicht sofort antwortet, obwohl er online zu sein scheint, machen Sie sich keine Sorgen und geben Sie ihm etwas Raum. ;-)</li>
@@ -487,7 +487,7 @@ und Benachrichtigungen auf dem Telefon des Nutzers anzeigen kann.</p>
<p>iOS-Geräten, durch die Integration mit den Apple-Push-Diensten.</p>
</li>
<li>
<p>Android-Geräten, durch die Integration des Google FCM Push-Dienste,
<p>Android-Geräten, durch die Integration des Google-FCM-Push-Dienstes,
auch auf Geräten, die <a href="https://microg.org">microG</a>
anstelle von proprietärem Google-Code auf dem Telefon.</p>
</li>
@@ -518,7 +518,7 @@ keine Daten an Apple weitergibt, die Apple nicht bereits hat.</p>
</h3>
<p>Wenn ein „Push-Service“ verfügbar ist, aktiviert Delta Chat Push-Benachrichtigungen
<p>Wenn ein „Push-Service“ verfügbar ist, aktiviert Delta Chat Push-Benachrichtigungen,
um eine sofortige Nachrichtenzustellung für alle Chatmail-Benutzer zu erreichen.
Wenn Sie einen klassischen E-Mail-Anbieter anstelle von <a href="https://delta.chat/chatmail">chatmail</a> Servern verwenden,
sind Push-Benachrichtigungen nicht verfügbar.</p>
@@ -544,7 +544,7 @@ können sicher ausprobiert werden, wenn Sie feststellen, dass Nachrichten nur mi
<h3 id="privacy-notifications">
Wie privat sind Delta Chat Push-Benachrichtigungen? <a href="#privacy-notifications" class="anchor"></a>
Wie privat sind Delta-Chat-Push-Benachrichtigungen? <a href="#privacy-notifications" class="anchor"></a>
</h3>
@@ -557,16 +557,15 @@ an irgendein System, das an der Zustellung von Push-Benachrichtigungen beteiligt
<ul>
<li>
<p>Eine Delta-Chat-Anwendung erhält lokal ein „Geräte-Token“ (eine zufällige Zahl) und speichert es
<p>Eine Delta-Chat-Anwendung erhält lokal ein „Geräte-Token“, verschlüsselt und speichert es
auf dem <a href="https://delta.chat/chatmail">Chatmail</a>-Server.</p>
</li>
<li>
<p>Wenn ein <a href="https://delta.chat/chatmail">Chatmail</a>-Server eine E-Mail für einen Delta Chat-Benutzer erhält
erhält, leitet er den „Geräte-Token an den zentralen Delta-Chat-Benachrichtigungs-Proxy weiter.</p>
<p>Wenn ein <a href="https://delta.chat/chatmail">Chatmail</a>-Server eine E-Mail für einen Delta-Chat-Benutzer erhält
erhält, leitet er das verschlüsselte Geräte-Token an den zentralen Delta-Chat-Benachrichtigungs-Proxy weiter.</p>
</li>
<li>
<p>Der zentrale Delta-Chat-Benachrichtigungs-Proxy leitet
das „Geräte-Token“ an den jeweiligen Push-Dienst (Apple, Google, etc.) weiter,
<p>Der zentrale Delta-Chat-Benachrichtigungs-Proxy entschlüsselt das Geräte-Token und leitet es an den jeweiligen Push-Dienst (Apple, Google, etc.) weiter,
ohne jemals die IP- oder E-Mail-Adresse des Delta-Chat-Benutzers zu kennen.</p>
</li>
<li>
@@ -578,14 +577,15 @@ und auch nie den Inhalt einer Nachricht (auch nicht in verschlüsselter Form).</
</li>
</ul>
<p>Stand Mai 2024 kennen die Chatmail-Server die Geräte-Token,
aber wir planen, diese Informationen an den Benachrichtigungs-Proxy zu verschlüsseln
zu verschlüsseln, so dass der Chatmail-Server niemals das „Geräte-Token“ erfährt.</p>
<p>Der zentrale Delta-Chat-Benachrichtigungs-Proxy <a href="https://github.com/deltachat/notifiers">ist klein und vollständig in Rust implementiert</a>
und vergisst die Geräte-Token, sobald Apple/Google/etc. sie verarbeitet hat,
normalerweise innerhalb weniger Millisekunden.</p>
<p>Beachten Sie, dass das Geräte-Token zwischen Anwendungen und dem Benachrichtigungs-Proxy verschlüsselt,
aber nicht signiert ist.
Der Benachrichtigungs-Proxy sieht also niemals E-Mail-Adressen, IP-Adressen oder
irgendwelche kryptografischen Identitätsinformationen, die mit dem Gerät oder dem Geräte-Token eines Nutzers verbunden sind.</p>
<p>Aufgrund dieses umfassenden Datenschutzkonzepts würde sogar die Beschlagnahmung eines Chatmail-Servers,
oder die vollständige Beschlagnahmung des zentralen Delta-Chat-Benachrichtigungsproxys
keine privaten Informationen preisgeben, die den zentralen Push-Diensten nicht bereits vorliegen.</p>
@@ -627,7 +627,7 @@ Willkommen bei der Macht des interoperablen und massiven Chatmail- und E-Mail-Sy
<p><a href="https://autocrypt.org">Autocrypt</a> wird verwendet, um automatisch
eine Ende-zu-Ende-Verschlüsselung mit Kontakten und Gruppenchats herzustellen.
Autocrypt verwendet eine begrenzte und <a href="#openpgp-secure">sichere Untermenge des OpenPGP-Standards</a>.
Ende-zu-Ende verschlüsselte Nachrichten sind mit einem Vorhängeschloss gekennzeichnet <img style="vertical-align:middle; width:1.2em; margin:1px" src="../lock-icon.png" alt="padlock" /></p>
Ende-zu-Ende-verschlüsselte Nachrichten sind mit einem Vorhängeschloss gekennzeichnet <img style="vertical-align:middle; width:1.2em; margin:1px" src="../lock-icon.png" alt="padlock" /></p>
<p><a href="https://securejoin.delta.chat/en/latest/new.html">Secure-Join-Protokolle</a>
werden für Chats mit garantierter Ende-zu-Ende-Verschlüsselung verwendet,
@@ -639,7 +639,7 @@ garantieren Ende-zu-Ende-verschlüsselte Nachrichten.</p>
<h3 id="whene2e">
Wie kann ich wissen, ob Nachrichten Ende-zu-Ende verschlüsselt sind? <a href="#whene2e" class="anchor"></a>
Wie kann ich wissen, ob Nachrichten Ende-zu-Ende-verschlüsselt sind? <a href="#whene2e" class="anchor"></a>
</h3>
@@ -761,7 +761,7 @@ auch wenn der Kontakt dort Mitglied ist.</p>
<p><strong>Ihr Kontakt verwendet Delta Chat auf einem zweiten Gerät (Smartphone oder Laptop)</strong></p>
<p>Wenn Ihr Kontakt ein weiteres Gerät mit Delta Chat eingerichtet hat,
sollte das Konto von dem neuen Gerät entfernen werden und <a href="#multiclient">als zweites Gerät, wie hier beschrieben</a> erneut hinzugefügt werden.
sollte das Konto von dem neuen Gerät entfernen werden und <a href="#multiclient">als zweites Gerät, wie hier beschrieben</a>, erneut hinzugefügt werden.
Sobald sie sich danach schreiben, wird die Warnung verschwinden
und die Verschlüsselung ist mit beiden Geräten Ihres Kontakts garantiert.</p>
@@ -883,7 +883,7 @@ wenn dieser falsch ist.</p>
<p>Delta Chat war auch nie anfällig für den EFAIL-Angriff “Direct Exfiltration”,
da nur <code class="language-plaintext highlighter-rouge">multipart/encrypted</code> Nachrichten entschlüsselt werden,
die genau einen verschlüsselten und signierten Teil enthalten;
so wie in der Autocrypt Level 1 Spezifikation definiert.</p>
so wie in der Autocrypt-Level-1-Spezifikation definiert.</p>
<h3 id="tls">
@@ -949,7 +949,7 @@ Nachrichten an die Geräte der Empfänger weiterzuleiten und zuzustellen.</p>
</h3>
<p>Sowohl zum Schutz vor E-Mail-Servern, die Metadaten sammeln
<p>Sowohl zum Schutz vor E-Mail-Servern, die Metadaten sammeln,
als auch gegen die Gefahr der Beschlagnahmung von Geräten
empfehlen wir die Verwendung einer für Delta Chat optimierten <a href="https://delta.chat/serverguide">E-Mail-Server-Instanz</a>, um pseudonym-temporäre Konten durch Scannen von QR-Codes zu erstellen.
Beachten Sie, dass Delta-Chat-Apps auf allen Plattformen mehrere Konten unterstützen.
@@ -996,7 +996,7 @@ ohne Ende-zu-Ende-Unterstützung verwendet.</p>
</h3>
<p>Wenn ein Kontakt keine Autocrypt-fähige App verwendet,
werden alle Nachrichten, die diesen Kontakt betreffen (in Gruppen- oder Direkt-Chats)
werden alle Nachrichten, die diesen Kontakt betreffen (in Gruppen- oder Direkt-Chats),
nicht Ende-zu-Ende-verschlüsselt und zeigen daher kein “Vorhängeschloss”.
Beachten Sie, auch Kontakte, die primär Delta Chat verwenden,
können gleichzeitig auch nicht-Autocrypt-fähige Apps verwenden.
@@ -1012,7 +1012,7 @@ um zu verhindern, dass unlesbare Nachrichten auf der Seite Ihrer Kontakte ankomm
</h3>
<p>Wenn Sie einen sicheren Ende-zu-Ende-verschlüsselten Chat mit einem Kontakt benötigen,
der sowohl Delta Chat als auch nicht-Autocrypt-Anwendungen nutzt,
der sowohl Delta Chat als auch Nicht-Autocrypt-Anwendungen nutzt,
können Sie eine <a href="#howtoe2ee">garantierte Ende-zu-Ende-Verschlüsselung</a> einrichten, mit einer Gruppe mit Ihnen beiden als Mitgliedern.
In diesem Gruppenchat werden alle Nachrichten Ende-zu-Ende verschlüsselt werdejn,
auch wenn im Direkt-Chat eine
@@ -1026,10 +1026,10 @@ auch wenn im Direkt-Chat eine
</h3>
<p>Der beste Weg, um sicherzustellen, dass alle Nachrichten Ende-zu-Ende verschlüsselt sind
<p>Der beste Weg, um sicherzustellen, dass alle Nachrichten Ende-zu-Ende-verschlüsselt sind
und Metadaten so schnell wie möglich gelöscht werden,
ist <a href="#howtoe2ee">die Verwendung von Chats mit garantierter Ende-zu-Ende-Verschlüsselung</a>
und die Aktivierung von <a href="#ephemeralmsgs">Verschwindende Nachrichten</a>.</p>
und die Aktivierung von <a href="#ephemeralmsgs">verschwindenden Nachrichten</a>.</p>
<p>Garantierte Ende-zu-Ende-Verschlüsselung schützt vor <a href="https://en.wikipedia.org/wiki/Man-in-the-middle_attack">MITM-Angriffen</a>
und das Aktivieren von “Verschwindende Nachrichten” löscht die Nachrichten
@@ -1046,7 +1046,7 @@ auf dem Server und Lokal nach einer vom Benutzer eingestellten Zeit.</p>
</h3>
<p>Nein, Delta Chat unterstützt kein “Perfect Forward Secrecy” (PFS).
Das bedeutet, dass wenn Ihr privater Delta-Chat-Schlüssel durchgesickert ist,
Das bedeutet, wenn Ihr privater Delta-Chat-Schlüssel durchgesickert ist
und jemand Ihre vorherigen In-Transit-Nachrichten gesammelt hat,
können diese mit dem veröffentlichtem Schlüssel entschlüsselt werden.</p>
@@ -1057,7 +1057,7 @@ Die typische, reale Situation für durchgesickerte private Schlüssel, ist die <
OpenPGP ist nur ein Container für verschlüsselte Nachrichten mit dem
die Verwaltung der Schlüssel (und damit die Schlüsselrotation oder das Schlüssel-“Ratcheting”)
auf flexible Weise organisiert werden kann.
Siehe <a href="https://gitlab.com/sequoia-pgp/openpgp-dr">Seqouias PFS-Prototyp</a>
Siehe <a href="https://gitlab.com/sequoia-pgp/openpgp-dr">Seqouias PFS-Prototyp</a>
für bestehende Experimente in der OpenPGP-Community.</p>
<h3 id="ist-die-ende-zu-ende-verschlüsselung-von-delta-chat-genauso-sicher-wie-die-von-signal">
@@ -1146,7 +1146,7 @@ Für andere Programme können Sie online eine Lösung finden.</p>
Weitere Informationen finden Sie in unserem Blogbeitrag über <a href="https://delta.chat/en/2024-03-25-crypto-analysis-securejoin">Hardening Guaranteed End-to-End encryption</a> und in der hinterher publizierten <a href="https://eprint.iacr.org/2024/918.pdf">Kryptografischen Analyse von Delta Chat</a></p>
</li>
<li>
<p>Im April 2023 haben wir Sicherheits- und Datenschutzprobleme mit den “In Chats geteilten Apps”-Feature behoben, die mit Fehlern beim Sandboxing, insbesondere mit Chromium zusammenhängen. Wir haben daraufhin eine unabhängige Sicherheitsprüfung von Cure53 durchführen lassen, und alle gefundenen Probleme wurden mit den im April 2023 veröffentlichten 1.36 Releases behoben. Siehe <a href="https://delta.chat/en/2023-05-22-webxdc-security">hier für die vollständige Hintergrundgeschichte</a>.</p>
<p>Im April 2023 haben wir Sicherheits- und Datenschutzprobleme mit dem “In Chats geteilten Apps”-Feature behoben, die mit Fehlern beim Sandboxing, insbesondere mit Chromium zusammenhängen. Wir haben daraufhin eine unabhängige Sicherheitsprüfung von Cure53 durchführen lassen, und alle gefundenen Probleme wurden mit den im April 2023 veröffentlichten 1.36 Releases behoben. Siehe <a href="https://delta.chat/en/2023-05-22-webxdc-security">hier für die vollständige Hintergrundgeschichte</a>.</p>
</li>
<li>
<p>Im März 2023 analysierte <a href="https://cure53.de">Cure53</a> sowohl die Transportverschlüsselung von Delta Chats Netzwerkverbindungen als auch das reproduzierbare Mailserver-Setup wie <a href="https://delta.chat/de/serverguide">auf dieser Seite empfohlen</a>. Sie können mehr über das Audit <a href="https://delta.chat/en/2023-03-27-third-independent-security-audit">in unserem Blog</a> lesen oder Sie lesen den <a href="https://delta.chat/assets/blog/MER-01-report.pdf">vollständigen Bericht hier</a>.</p>
@@ -1156,7 +1156,7 @@ Weitere Informationen finden Sie in unserem Blogbeitrag über <a href="https://d
Es wurden keine kritischen oder hochgradig gefährlichen Probleme gefunden. Der Bericht wies auf einige Schwachstellen mittlerer Schwere hin - sie stellen für sich genommen keine Bedrohung für Delta-Chat-Benutzer dar, da sie von der Umgebung abhängen, in der Delta Chat verwendet wird. Aus Gründen der Benutzerfreundlichkeit und der Kompatibilität können wir nicht alle Schwachstellen beseitigen und haben beschlossen, Sicherheitsempfehlungen für bedrohte Benutzer zu geben. Sie können den <a href="https://delta.chat/assets/blog/2020-second-security-review.pdf">vollständigen Bericht hier</a> lesen.</p>
</li>
<li>
<p>Im Jahr 2019 analysierte <a href="https://includesecurity.com">Include Security</a> die von Delta Chat verwendeten <a href="https://github.com/rpgp/rpgp">PGP</a> und <a href="https://github.com/RustCrypto/RSA">RSA</a> Bibliotheken.
<p>Im Jahr 2019 analysierte <a href="https://includesecurity.com">Include Security</a> die von Delta Chat verwendeten <a href="https://github.com/rpgp/rpgp">PGP-</a> und <a href="https://github.com/RustCrypto/RSA">RSA-</a> Bibliotheken.
Es wurden keine kritischen Probleme gefunden, aber zwei Probleme mit hohem Schweregrad, die wir anschließend behoben haben. Außerdem wurden ein mittelschweres und einige weniger schwerwiegende Probleme gefunden, aber es gab keine Möglichkeit, diese Schwachstellen in der Delta-Chat-Implementierung auszunutzen. Einige dieser Schwachstellen haben wir dennoch nach Abschluss des Audits behoben. Sie können den [vollständigen Bericht hier] lesen (../assets/blog/2019-first-security-review.pdf).</p>
</li>
</ul>
@@ -1260,32 +1260,32 @@ Verwenden Sie nach Möglichkeit ein Nicht-Gast-Netzwerk. Wenn Sie Zugriff auf de
<li><strong>Wenn Sie iOS verwenden</strong> und auf Schwierigkeiten stoßen, hilft Ihnen vielleicht <a href="https://support.delta.chat/t/import-backup-to-ios/1628">diese Anleitung</a>.</li>
</ul>
</li>
<li>Sie sind nun synchronisiert und können beide Geräte zum Senden und Empfangen von Ende-zu-Ende verschlüsselten Nachrichten mit Ihren Kommunikationspartnern verwenden.</li>
<li>Sie sind nun synchronisiert und können beide Geräte zum Senden und Empfangen von Ende-zu-Ende-verschlüsselten-Nachrichten mit Ihren Kommunikationspartnern verwenden.</li>
</ul>
<h3 id="gibt-es-pläne-für-eine-delta-chat-web-anwendung">
Gibt es Pläne für eine Delta Chat Web-Anwendung? <a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung" class="anchor"></a>
Gibt es Pläne für eine Delta-Chat-Web-Anwendung? <a href="#gibt-es-pläne-für-eine-delta-chat-web-anwendung" class="anchor"></a>
</h3>
<ul>
<li>Es gibt keine direkten Pläne, aber einige vorläufige Gedanken.</li>
<li>Es gibt 2-3 Möglichkeiten, einen Delta Chat Web-Client einzuführen, aber sie bedeuten alle immense Arbeit. Im Moment fokussieren wir uns darauf, stabile native Apps in den Appstores (Google Play/iOS/Windows/macOS/Linux repositories) anzubieten.</li>
<li>Sollten Sie einen Web-Client benötigen, weil Sie auf Ihrem Arbeitsrechner keine Software installieren dürfen, können Sie den Windows Desktop-Client bzw. Applmage für Linux nutzen. Sie finden diese unter <a href="https://get.delta.chat">get.delta.chat</a>.</li>
<li>Es gibt 2-3 Möglichkeiten, einen Delta-Chat-Web-Client einzuführen, aber sie bedeuten alle immense Arbeit. Im Moment fokussieren wir uns darauf, stabile native Apps in den Appstores (Google Play/iOS/Windows/macOS/Linux repositories) anzubieten.</li>
<li>Sollten Sie einen Web-Client benötigen, weil Sie auf Ihrem Arbeitsrechner keine Software installieren dürfen, können Sie den Windows-Desktop-Client bzw. Applmage für Linux nutzen. Sie finden diese unter <a href="https://get.delta.chat">get.delta.chat</a>.</li>
</ul>
<h2 id="webxdc">
Webxdc Apps <a href="#webxdc" class="anchor"></a>
Webxdc-Apps <a href="#webxdc" class="anchor"></a>
</h2>
<p>In Delta Chat können Sie <a href="https://webxdc.org">Webxdc Apps</a>, Anhänge mit der Dateierweiterung “.xdc” teilen. Sie können sehr unterschiedliche Dinge tun und machen Delta Chat zu einem wirklich erweiterbaren Messenger.</p>
<p>In Delta Chat können Sie <a href="https://webxdc.org">Webxdc-Apps</a>, Anhänge mit der Dateierweiterung “.xdc” teilen. Sie können sehr unterschiedliche Dinge tun und machen Delta Chat zu einem wirklich erweiterbaren Messenger.</p>
<h3 id="wie-privat-sind-webxdc-apps">
@@ -1311,7 +1311,7 @@ Verwenden Sie nach Möglichkeit ein Nicht-Gast-Netzwerk. Wenn Sie Zugriff auf de
</h3>
<ul>
<li>Grundsätzlich kann jeder Webxdc Apps mit anderen ohne Einschränkungen teilen.</li>
<li>Grundsätzlich kann jeder Webxdc-Apps mit anderen ohne Einschränkungen teilen.</li>
<li>Von <a href="https://webxdc.org/apps/">webxdc.org/apps</a>.</li>
<li>Sie können <a href="https://delta.chat/en/2023-08-11-xstore">hallo an xstore@testrun.org senden</a>
um einen experimentellen Webxdc Appstore zu sehen.
@@ -1330,7 +1330,7 @@ forum</a> veröffentlicht und diskutiert.</li>
<ul>
<li>Webxdc Apps sind nur ZIP-Dateien, die HTML-, CSS- und JavaScript-Code enthalten.</li>
<li>Sie können die <a href="https://github.com/webxdc/hello">Hello World-Beispiel-App</a> erweitern, um loszulegen.</li>
<li>Sie können die <a href="https://github.com/webxdc/hello">Hello-World-Beispiel-App</a> erweitern, um loszulegen.</li>
<li>Alles andere, was Sie wissen müssen, steht in der <a href="https://docs.webxdc.org/">Dokumentation</a>.</li>
<li>Wenn Sie Fragen haben, können Sie andere mit Erfahrung im <a href="https://support.delta.chat/c/webxdc/20">Delta-Chat-Forum</a> fragen.</li>
</ul>
@@ -1643,7 +1643,7 @@ wenn Sie eine <a href="#signature">Signaturtext</a> einfügen.</p>
<ul>
<li>Ja und Nein.</li>
<li>Nein, Sie können sich nicht mit Delta Chat in ein Protonmail-, Tutanota- oder Criptext-Konto einloggen, da diese keinen Standard-E-Mail-Empfang über IMAP anbieten.</li>
<li>Ja, Sie können Delta Chat verwenden, um Nachrichten an Personen zu senden, die Protonmail, Tutanota oder Criptext verwenden. Diese Nachrichten werden jedoch nicht ende-zu-ende-verschlüsselt, da diese Anbieter keine mit dem <a href="https://autocrypt.org/">Autocrypt</a>-Standard kompatible Verschlüsselung verwenden.</li>
<li>Ja, Sie können Delta Chat verwenden, um Nachrichten an Personen zu senden, die Protonmail, Tutanota oder Criptext verwenden. Diese Nachrichten werden jedoch nicht Ende-zu-Ende-verschlüsselt, da diese Anbieter keine mit dem <a href="https://autocrypt.org/">Autocrypt</a>-Standard kompatible Verschlüsselung verwenden.</li>
<li>Delta Chat kann Ende-zu-Ende-Verschlüsselung über jeden E-Mail-Anbieter mit jeder
<a href="https://autocrypt.org/dev-status.html">Autocrypt-fähige E-Mail-Anwendung</a> herstellen</li>
</ul>
@@ -1712,7 +1712,7 @@ Andernfalls könnten Sie unverschlüsselte Nachrichten aus diesen Gruppenchats e
<p>Im <strong>Paketmanager</strong> Ihrer Linux-Distribution nachschauen</p>
</li>
<li>
<p><strong>Android APKs</strong> sind auch auf <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a> verfügbar.</p>
<p><strong>Android-APKs</strong> sind auch auf <a href="https://github.com/deltachat/deltachat-android/releases">https://github.com/deltachat/deltachat-android/releases</a> verfügbar.</p>
</li>
</ul>
@@ -1741,10 +1741,10 @@ Die zweite Förderung 2019/2020 (~$300K) half uns bei der Erstellung der iOS-Ve
<p>Die <a href="https://nlnet.nl/">NLnet-Stiftung</a> bewilligte 2019/2020 46K EUR für die Fertigstellung von Rust-/Python-Bindungs und die Einrichtung eines Chat-Bot-Ökosystems.</p>
</li>
<li>
<p>Im Jahr 2021 erhielten wir weitere EU-Mittel für zwei “Next-Generation-Internet” Anträge, nämlich für <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - E-Mail-Provider-Portabilitätsverzeichnis</a> (~97K EUR) und <a href="https://nlnet.nl/project/EmailPorting/">AEAP - E-Mail-Adressportierung</a> (~90K EUR). Ziel sind bessere Unterstützung von Mehrfachkonten, verbesserten QR-Code-Kontakt- und -Gruppen-Setups sowie Netzwerkverbesserungen auf allen Plattformen.</p>
<p>Im Jahr 2021 erhielten wir weitere EU-Mittel für zwei “Next-Generation-Internet”-Anträge, nämlich für <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - E-Mail-Provider-Portabilitätsverzeichnis</a> (~97K EUR) und <a href="https://nlnet.nl/project/EmailPorting/">AEAP - E-Mail-Adressportierung</a> (~90K EUR). Ziel sind bessere Unterstützung von Mehrfachkonten, verbesserten QR-Code-Kontakt- und -Gruppen-Setups sowie Netzwerkverbesserungen auf allen Plattformen.</p>
</li>
<li>
<p>Von Ende 2021 bis März 2023 erhielten wir eine <em>Internet Freedom</em> Finanzierung (500K USD) vom U.S. Bureau of Democracy, Human Rights and Labor (DRL). Diese Finanzierung unterstützte unsere langjährigen Ziele, Delta Chat benutzerfreundlicher und kompatibel mit einer breiten Palette von E-Mail-Servern weltweit zu machen, sowie widerstandsfähiger und sicherer an Orten, die häufig von Internetzensur und Abschaltungen betroffen sind.</p>
<p>Von Ende 2021 bis März 2023 erhielten wir eine <em>Internet-Freedom</em>-Finanzierung (500K USD) vom U.S. Bureau of Democracy, Human Rights and Labor (DRL). Diese Finanzierung unterstützte unsere langjährigen Ziele, Delta Chat benutzerfreundlicher und kompatibel mit einer breiten Palette von E-Mail-Servern weltweit zu machen, sowie widerstandsfähiger und sicherer an Orten, die häufig von Internetzensur und Abschaltungen betroffen sind.</p>
</li>
<li>
<p>2023-2024 schlossen wir erfolgreich das vom OTF finanzierte
@@ -1754,11 +1754,11 @@ das <a href="https://delta.chat/chatmail">Chatmail-Server-Netzwerk</a>
und „Instant Onboarding“ allen ab April 2024 veröffentlichten Anwendungen hinzu.</p>
</li>
<li>
<p>2023 und 2024 wurden wir in das Next Generation Internet (NGI)
Programm für unsere Arbeit an <a href="https://nlnet.nl/project/WebXDC-Push/">webxdc PUSH</a> aufgenommen,
<p>2023 und 2024 wurden wir in das Next-Generation-Internet-Programm (NGI)
für unsere Arbeit an <a href="https://nlnet.nl/project/WebXDC-Push/">Webxdc-PUSH</a> aufgenommen,
zusammen mit Kooperationspartnern, die an
<a href="https://nlnet.nl/project/Webxdc-Evolve/">webxdc evolve</a>,
<a href="https://nlnet.nl/project/WebXDC-XMPP/">webxdc XMPP</a>,
<a href="https://nlnet.nl/project/Webxdc-Evolve/">Webxdc-Evolve</a>,
<a href="https://nlnet.nl/project/WebXDC-XMPP/">Webxdc-XMPP</a>,
<a href="https://nlnet.nl/project/DeltaTouch/">DeltaTouch</a> und
<a href="https://nlnet.nl/project/DeltaTauri/">DeltaTauri</a>.
Alle diese Projekte sind teilweise abgeschlossen oder sollen Anfang 2025 abgeschlossen werden.</p>
@@ -1776,7 +1776,7 @@ Der Erhalt von Spenden hilft uns auch, unabhängiger und langfristig lebensfähi
<p>Die oben aufgeführte finanzielle Förderung wird hauptsächlich von der merlinux GmbH in Freiburg (Deutschland) organisiert und an mehr als ein Dutzend Mitwirkende weltweit verteilt.</p>
<p>Möglichkeiten mitzuwirken finden Sie Auf der <a href="https://delta.chat/de/contribute">Delta Chat Seite “Mitwirken”</a>.</p>
<p>Möglichkeiten mitzuwirken finden Sie Auf der <a href="https://delta.chat/de/contribute">Delta-Chat-Seite “Mitwirken”</a>.</p>
+9 -8
View File
@@ -603,16 +603,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -625,14 +625,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+9 -8
View File
@@ -597,16 +597,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -619,14 +619,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+40 -39
View File
@@ -8,7 +8,7 @@
<li><a href="#delta-chat-prend-il-en-charge-les-images-vidéos-et-autres-pièces-jointes-">Delta Chat prend-il en charge les images, vidéos et autres pièces jointes ?</a></li>
<li><a href="#multiple-accounts">What are profiles? How can I switch between them?</a></li>
<li><a href="#qui-peut-voir-ma-photo-de-profil-">Qui peut voir ma photo de profil ?</a></li>
<li><a href="#signature">Can I set a Bio/Signature/Status/Motto with Delta Chat?</a></li>
<li><a href="#signature">Puis-je afficher une Bio/Signature ou un Status/Motto avec Delta Chat?</a></li>
<li><a href="#que-signifient-épingler-sourdine-et-archiver-">Que signifient “épingler”, “sourdine” et “archiver” ?</a></li>
<li><a href="#que-signifie-le-point-vert-">Que signifie le point vert ?</a></li>
<li><a href="#ephemeralmsgs">How do disappearing messages work?</a></li>
@@ -115,14 +115,14 @@
</h2>
<p>Delta Chat is a reliable, decentralized and secure messaging app,
available for mobile and desktop platforms.</p>
<p>Delta Chat est une application de messagerie fiable, décentralisée et sécurisée,
Disponible pour les plateformes smartphone et ordinateurs de bureau.</p>
<p>Delta Chat feels like Whatsapp or Telegram but you can also use and regard it as an e-mail app.
You can signup anonymously to a variety of <a href="https://delta.chat/chatmail">interoperable chatmail servers</a>
which are minimal e-mail servers optimized for fast and secure operations.
Or you may use classic e-mail servers and an existing e-mail account
in which case Delta Chat acts as an e-mail app.</p>
<p>Delta Chat ressemble à Whatsapp ou Telegram mais vous pouvez aussi lutiliser et la considérer comme une application e-mail.
Vous pouvez vous inscrire anonymement à une variété <a href="https://delta.chat/chatmail">de serveurs chatmail interéopérables</a>
Qui sont des serveurs e-mails minimalistes optimisés pour des opérations rapides et sécurisées.
Ou vous pouvez utiliser des serveurs e-mail classiques et utiliser votre compte e-mail
dans ce cas Delta Chat agit comme une application de courriel.</p>
<p><img style="float:right; width:50%; max-width:360%; margin:1em;" src="../delta-what-optim.png" /></p>
@@ -134,15 +134,15 @@ in which case Delta Chat acts as an e-mail app.</p>
</h3>
<p>To securely setup contact with others <a href="#howtoe2ee">scan an invite QR code
or share an invite link</a>.
This is required when using a (default) chatmail-based chat profile
because chatmail servers reject un-encrypted outgoing messages.</p>
<p>Pour établir un contact en toute sécurité avec dautres personnes <a href="#howtoe2ee">scanner un code QR dinvitation
ou partager un lien dinvitation</a>.
Cette opération est nécessaire lors de lutilisation dun profil de discussion basé sur le chatmail (par défaut).
car les serveurs de chatmail rejettent les messages sortants non chiffrés.</p>
<p>If you create a chat profile with a classic e-mail address
you may manually create a contact if you know their e-mail address
and then write a message to them
even if the recipient is not using Delta Chat.</p>
<p>Si vous créez un profil discussion avec une adresse courriel classique
vous pouvez créer manuellement un contact si vous connaissez son adresse courriel
et lui écrire un message
même si le destinataire nutilise pas Delta Chat.</p>
<h3 id="quels-sont-les-avantages-de-delta-chat-par-rapport-aux-autres-messageries-">
@@ -154,23 +154,23 @@ even if the recipient is not using Delta Chat.</p>
<ul>
<li>
<p>Anonymous chat profiles with fast, secure and interoperable <a href="https://delta.chat/chatmail">chatmail servers</a>
which offer instant Push Notifications for iOS and Android devices.</p>
<p>Profils anonymes de discussion avec des <a href="https://delta.chat/chatmail">serveurs de chatmail</a> rapides, sécurisés et interopérables
qui offrent des notifications push instantanées pour les appareils iOS et Android.</p>
</li>
<li>
<p>Pervasive <a href="#multiple-accounts">multi-profile</a> and multi-device support on all platforms.</p>
<p>Fonctionnalités de <a href="#multiple-accounts">multi-profil</a> et de multi-appareil supportées sur toutes les plateformes.</p>
</li>
<li>
<p>Interactive <a href="https://webxdc.org/apps">web apps in chats</a> for gaming and collaboration</p>
<p><a href="https://webxdc.org/apps">web apps dans les chats</a> interactifs pour le gaming et la collaboration</p>
</li>
<li>
<p><a href="#security-audits">Audited end-to-end encryption</a>
safe against network and server attacks.</p>
<p><a href="#security-audits">Chiffrement de bout en bout audité</a>
contre les attaques ciblées sur le réseau et les serveurs.</p>
</li>
<li>
<p>Free and Open Source software, both app and server side.
Built on <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md">E-mail and Web Internet Standards</a>,
<a href="https://xkcd.com/927/">to avoid “yet another standard syndrome (xkcd 927)</a></p>
<p>Logiciel libre et open source, à la fois appli et côté serveur.
Construit sur des <a href="https://github.com/deltachat/deltachat-core-rust/blob/master/standards.md">Standards dInternet et de-mail</a>,
<a href="https://xkcd.com/927/">pour éviter le syndrome du “standard de plus” (xkcd 927)</a></p>
</li>
</ul>
@@ -256,16 +256,16 @@ that tend to cause unsolicited messages (“spam”) sooner or later.</p>
<h3 id="signature">
Can I set a Bio/Signature/Status/Motto with Delta Chat? <a href="#signature" class="anchor"></a>
Puis-je afficher une Bio/Signature ou un Status/Motto avec Delta Chat? <a href="#signature" class="anchor"></a>
</h3>
<p>Yes,
you can do so under <strong>Settings → Profile → Bio</strong>.
Your contacts who use Delta Chat will see it
when they view your contact details.
Moreover, it will appear as a classic e-mail signature.</p>
<p>Oui,
vous pouvez le faire sous <strong>Paramètres → Profil → Bio</strong>.
Vos contacts qui utilisent Delta Chat le verront
lorsquils consulteront vos coordonnées.
De plus, elle apparaîtra sous la forme dune signature classique sur vos courriels.</p>
<h3 id="que-signifient-épingler-sourdine-et-archiver-">
@@ -578,16 +578,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -600,14 +600,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+9 -8
View File
@@ -603,16 +603,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -625,14 +625,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+12 -11
View File
@@ -597,17 +597,17 @@ a qualsiasi sistema coinvolto nella consegna di Notifiche Push.</p>
<ul>
<li>
<p>Unapp Delta Chat ottiene un “gettone del dispositivo” localmente e lo memorizza
sul server <a href="https://delta.chat/chatmail">chatmail</a>.</p>
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>Quando un server <a href="https://delta.chat/chatmail">chatmail</a> riceve une-mail per un utente Delta Chat
inoltra il “gettone del dispositivo” al proxy di notifica centrale di Delta Chat.</p>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>Il proxy di notifica centrale di Delta Chat inoltra
il “gettone del dispositivo” al rispettivo servizio Push (Apple, Google, ecc.),
senza mai conoscere lIP o lindirizzo e-mail degli utenti Delta Chat.</p>
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
<p>Il Servizio Push centrale (Apple, Google, ecc.)
@@ -619,14 +619,15 @@ e inoltre non vedono mai il contenuto del messaggio (anche non in forma crittogr
</li>
</ul>
<p>A partire da Maggio 2024, i server chatmail conoscono i “gettoni del dispositivo”
ma prevediamo di crittografare queste informazioni nel proxy di notifica
in modo tale che il server chatmail non apprenda mai il gettone del dispositivo.</p>
<p>Il proxy di notifica centrale di Delta Chat <a href="https://github.com/deltachat/notifiers">è piccolo e completamente implementato in Rust</a>
e si dimentica dei gettoni del dispositivo non appena Apple/Google/ecc li elabora,
di solito nel giro di pochi millisecondi.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Come risultato di questo disegno complessivo sulla riservatezza, anche il sequestro di un server chatmail,
o il sequestro totale del proxy di notifica centrale di Delta Chat
non rivelerebbe informazioni private che i servizi Push non abbiano già.</p>
+9 -8
View File
@@ -597,16 +597,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -619,14 +619,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+6 -6
View File
@@ -494,23 +494,23 @@ nadal będziesz mógł pisać, ale nie będziesz już powiadamiany o żadnych no
<ul>
<li>
<p>Aplikacja Delta Chat uzyskuje lokalnie „token urządzenia” i przechowuje go na serwerze <a href="https://delta.chat/chatmail">chatmail</a>.</p>
<p>Aplikacja Delta Chat uzyskuje lokalnie „token urządzenia”, szyfruje i przechowuje go na serwerze <a href="https://delta.chat/chatmail">chatmail</a>.</p>
</li>
<li>
<p>Kiedy serwer <a href="https://delta.chat/chatmail">chatmail</a> odbierze wiadomość e-mail od użytkownika Delta Chat, przekazuje token urządzenia do centralnego serwera proxy powiadomień Delta Chat.</p>
<p>Kiedy serwer <a href="https://delta.chat/chatmail">chatmail</a> odbierze wiadomość e-mail od użytkownika Delta Chat, przekazuje zaszyfrowany token urządzenia do centralnego serwera proxy powiadomień Delta Chat.</p>
</li>
<li>
<p>Centralny serwer proxy powiadomień Delta Chat przekazuje token urządzenia do odpowiedniej usługi Push (Apple, Google itp.), nie znając nawet adresu IP ani adresu e-mail użytkowników Delta Chat.</p>
<p>Centralny serwer proxy powiadomień Delta Chat deszyfruje token urządzenia i przekazuje go do odpowiedniej usługi Push (Apple, Google itp.), nie znając nawet adresu IP ani adresu e-mail użytkowników Delta Chat.</p>
</li>
<li>
<p>Centralna usługa Push (Apple, Google itp.) budzi aplikację Delta Chat na twoim urządzeniu, aby sprawdzić w tle nowe wiadomości. Nie zna chatmaila ani adresu e-mail urządzenia, na którym się budzi. Centralne usługi push Apple/Google nigdy nie widzą adresu e-mail (nadawcy ani odbiorcy), a także nigdy nie widzą treści wiadomości (również w formie zaszyfrowanej).</p>
</li>
</ul>
<p>Od maja 2024 r. serwery chatmail znają „tokeny urządzenia”, ale planujemy szyfrować te informacje na serwerze proxy powiadomień, tak aby serwer chatmail nigdy nie poznał tokena urządzenia.</p>
<p>Centralny serwer proxy powiadomień Delta Chat <a href="https://github.com/deltachat/notifiers">jest mały i w pełni zaimplementowany w Rust</a> i zapomina o tokenach urządzeń zaraz po ich przetworzeniu przez Apple/Google/itp, zwykle w ciągu kilku milisekund.</p>
<p>Pamiętaj, że token urządzenia jest szyfrowany między aplikacjami a serwerem proxy powiadomień, ale nie jest podpisany. Serwer proxy powiadomień nigdy nie widzi adresów e-mail, adresów IP ani żadnych kryptograficznych informacji identyfikujących powiązanych z urządzeniem użytkownika (tokenem).</p>
<p>W wyniku tego ogólnego projektu ochrony prywatności nawet przejęcie serwera chatmail lub pełne przejęcie centralnego serwera proxy powiadomień Delta Chat nie spowodowałoby ujawnienia prywatnych informacji, których usługi Push jeszcze nie posiadają.</p>
<h3 id="dlaczego-delta-chat-integruje-się-ze-scentralizowanymi-zastrzeżonymi-usługami-push-applegoogle">
@@ -945,7 +945,7 @@ W przypadku innych programów można znaleźć rozwiązanie online.</p>
<p>W systemie <strong>iOS</strong> upewnij się, że jest przydzielony dostęp do opcji „Ustawienia » Aplikacje » Delta Chat » <strong>Sieć lokalna</strong></p>
</li>
<li>
<p>W systemie <strong>macOS</strong> włącz „Ustawienia systemowe » Prywatność i bezpieczeństwo » <strong>Sieć lokalna</strong> » Delta Chat”</p>
<p>W systemie <strong>macOS</strong> włącz „Preferencje systemowe » Ochrona i prywatność » <strong>Sieć lokalna</strong> » Delta Chat”</p>
</li>
<li>
<p>Twój system może mieć „zaporę ogniową”, o której wiadomo, że powoduje problemy (szczególnie w systemie Windows).
+9 -8
View File
@@ -597,16 +597,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -619,14 +619,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+9 -8
View File
@@ -600,16 +600,16 @@ Push-уведомления недоступны.</p>
<ul>
<li>
<p>Приложение Delta Chat локально получает “токен устройства” и сохраняет его
<p>Приложение Delta Chat локально получает “токен устройства” шифрует его и сохраняет
на сервере <a href="https://delta.chat/chatmail">chatmail</a>.</p>
</li>
<li>
<p>Когда сервер <a href="https://delta.chat/chatmail">chatmail</a> получает электронную почту для пользователя Delta Chat
он пересылает “токен устройства” центральному прокси-серверу уведомлений Delta Chat.</p>
он пересылает “зашифрованный токен устройства” центральному прокси-серверу уведомлений Delta Chat.</p>
</li>
<li>
<p>Центральный прокси-сервер уведомлений Delta Chat пересылает
“токен устройства” в соответствующую службу Push (Apple, Google и т. д.),
<p>Центральный прокси-сервер уведомлений Delta Chat расшифровывает “токен устройства” и
пересылает его в соответствующую службу Push (Apple, Google и т. д.),
даже не зная IP-адрес или адрес электронной почты пользователей Delta Chat.</p>
</li>
<li>
@@ -622,14 +622,15 @@ Push-уведомления недоступны.</p>
</li>
</ul>
<p>По состоянию на май 2024 года серверы chatmail знают о “токенах устройства”,
но мы планируем зашифровать эту информацию для прокси-сервера уведомлений
так, чтобы сервер chatmail не смог получить доступ к токену устройства.</p>
<p>Центральный прокси-сервер уведомлений Delta Chat <a href="https://github.com/deltachat/notifiers">небольшой и полностью реализован на Rust</a>
забывает о токенах устройств, как только Apple/Google/и т. д. обработали их,
обычно за несколько миллисекунд.</p>
<p>Обратите внимание, что токен устройства шифруется между приложениями и прокси-сервером уведомлений,
но не подписывается.
Прокси-сервер уведомлений не получает доступ к адресам электронной почты, IP-адресам
или криптографическим идентификационным данным устройства пользователя (токену).</p>
<p>В результате такого общего подхода к обеспечению конфиденциальности, даже захват почтового сервера chatmail,
или полный захват центрального прокси-сервера уведомлений Delta Chat
не раскроет конфиденциальную информацию, которой сервисы Push уже не обладают.</p>
+9 -8
View File
@@ -603,16 +603,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -625,14 +625,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+9 -8
View File
@@ -605,16 +605,16 @@ to any system involved in the delivery of Push Notifications.</p>
<ul>
<li>
<p>A Delta Chat app obtains a “device token” locally and stores it
<p>A Delta Chat app obtains a “device token” locally, encrypts it and stores it
on the <a href="https://delta.chat/chatmail">chatmail</a> server.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives an e-mail for a Delta Chat user
it forwards the device token to the central Delta Chat notification proxy.</p>
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
</li>
<li>
<p>The central Delta Chat notification proxy forwards
the “device token” to the respective Push service (Apple, Google, etc.),
<p>The central Delta Chat notification proxy decrypts the device token
and forwards it to the respective Push service (Apple, Google, etc.),
without ever knowing the IP or e-mail address of Delta Chat users.</p>
</li>
<li>
@@ -627,14 +627,15 @@ and also never see any message content (also not in encrypted forms).</p>
</li>
</ul>
<p>As of May 2024, chatmail servers know about “device tokens”
but we plan to encrypt this information to the notification proxy
such that the chatmail server never learns the device token.</p>
<p>The central Delta Chat notification proxy <a href="https://github.com/deltachat/notifiers">is small and fully implemented in Rust</a>
and forgets about device-tokens as soon as Apple/Google/etc processed them,
usually in a matter of milliseconds.</p>
<p>Note that the device token is encrypted between apps and notification proxy
but it is not signed.
The notification proxy thus never sees e-mail addresses, IP-addresses or
any cryptographic identity information associated with a users device (token).</p>
<p>Resulting from this overall privacy design, even the seizure of a chatmail server,
or the full seizure of the central Delta Chat notification proxy
would not reveal private information that Push services do not already have.</p>
+5 -5
View File
@@ -498,23 +498,23 @@ Push-сповіщення автоматично активуються для
<ul>
<li>
<p>Додаток Delta Chat отримує “токен пристрою” локально і зберігає його на сервері <a href="https://delta.chat/chatmail">chatmail</a>.</p>
<p>Додаток Delta Chat отримує “токен пристрою” локально, шифрує його і зберігає на сервері <a href="https://delta.chat/chatmail">chatmail</a>.</p>
</li>
<li>
<p>Коли <a href="https://delta.chat/chatmail">chatmail</a>-сервер отримує електронний лист від користувача Delta Chat він пересилає токен пристрою до центрального проксі-сповіщення Delta Chat.</p>
<p>Коли сервер <a href="https://delta.chat/chatmail">chatmail</a> отримує електронний лист від користувача Delta Chat він пересилає зашифрований токен пристрою до центрального проксі-сервера сповіщень Delta Chat.</p>
</li>
<li>
<p>Центральний проксі-сервер сповіщень Delta Chat пересилає токен пристрою до відповідного Push-сервісу (Apple, Google тощо), навіть не знаючи IP-адреси чи електронної пошти користувачів Delta Chat.</p>
<p>Центральний проксі-сервер сповіщень Delta Chat розшифровує токен пристрою і пересилає його до відповідного Push-сервісу (Apple, Google тощо), навіть не знаючи IP-адреси або електронної пошти користувачів Delta Chat.</p>
</li>
<li>
<p>Центральний Push-сервіс (Apple, Google тощо) запускає додаток Delta Chat на вашому пристрої щоб перевірити наявність нових повідомлень у фоновому режимі. Він не знає про пошту чату або адресу електронної пошти пристрою, який він пробуджує. Центральні служби Apple/Google Push ніколи не бачать адресу електронної пошти (відправника або одержувача) а також ніколи не бачать жодного вмісту повідомлення (навіть в зашифрованому вигляді).</p>
</li>
</ul>
<p>Станом на травень 2024 року chatmail-сервери знають про “токени пристроїв” але ми плануємо зашифрувати цю інформацію для проксі-сповіщень таким чином, щоб сервер чату ніколи не дізнався токен пристрою.</p>
<p>Центральний проксі для сповіщень Delta Chat <a href="https://github.com/deltachat/notifiers">невеликий і повністю реалізований на Rust</a> забуває про токени пристроїв, як тільки Apple/Google/etc обробили їх, зазвичай за лічені мілісекунди.</p>
<p>Зверніть увагу, що токен пристрою шифрується між програмами та проксі-сповіщеннями але не підписується. Таким чином, проксі-служба сповіщень ніколи не бачить адреси електронної пошти, IP-адреси або будь-яку криптографічну ідентифікаційну інформацію, пов’язану з пристроєм користувача (токеном).</p>
<p>В результаті цього загального дизайну конфіденційності, навіть захоплення chatmail-сервера, або повне вилучення центрального проксі-сервера повідомлень Delta Chat не призведе до розкриття приватної інформації, якої ще не мають Push-сервіси.</p>
<h3 id="чому-delta-chat-інтегрується-з-централізованими-пропрієтарними-push-сервісами-applegoogle">
File diff suppressed because it is too large Load Diff
Binary file not shown.
@@ -195,7 +195,6 @@ public class DcContext {
public native void deleteMsgs (int msg_ids[]);
public native void forwardMsgs (int msg_ids[], int chat_id);
public native boolean resendMsgs (int msg_ids[]);
public native int prepareMsg (int chat_id, DcMsg msg);
public native int sendMsg (int chat_id, DcMsg msg);
public native int sendTextMsg (int chat_id, String text);
public native int sendVideochatInvitation(int chat_id);
+7 -2
View File
@@ -156,19 +156,20 @@ public class DcMsg {
public native String getSetupCodeBegin ();
public native String getVideochatUrl ();
public native int getVideochatType ();
public native boolean isIncreation ();
public native void setText (String text);
public native void setSubject (String text);
public native void setHtml (String text);
public native void setFile (String file, String filemime);
public native void forceSticker ();
public native void setFileAndDeduplicate(String file, String name, String filemime);
public native void setDimension (int width, int height);
public native void setDuration (int duration);
public native void setLocation (float latitude, float longitude);
public native String getPOILocation ();
public void setQuote (DcMsg quote) { setQuoteCPtr(quote.msgCPtr); }
public native String getQuotedText ();
public native String getError ();
public native String getOverrideSenderName();
public native boolean isOutgoing();
public native int getSenderColor();
public String getSenderName(DcContact dcContact) {
@@ -209,6 +210,10 @@ public class DcMsg {
return ids;
}
public boolean isOutgoing() {
return getFromId() == DcContact.DC_CONTACT_ID_SELF;
}
public String getDisplayBody() {
return getText();
}
@@ -124,9 +124,6 @@ public class ApplicationContext extends MultiDexApplication {
e.printStackTrace();
}
}
if ("deltafans@nine.testrun.org".equals(ac.getConfig("configured_addr")) && !ac.isCommunity()) {
ac.setCommunityMode(true);
}
}
if (allAccounts.length == 0) {
dcAccounts.addAccount();
@@ -232,11 +229,10 @@ public class ApplicationContext extends MultiDexApplication {
TimeUnit.MILLISECONDS)
.setConstraints(constraints)
.build();
try {
// in Android 4 this throws exception due to R8/shrinking
WorkManager.getInstance(this)
.enqueueUniquePeriodicWork("FetchWorker", ExistingPeriodicWorkPolicy.KEEP, fetchWorkRequest);
} catch (Throwable e) {}
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
"FetchWorker",
ExistingPeriodicWorkPolicy.KEEP,
fetchWorkRequest);
AppCompatDelegate.setCompatVectorFromResourcesEnabled(true);
if (Prefs.isPushEnabled(this)) {
@@ -45,6 +45,7 @@ import android.text.TextWatcher;
import android.util.Log;
import android.util.Pair;
import android.view.KeyEvent;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
@@ -53,6 +54,7 @@ import android.view.View.OnFocusChangeListener;
import android.view.View.OnKeyListener;
import android.view.WindowManager;
import android.view.inputmethod.EditorInfo;
import android.widget.FrameLayout;
import android.widget.ImageButton;
import android.widget.ImageView;
import android.widget.TextView;
@@ -117,7 +119,7 @@ import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.concurrent.AssertedSuccessListener;
import org.thoughtcrime.securesms.util.guava.Optional;
import org.thoughtcrime.securesms.util.views.Stub;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
import org.thoughtcrime.securesms.video.recode.VideoRecoder;
import org.thoughtcrime.securesms.videochat.VideochatUtil;
@@ -173,11 +175,13 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
private View composePanel;
private ScaleStableImageView backgroundView;
private MessageRequestsBottomView messageRequestBottomView;
private ProgressDialog progressDialog;
private AttachmentTypeSelector attachmentTypeSelector;
private AttachmentManager attachmentManager;
private AudioRecorder audioRecorder;
private Stub<MediaKeyboard> emojiDrawerStub;
private FrameLayout emojiPickerContainer;
private MediaKeyboard emojiPicker;
protected HidingLinearLayout quickAttachmentToggle;
private InputPanel inputPanel;
@@ -317,10 +321,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
super.onConfigurationChanged(newConfig);
composeText.setTransport(sendButton.getSelectedTransport());
if (emojiDrawerStub.resolved() && container.getCurrentInput() == emojiDrawerStub.get()) {
if (emojiPicker != null && container.getCurrentInput() == emojiPicker) {
container.hideAttachedInput(true);
}
emojiPicker = null; // force reloading next time onEmojiToggle() is called
initializeBackground();
}
@@ -358,7 +363,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
for (int i = 0; i < uriCount; i++) {
uriList.add(multipleUris.getItemAt(i).getUri());
}
askSendingFiles(uriList, () -> SendRelayedMessageUtil.sendMultipleMsgs(this, chatId, uriList, null));
askSendingFiles(uriList, () -> {
Util.runOnAnyBackgroundThread(() -> {
SendRelayedMessageUtil.sendMultipleMsgs(this, chatId, uriList, null);
});
});
}
}
}
@@ -730,8 +739,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
handleReplyMessage(quote);
}
String filename = draft.getFile();
if (filename.isEmpty() || !new File(filename).exists()) {
String file = draft.getFile();
if (file.isEmpty() || !new File(file).exists()) {
future.set(!text.isEmpty());
updateToggleButtonState();
return future;
@@ -751,26 +760,21 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
};
File file = new File(filename);
Uri uri = Uri.fromFile(file);
switch (draft.getType()) {
case DcMsg.DC_MSG_IMAGE:
setMedia(uri, MediaType.IMAGE).addListener(listener);
setMedia(draft, MediaType.IMAGE).addListener(listener);
break;
case DcMsg.DC_MSG_GIF:
setMedia(uri, MediaType.GIF).addListener(listener);
setMedia(draft, MediaType.GIF).addListener(listener);
break;
case DcMsg.DC_MSG_AUDIO:
setMedia(uri, MediaType.AUDIO).addListener(listener);
setMedia(draft, MediaType.AUDIO).addListener(listener);
break;
case DcMsg.DC_MSG_VIDEO:
setMedia(uri, MediaType.VIDEO).addListener(listener);
break;
case DcMsg.DC_MSG_WEBXDC:
setMedia(draft, MediaType.DOCUMENT).addListener(listener);
setMedia(draft, MediaType.VIDEO).addListener(listener);
break;
default:
setMedia(uri, MediaType.DOCUMENT).addListener(listener);
setMedia(draft, MediaType.DOCUMENT).addListener(listener);
break;
}
@@ -804,7 +808,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
sendButton = ViewUtil.findById(this, R.id.send_button);
attachButton = ViewUtil.findById(this, R.id.attach_button);
composeText = ViewUtil.findById(this, R.id.embedded_text_editor);
emojiDrawerStub = ViewUtil.findStubById(this, R.id.emoji_drawer_stub);
emojiPickerContainer = ViewUtil.findById(this, R.id.emoji_picker_container);
composePanel = ViewUtil.findById(this, R.id.bottom_panel);
container = ViewUtil.findById(this, R.id.layout_container);
quickAttachmentToggle = ViewUtil.findById(this, R.id.quick_attachment_toggle);
@@ -976,14 +980,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
protected static final int ACTION_SEND_OUT = 1;
protected static final int ACTION_SAVE_DRAFT = 2;
private String getSelfReaction(int msgId) {
try {
final String [] selfReactions = rpc.getMsgReactions(dcContext.getAccountId(), msgId).getReactionsByContact().get(DcContact.DC_CONTACT_ID_SELF);
if (selfReactions != null && selfReactions.length > 0) return selfReactions[0];
} catch(Exception e) { e.printStackTrace(); }
return null;
}
protected ListenableFuture<Integer> processComposeControls(int action) {
return processComposeControls(action, composeText.getTextTrimmed(),
attachmentManager.isAttachmentPresent() ?
@@ -1032,7 +1028,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
msg = new DcMsg(dcContext, DcMsg.DC_MSG_FILE);
}
String path = attachment.getRealPath(this);
msg.setFile(path, null);
msg.setFileAndDeduplicate(path, attachment.getFileName(), null);
}
}
msg.setText(body);
@@ -1069,7 +1065,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
{
boolean doSend = true;
if (recompress==DcMsg.DC_MSG_VIDEO) {
Util.runOnMain(() -> {
progressDialog = ProgressDialog.show(
ConversationActivity.this,
"",
getString(R.string.one_moment),
true,
false
);
});
doSend = VideoRecoder.prepareVideo(ConversationActivity.this, dcChat.getId(), msg);
Util.runOnMain(() -> {
try {
progressDialog.dismiss();
} catch (final IllegalArgumentException e) {
// The activity is finishing/destroyed, do nothing.
}
});
}
if (doSend) {
@@ -1225,16 +1237,23 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
});
}
private void reloadEmojiPicker() {
emojiPickerContainer.removeAllViews();
emojiPicker = (MediaKeyboard) LayoutInflater.from(this).inflate(R.layout.conversation_activity_emojidrawer_stub, emojiPickerContainer, false);
emojiPickerContainer.addView(emojiPicker);
inputPanel.setMediaKeyboard(emojiPicker);
}
@Override
public void onEmojiToggle() {
if (!emojiDrawerStub.resolved()) {
inputPanel.setMediaKeyboard(emojiDrawerStub.get());
if (emojiPicker == null) {
reloadEmojiPicker();
}
if (container.getCurrentInput() == emojiDrawerStub.get()) {
if (container.getCurrentInput() == emojiPicker) {
container.showSoftkey(composeText);
} else {
container.show(composeText, emojiDrawerStub.get());
container.show(composeText, emojiPicker);
}
}
@@ -1262,7 +1281,8 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
if (quote.isPresent()) {
msg.setQuote(quote.get().getQuotedMsg());
}
msg.setFile(path, null);
msg.setFileAndDeduplicate(path, null, null);
msg.forceSticker();
dcContext.sendMsg(chatId, msg);
}
@@ -26,6 +26,7 @@ import android.content.Intent;
import android.content.res.Configuration;
import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.view.LayoutInflater;
@@ -210,7 +211,7 @@ public class ConversationFragment extends MessageSelectorFragment
public void onResume() {
super.onResume();
dcContext.marknoticedChat((int) chatId);
Util.runOnBackground(() -> dcContext.marknoticedChat((int) chatId));
if (list.getAdapter() != null) {
list.getAdapter().notifyDataSetChanged();
}
@@ -703,7 +704,7 @@ public class ConversationFragment extends MessageSelectorFragment
index++;
}
}
dcContext.markseenMsgs(ids);
Util.runOnAnyBackgroundThread(() -> dcContext.markseenMsgs(ids));
}
@@ -811,6 +812,9 @@ public class ConversationFragment extends MessageSelectorFragment
else if(messageRecord.getInfoType() == DcMsg.DC_INFO_WEBXDC_INFO_MESSAGE) {
WebxdcActivity.openWebxdcActivity(getContext(), messageRecord.getParent(), messageRecord.getWebxdcHref());
}
else if (!TextUtils.isEmpty(messageRecord.getPOILocation()) && messageRecord.getType() == DcMsg.DC_MSG_TEXT && !messageRecord.hasHtml()) {
WebxdcActivity.openMaps(getContext(), getListAdapter().getChat().getId(), "index.html#"+messageRecord.getPOILocation());
}
else {
String self_mail = dcContext.getConfig("configured_mail_user");
if (self_mail != null && !self_mail.isEmpty()
@@ -89,7 +89,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
public static final String CLEAR_NOTIFICATIONS = "clear_notifications";
public static final String ACCOUNT_ID_EXTRA = "account_id";
public static final String FROM_WELCOME = "from_welcome";
public static final String WARN_CANNOT_ENCRYPT = "warn_cannot_encrypt";
private ConversationListFragment conversationListFragment;
public TextView title;
@@ -257,6 +256,10 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
@Override
protected void onNewIntent(Intent intent) {
if (isFinishing()) {
Log.w(TAG, "Activity is finishing, aborting onNewIntent()");
return;
}
super.onNewIntent(intent);
setIntent(intent);
refresh();
@@ -274,11 +277,6 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
AccountManager.getInstance().switchAccountAndStartActivity(this, accountId);
}
String warnAddr = getIntent().getStringExtra(WARN_CANNOT_ENCRYPT);
if (!TextUtils.isEmpty(warnAddr)) {
DcHelper.showEncryptionRequiredDialog(this, warnAddr);
}
refreshAvatar();
refreshUnreadIndicator();
refreshTitle();
@@ -458,11 +456,8 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
case R.id.menu_all_media:
startActivity(new Intent(this, ProfileActivity.class));
return true;
case R.id.menu_webxdc_apps_store:
handleShowBot("juegos@buzon.uy", "OPENPGP4FPR:d3d403a734be71fe9293a00311fef80dbe5dbc89#a=juegos%40buzon.uy&n=&i=WQZY-8FODS3&s=ZQBkaclFzao");
return true;
case R.id.menu_public_bots:
handleShowBot("puente@buzon.uy", "OPENPGP4FPR:4B41E5AFAF78A0C71DB56138D5BEFED00A45F97A#a=puente%40buzon.uy&n=Public%20Bots&i=ZC_oaJtuvJP&s=5SE96rRovsK");
handleShowBot("botsindex@arcanechat.me", "https://i.delta.chat/#67889B0362BEDBFEE05ACD92C1D737FA632A9582&a=botsindex%40arcanechat.me&n=Public%20Bots&i=336MTEz38EH-RJxM9OKWygYK&s=TpVVGK6C4KrJmRG0bwHLalXt");
return true;
}
@@ -30,7 +30,6 @@ import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.google.android.material.textfield.TextInputLayout;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.components.AvatarSelector;
import org.thoughtcrime.securesms.components.InputAwareLayout;
@@ -147,10 +146,6 @@ public class CreateProfileActivity extends BaseActionBarActivity {
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
setAvatarView(data.getData());
break;
case Crop.REQUEST_CROP:
setAvatarView(Crop.getOutput(data));
break;
}
}
@@ -17,7 +17,6 @@ import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.loader.app.LoaderManager;
import com.b44t.messenger.DcChat;
@@ -26,7 +25,6 @@ import com.b44t.messenger.DcContext;
import com.bumptech.glide.load.engine.DiskCacheStrategy;
import com.bumptech.glide.request.target.SimpleTarget;
import com.bumptech.glide.request.transition.Transition;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.components.AvatarSelector;
import org.thoughtcrime.securesms.connect.DcHelper;
@@ -221,22 +219,7 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
updateGroup(groupName);
} else {
verified = !broadcast && allMembersVerified();
if (verified && getAdapter().getContacts().size() == 1) {
new AlertDialog.Builder(this)
.setMessage(R.string.create_verified_group_ask)
.setNeutralButton(R.string.learn_more, (d, w) -> DcHelper.openHelp(this, "#e2eeguarantee"))
.setPositiveButton(R.string.yes, (d, w) -> {
createGroup(groupName);
})
.setNegativeButton(R.string.no, (d, w) -> {
verified = false;
createGroup(groupName);
})
.setCancelable(true)
.show();
} else {
createGroup(groupName);
}
createGroup(groupName);
}
return true;
@@ -360,10 +343,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
case ScribbleActivity.SCRIBBLE_REQUEST_CODE:
setAvatarView(data.getData());
break;
case Crop.REQUEST_CROP:
setAvatarView(Crop.getOutput(data));
break;
}
}
@@ -41,7 +41,6 @@ import com.bumptech.glide.request.target.CustomTarget;
import com.bumptech.glide.request.transition.Transition;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.components.AvatarSelector;
import org.thoughtcrime.securesms.connect.AccountManager;
@@ -56,6 +55,7 @@ import org.thoughtcrime.securesms.profiles.ProfileMediaConstraints;
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
import org.thoughtcrime.securesms.qr.RegistrationQrActivity;
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
@@ -71,7 +71,7 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
private static final String DCACCOUNT = "dcaccount";
private static final String DCLOGIN = "dclogin";
private static final String INSTANCES_URL = "https://delta.chat/chatmail";
private static final String DEFAULT_CHATMAIL_HOST = "nine.testrun.org";
private static final String DEFAULT_CHATMAIL_HOST = "arcanechat.me";
public static final String QR_ACCOUNT_EXTRA = "qr_account_extra";
public static final String FROM_WELCOME = "from_welcome";
@@ -191,10 +191,6 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
setAvatarView(data.getData());
break;
case Crop.REQUEST_CROP:
setAvatarView(Crop.getOutput(data));
break;
case IntentIntegrator.REQUEST_CODE:
String qrRaw = data.getStringExtra(RegistrationQrActivity.QRDATA_EXTRA);
if (qrRaw == null) {
@@ -333,14 +329,14 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
privacyPolicyBtn.setOnClickListener(view -> {
if (!isDcLogin) {
WebViewActivity.openUrlInBrowser(this, "https://" + providerHost + "/privacy.html");
IntentUtils.showInBrowser(this, "https://" + providerHost + "/privacy.html");
}
});
signUpBtn.setOnClickListener(view -> createProfile());
findViewById(R.id.use_other_server).setOnClickListener((v) -> {
WebViewActivity.openUrlInBrowser(this, INSTANCES_URL);
IntentUtils.showInBrowser(this, INSTANCES_URL);
});
findViewById(R.id.login_button).setOnClickListener((v) -> {
startRegistrationActivity();
@@ -62,16 +62,16 @@ public class LocalHelpActivity extends WebViewActivity
webView.scrollTo(0, 0);
return true;
case R.id.learn_more:
openOnlineUrl("https://delta.chat");
openOnlineUrl("https://arcanechat.me");
return true;
case R.id.privacy_policy:
openOnlineUrl("https://delta.chat/gdpr");
openOnlineUrl("https://arcanechat.me/privacy.html");
return true;
case R.id.contribute:
openOnlineUrl("https://github.com/deltachat/deltachat-android");
openOnlineUrl("https://arcanechat.me/#contribute");
return true;
case R.id.report_issue:
openOnlineUrl("https://github.com/deltachat/deltachat-android/issues");
openOnlineUrl("https://github.com/ArcaneChat/android/issues");
return true;
}
return false;
@@ -207,7 +207,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
messageRecord = null;
long date = getIntent().getLongExtra(DATE_EXTRA, 0);
long size = getIntent().getLongExtra(SIZE_EXTRA, 0);
initialMedia = new MediaItem(null, getIntent().getData(), getIntent().getType(),
initialMedia = new MediaItem(null, getIntent().getData(), null, getIntent().getType(),
DcMsg.DC_MSG_NO_ID, date, size, false);
if (address != null) {
@@ -218,7 +218,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
} else {
messageRecord = dcContext.getMsg(msgId);
initialMedia = new MediaItem(Recipient.fromChat(context, msgId), Uri.fromFile(messageRecord.getFileAsFile()),
messageRecord.getFilemime(), messageRecord.getId(), messageRecord.getDateReceived(),
messageRecord.getFilename(), messageRecord.getFilemime(), messageRecord.getId(), messageRecord.getDateReceived(),
messageRecord.getFilebytes(), messageRecord.isOutgoing());
conversationRecipient = Recipient.fromChat(context, msgId);
}
@@ -232,12 +232,11 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
// if you search for the place where the media are loaded, go to 'onCreateLoader'.
Log.w(TAG, "Loading Part URI: " + initialMedia);
if (messageRecord != null) {
getSupportLoaderManager().restartLoader(0, null, this);
} else {
mediaPager.setAdapter(new SingleItemPagerAdapter(this, GlideApp.with(this),
getWindow(), initialMedia.uri, initialMedia.type, initialMedia.size));
getWindow(), initialMedia.uri, initialMedia.name, initialMedia.type, initialMedia.size));
}
}
@@ -313,7 +312,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
private void performSavetoDisk(@NonNull MediaItem mediaItem) {
SaveAttachmentTask saveTask = new SaveAttachmentTask(MediaPreviewActivity.this);
long saveDate = (mediaItem.date > 0) ? mediaItem.date : System.currentTimeMillis();
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, null));
saveTask.executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR, new Attachment(mediaItem.uri, mediaItem.type, saveDate, mediaItem.name));
}
private void showInChat() {
@@ -473,9 +472,12 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
MediaItemAdapter adapter = (MediaItemAdapter)mediaPager.getAdapter();
if (adapter != null) {
MediaItem item = adapter.getMediaItemFor(position);
if (item.recipient != null) item.recipient.removeListener(MediaPreviewActivity.this);
try {
MediaItem item = adapter.getMediaItemFor(position);
if (item.recipient != null) item.recipient.removeListener(MediaPreviewActivity.this);
} catch (IllegalArgumentException e) {
Log.w(TAG, "Ignoring invalid position index");
}
adapter.pause(position);
}
}
@@ -486,18 +488,20 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
private final GlideRequests glideRequests;
private final Window window;
private final Uri uri;
private final String name;
private final String mediaType;
private final long size;
private final LayoutInflater inflater;
SingleItemPagerAdapter(@NonNull Context context, @NonNull GlideRequests glideRequests,
@NonNull Window window, @NonNull Uri uri, @NonNull String mediaType,
@NonNull Window window, @NonNull Uri uri, @Nullable String name, @NonNull String mediaType,
long size)
{
this.glideRequests = glideRequests;
this.window = window;
this.uri = uri;
this.name = name;
this.mediaType = mediaType;
this.size = size;
this.inflater = LayoutInflater.from(context);
@@ -519,7 +523,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
MediaView mediaView = itemView.findViewById(R.id.media_view);
try {
mediaView.set(glideRequests, window, uri, mediaType, size, true);
mediaView.set(glideRequests, window, uri, name, mediaType, size, true);
} catch (IOException e) {
Log.w(TAG, e);
}
@@ -539,7 +543,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
@Override
public MediaItem getMediaItemFor(int position) {
return new MediaItem(null, uri, mediaType, DcMsg.DC_MSG_NO_ID, -1, -1, true);
return new MediaItem(null, uri, name, mediaType, DcMsg.DC_MSG_NO_ID, -1, -1, true);
}
@Override
@@ -604,7 +608,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
try {
//noinspection ConstantConditions
mediaView.set(glideRequests, window, Uri.fromFile(msg.getFileAsFile()),
mediaView.set(glideRequests, window, Uri.fromFile(msg.getFileAsFile()), msg.getFilename(),
msg.getFilemime(), msg.getFilebytes(), autoplay);
} catch (IOException e) {
Log.w(TAG, e);
@@ -633,6 +637,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
return new MediaItem(Recipient.fromChat(context, msg.getId()),
Uri.fromFile(msg.getFileAsFile()),
msg.getFilename(),
msg.getFilemime(),
msg.getId(),
msg.getDateReceived(),
@@ -655,6 +660,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
private static class MediaItem {
private final @Nullable Recipient recipient;
private final @NonNull Uri uri;
private final @Nullable String name;
private final @NonNull String type;
private final int msgId;
private final long date;
@@ -663,6 +669,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
private MediaItem(@Nullable Recipient recipient,
@NonNull Uri uri,
@Nullable String name,
@NonNull String type,
int msgId,
long date,
@@ -671,6 +678,7 @@ public class MediaPreviewActivity extends PassphraseRequiredActionBarActivity
{
this.recipient = recipient;
this.uri = uri;
this.name = name;
this.type = type;
this.msgId = msgId;
this.date = date;
@@ -111,8 +111,6 @@ public class NewConversationActivity extends ContactSelectionActivity {
int contactId = dcContext.lookupContactIdByAddr(addr);
if (contactId!=0 && dcContext.getChatIdByContactId(contactId)!=0) {
openConversation(dcContext.getChatIdByContactId(contactId));
} else if (contactId == 0 && dcContext.isChatmail()) {
DcHelper.showEncryptionRequiredDialog(this, addr);
} else {
String nameNAddr = contactId == 0 ? addr : dcContext.getContact(contactId).getNameNAddr();
new AlertDialog.Builder(this)
@@ -16,7 +16,6 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
import static org.thoughtcrime.securesms.connect.DcHelper.getContext;
import static org.thoughtcrime.securesms.service.IPCAddAccountsService.ACCOUNT_DATA;
import android.content.ActivityNotFoundException;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.res.Resources;
@@ -438,7 +437,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
.setPositiveButton(R.string.perm_continue, (dialog, which)-> {
// pass control to browser, we'll be back in business at (**)
activity.oauth2Requested = System.currentTimeMillis();
IntentUtils.showBrowserIntent(activity, oauth2url);
IntentUtils.showInBrowser(activity, oauth2url);
oauth2started.set(true);
})
.setCancelable(false)
@@ -493,11 +492,7 @@ public class RegistrationActivity extends BaseActionBarActivity implements DcEve
if (provider!=null) {
String url = provider.getOverviewPage();
if(!url.isEmpty()) {
try {
startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
} catch (ActivityNotFoundException e) {
Toast.makeText(this, R.string.no_browser_installed, Toast.LENGTH_LONG).show();
}
IntentUtils.showInBrowser(this, url);
} else {
// this should normally not happen
Toast.makeText(this, "ErrProviderWithoutUrl", Toast.LENGTH_LONG).show();
@@ -58,6 +58,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
{
private static final String TAG = ShareActivity.class.getSimpleName();
public static final String EXTRA_ACC_ID = "acc_id";
public static final String EXTRA_CHAT_ID = "chat_id";
public static final String EXTRA_MSG_TYPE = "msg_type";
public static final String EXTRA_MSG_SUBJECT = "msg_subject";
@@ -213,14 +214,10 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
}
private void handleResolvedMedia(Intent intent) {
int accId = intent.getIntExtra(EXTRA_ACC_ID, -1);
int chatId = intent.getIntExtra(EXTRA_CHAT_ID, -1);
String msgType = intent.getStringExtra(EXTRA_MSG_TYPE);
String shortcutId = intent.getStringExtra(ShortcutManagerCompat.EXTRA_SHORTCUT_ID);
if (chatId == -1 && shortcutId != null) {
chatId = Integer.parseInt(shortcutId);
}
String[] extraEmail = getIntent().getStringArrayExtra(Intent.EXTRA_EMAIL);
/*
usually, external app will try to start "e-mail sharing" intent, providing it:
@@ -259,28 +256,21 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
}
*/
String addr = null;
if(chatId == -1 && extraEmail != null && extraEmail.length > 0) {
addr = extraEmail[0];
final String addr = extraEmail[0];
int contactId = dcContext.lookupContactIdByAddr(addr);
if(contactId != 0 || !dcContext.isChatmail()) {
if(contactId == 0) {
contactId = dcContext.createContact(null, addr);
}
chatId = dcContext.createChatByContactId(contactId);
addr = null;
if(contactId == 0) {
contactId = dcContext.createContact(null, addr);
}
chatId = dcContext.createChatByContactId(contactId);
}
Intent composeIntent;
if (addr != null) {
composeIntent = new Intent(this, ConversationListActivity.class);
composeIntent.putExtra(ConversationListActivity.WARN_CANNOT_ENCRYPT, addr);
startActivity(composeIntent);
} else if (chatId != -1) {
if (accId != -1 && chatId != -1) {
composeIntent = getBaseShareIntent(ConversationActivity.class);
composeIntent.putExtra(ConversationActivity.CHAT_ID_EXTRA, chatId);
composeIntent.putExtra(ConversationActivity.ACCOUNT_ID_EXTRA, accId);
RelayUtil.setSharedType(composeIntent, msgType);
RelayUtil.setSharedUris(composeIntent, resolvedExtras);
startActivity(composeIntent);
@@ -26,6 +26,7 @@ import androidx.webkit.ProxyController;
import androidx.webkit.ProxyConfig;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.IntentUtils;
public class WebViewActivity extends PassphraseRequiredActionBarActivity
implements SearchView.OnQueryTextListener,
@@ -278,16 +279,8 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
// onBackPressed() can be overwritten by derived classes as needed.
// the default behavior (close the activity) is just fine eg. for Webxdc, Connectivity, HTML-mails
public static void openUrlInBrowser(Context context, String url) {
try {
context.startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse(url)));
} catch (ActivityNotFoundException e) {
Toast.makeText(context, R.string.no_browser_installed, Toast.LENGTH_LONG).show();
}
}
protected boolean openOnlineUrl(String url) {
openUrlInBrowser(this, url);
IntentUtils.showInBrowser(this, url);
// returning `true` causes the WebView to abort loading
return true;
}
@@ -9,7 +9,6 @@ import android.graphics.Bitmap;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;
import android.util.Base64;
@@ -46,6 +45,7 @@ import org.json.JSONObject;
import org.thoughtcrime.securesms.connect.AccountManager;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.JsonUtils;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Prefs;
@@ -68,6 +68,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
private static final String EXTRA_HIDE_ACTION_BAR = "hideActionBar";
private static final String EXTRA_HREF = "href";
private static final int REQUEST_CODE_FILE_PICKER = 51426;
private static long lastOpenTime = 0;
private ValueCallback<Uri[]> filePathCallback;
private DcContext dcContext;
@@ -75,13 +76,23 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
private DcMsg dcAppMsg;
private String baseURL;
private String sourceCodeUrl = "";
private String selfAddr = "";
private String selfAddr;
private int sendUpdateMaxSize;
private int sendUpdateInterval;
private boolean internetAccess = false;
private boolean hideActionBar = false;
public static void openMaps(Context context, int chatId) {
openMaps(context, chatId, "");
}
public static void openMaps(Context context, int chatId, String href) {
DcContext dcContext = DcHelper.getContext(context);
int msgId = dcContext.initWebxdcIntegration(chatId);
int msgId = 0;
final int mapsVersion = 2;
if (dcContext.getConfigInt("ui.maps_version") >= mapsVersion) {
msgId = dcContext.initWebxdcIntegration(chatId);
}
if (msgId == 0) {
try {
InputStream inputStream = context.getResources().getAssets().open("webxdc/maps.xdc");
@@ -96,8 +107,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
Toast.makeText(context, "Cannot get maps.xdc, see log for details.", Toast.LENGTH_LONG).show();
return;
}
dcContext.setConfigInt("ui.maps_version", mapsVersion);
}
openWebxdcActivity(context, msgId, true, "");
openWebxdcActivity(context, msgId, true, href);
}
public static void openWebxdcActivity(Context context, DcMsg instance) {
@@ -203,7 +215,9 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
// this is needed here because if the app is opened while already in landscape mode, onConfigurationChanged() is not triggered
setScreenMode(getResources().getConfiguration());
}
selfAddr = JsonUtils.optString(info, "self_addr");
selfAddr = info.optString("self_addr");
sendUpdateMaxSize = info.optInt("send_update_max_size");
sendUpdateInterval = info.optInt("send_update_interval");
toggleFakeProxy(!internetAccess);
@@ -257,6 +271,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
@Override
protected void onDestroy() {
lastOpenTime = System.currentTimeMillis();
DcHelper.getEventCenter(this.getApplicationContext()).removeObservers(this);
leaveRealtimeChannel();
super.onDestroy();
@@ -279,7 +294,7 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
addToHomeScreen(this, dcAppMsg.getId());
return true;
case R.id.source_code:
openUrlInBrowser(this, sourceCodeUrl);
IntentUtils.showInBrowser(this, sourceCodeUrl);
return true;
case R.id.show_in_chat:
showInChat();
@@ -509,6 +524,16 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
return dcContext.isCommunity();
}
@JavascriptInterface
public int sendUpdateMaxSize() {
return WebxdcActivity.this.sendUpdateMaxSize;
}
@JavascriptInterface
public int sendUpdateInterval() {
return WebxdcActivity.this.sendUpdateInterval;
}
@JavascriptInterface
public String selfAddr() {
if (dcContext.isCommunity() && !TextUtils.isEmpty(dcContext.getCommunityUser())) {
@@ -23,8 +23,10 @@ import com.b44t.messenger.rpc.RpcException;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
@@ -53,19 +55,21 @@ public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
public boolean shouldOverrideUrlLoading(WebView view, String url) {
String ext = MediaUtil.getFileExtensionFromUrl(Uri.parse(url).getPath());
if ("xdc".equals(ext)) {
try {
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
Uri uri = PersistentBlobProvider.getInstance().create(WebxdcStoreActivity.this, httpResponse.getBlob(), "application/octet-stream", "app.xdc");
Intent intent = new Intent();
intent.setData(uri);
setResult(Activity.RESULT_OK, intent);
finish();
} catch (RpcException e) {
e.printStackTrace();
Toast.makeText(WebxdcStoreActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show();
}
Util.runOnAnyBackgroundThread(() -> {
try {
HttpResponse httpResponse = rpc.getHttpResponse(dcContext.getAccountId(), url);
Uri uri = PersistentBlobProvider.getInstance().create(WebxdcStoreActivity.this, httpResponse.getBlob(), "application/octet-stream", "app.xdc");
Intent intent = new Intent();
intent.setData(uri);
setResult(Activity.RESULT_OK, intent);
finish();
} catch (RpcException e) {
e.printStackTrace();
Util.runOnMain(() -> Toast.makeText(WebxdcStoreActivity.this, "Error: " + e.getMessage(), Toast.LENGTH_LONG).show());
}
});
} else {
WebViewActivity.openUrlInBrowser(WebxdcStoreActivity.this, url);
IntentUtils.showInBrowser(WebxdcStoreActivity.this, url);
}
return true;
}
@@ -93,7 +93,7 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
boolean canGoBack = AccountManager.getInstance().canRollbackAccountCreation(this);
supportActionBar.setDisplayHomeAsUpEnabled(canGoBack);
getSupportActionBar().setTitle(canGoBack? R.string.add_account : R.string.welcome_desktop);
getSupportActionBar().setTitle(canGoBack? R.string.add_account : R.string.app_name);
}
private void registerForEvents() {
@@ -48,7 +48,7 @@ public class AudioRecorder {
ParcelFileDescriptor fds[] = ParcelFileDescriptor.createPipe();
captureUri = blobProvider.create(context, new ParcelFileDescriptor.AutoCloseInputStream(fds[0]),
MediaUtil.AUDIO_AAC, null, null);
MediaUtil.AUDIO_AAC, "voice.aac", null);
audioCodec = new AudioCodec(context);
audioCodec.start(new ParcelFileDescriptor.AutoCloseOutputStream(fds[1]));
@@ -87,11 +87,14 @@ public class AudioSlidePlayer {
public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
if (playbackState == Player.STATE_READY) {
Util.runOnMain(() -> {
Log.d(TAG, "request duration " + durationCalculator.getDuration());
getListener().onReceivedDuration(Long.valueOf(durationCalculator.getDuration()).intValue());
durationCalculator.release();
durationCalculator.removeListener(this);
durationCalculator = null;
synchronized (AudioSlidePlayer.this) {
if (durationCalculator == null) return;
Log.d(TAG, "request duration " + durationCalculator.getDuration());
getListener().onReceivedDuration(Long.valueOf(durationCalculator.getDuration()).intValue());
durationCalculator.release();
durationCalculator.removeListener(this);
durationCalculator = null;
}
});
}
}
@@ -3,10 +3,8 @@ package org.thoughtcrime.securesms.components;
import android.content.Context;
import android.net.Uri;
import android.os.Build;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import android.util.AttributeSet;
import android.view.View;
import android.view.Window;
@@ -55,6 +53,7 @@ public class MediaView extends FrameLayout {
public void set(@NonNull GlideRequests glideRequests,
@NonNull Window window,
@NonNull Uri source,
@Nullable String fileName,
@NonNull String mediaType,
long size,
boolean autoplay)
@@ -68,7 +67,7 @@ public class MediaView extends FrameLayout {
imageView.setVisibility(View.GONE);
videoView.get().setVisibility(View.VISIBLE);
videoView.get().setWindow(window);
videoView.get().setVideoSource(new VideoSlide(getContext(), source, size), autoplay);
videoView.get().setVideoSource(new VideoSlide(getContext(), source, fileName, size), autoplay);
} else {
throw new IOException("Unsupported media type: " + mediaType);
}
@@ -29,7 +29,12 @@ public class AttachmentsContentProvider extends ContentProvider {
public ParcelFileDescriptor openFile(Uri uri, String mode) throws FileNotFoundException {
DcContext dcContext = DcHelper.getContext(getContext());
String path = uri.getPath();
// `uri` originally comes from DcHelper.openForViewOrShare() and
// looks like `content://chat.delta.attachments/ef39a39/text.txt`
// where ef39a39 is the file in the blob directory
// and text.txt is the original name of the file, as returned by `msg.getFilename()`.
// `uri.getPathSegments()` returns ["ef39a39", "text.txt"] in this example.
String path = uri.getPathSegments().get(0);
if (!DcHelper.sharedFiles.containsKey(path)) {
throw new FileNotFoundException("File was not shared before.");
}
@@ -284,6 +284,7 @@ public class DcHelper {
DcMsg msg = dcContext.getMsg(msg_id);
String path = msg.getFile();
String filename = msg.getFilename();
String mimeType = msg.getFilemime();
try {
File file = new File(path);
@@ -294,8 +295,11 @@ public class DcHelper {
Uri uri;
if (path.startsWith(dcContext.getBlobdir())) {
uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(file.getName()));
sharedFiles.put("/" + file.getName(), 1); // as different Android version handle uris in putExtra differently, we also check them on our own
// Build a Uri that will later be passed to AttachmentsContentProvider.openFile().
// The last part needs to be `filename`, i.e. the original, user-visible name of the file,
// so that the external apps show the name of the file correctly.
uri = Uri.parse("content://" + BuildConfig.APPLICATION_ID + ".attachments/" + Uri.encode(file.getName()) + "/" + Uri.encode(filename));
sharedFiles.put(file.getName(), 1); // as different Android version handle uris in putExtra differently, we also check them on our own
} else {
if (Build.VERSION.SDK_INT >= 24) {
uri = FileProvider.getUriForFile(activity, BuildConfig.APPLICATION_ID + ".fileprovider", file);
@@ -305,7 +309,7 @@ public class DcHelper {
}
if (cmd.equals(Intent.ACTION_VIEW)) {
mimeType = checkMime(path, mimeType);
mimeType = checkMime(filename, mimeType);
Intent intent = new Intent(Intent.ACTION_VIEW);
intent.setDataAndType(uri, mimeType);
intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
@@ -377,6 +381,13 @@ public class DcHelper {
return mimeType;
}
/**
* Return the path of a not-yet-existing file in the blobdir with roughly the given filename
* and the given extension.
* In many cases, since we're using setFileAndDeduplicate now, this wouldn't be necessary anymore
* and we could just create a file with a random filename,
* but there are a few usages that still need the current behavior (like `openMaps()`).
*/
public static String getBlobdirFile(DcContext dcContext, String filename, String ext) {
filename = FileUtils.sanitizeFilename(filename);
ext = FileUtils.sanitizeFilename(ext);
@@ -494,16 +505,6 @@ public class DcHelper {
.show();
}
public static void showEncryptionRequiredDialog(Context context, String addr) {
new AlertDialog.Builder(context)
.setMessage(context.getString(R.string.encryption_required_for_new_contact, addr))
.setNeutralButton(R.string.learn_more, (d, w) -> openHelp(context, "#howtoe2ee"))
.setNegativeButton(R.string.qrscan_title, (d, w) -> context.startActivity(new Intent(context, QrActivity.class)))
.setPositiveButton(R.string.ok, null)
.setCancelable(true)
.show();
}
public static void openWebxdc(Context context, DcMsg dcMsg) {
JSONObject info = dcMsg.getWebxdcInfo();
if (JsonUtils.optBoolean(info, "community")) {
@@ -125,6 +125,7 @@ public class DirectShareUtil {
Intent intent = new Intent(context, ShareActivity.class);
intent.setAction(Intent.ACTION_SEND);
intent.putExtra(ShareActivity.EXTRA_ACC_ID, dcContext.getAccountId());
intent.putExtra(ShareActivity.EXTRA_CHAT_ID, chat.getId());
Recipient recipient = new Recipient(context, chat);
@@ -16,6 +16,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.AvatarView;
import org.thoughtcrime.securesms.contacts.avatars.ResourceContactPhoto;
import org.thoughtcrime.securesms.mms.GlideRequests;
import org.thoughtcrime.securesms.util.DateUtils;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.recipients.RecipientModifiedListener;
import org.thoughtcrime.securesms.util.ThemeUtil;
@@ -109,6 +110,19 @@ public class ContactSelectionListItem extends LinearLayout implements RecipientM
this.nameView.setEnabled(true);
this.nameView.setText(name==null? "#" : name);
if (contact != null) {
if (contact.isBot()) {
number = getContext().getString(R.string.bot);
} else if (contact.wasSeenRecently()) {
number = getContext().getString(R.string.online);
} else {
long timestamp = contact.getLastSeen();
if (timestamp != 0) {
number = getContext().getString(R.string.last_seen_at, DateUtils.getExtendedTimeSpanString(getContext(), timestamp));
}
}
}
if(number!=null) {
this.numberView.setText(number == null ? "" : number);
this.labelView.setText(label==null? "" : label);
@@ -23,7 +23,6 @@ import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.PorterDuff;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Build;
@@ -67,7 +66,6 @@ import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.providers.PersistentBlobProvider;
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.ThemeUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.guava.Optional;
import org.thoughtcrime.securesms.util.views.Stub;
@@ -125,11 +123,6 @@ public class AttachmentManager {
removableMediaView.setRemoveClickListener(new RemoveButtonListener());
removableMediaView.setEditClickListener(new EditButtonListener());
thumbnail.setOnClickListener(new ThumbnailClickListener());
int incomingBubbleColor = ThemeUtil.getThemedColor(context, R.attr.conversation_item_incoming_bubble_color);
audioView.getBackground().setColorFilter(incomingBubbleColor, PorterDuff.Mode.MULTIPLY);
documentView.getBackground().setColorFilter(incomingBubbleColor, PorterDuff.Mode.MULTIPLY);
webxdcView.getBackground().setColorFilter(incomingBubbleColor, PorterDuff.Mode.MULTIPLY);
vcardView.getBackground().setColorFilter(incomingBubbleColor, PorterDuff.Mode.MULTIPLY);
}
}
@@ -261,11 +254,11 @@ public class AttachmentManager {
return new DocumentSlide(context, msg);
}
else if (PartAuthority.isLocalUri(uri)) {
return getManuallyCalculatedSlideInfo(uri, width, height);
return getManuallyCalculatedSlideInfo(uri, width, height, msg);
} else {
Slide result = getContentResolverSlideInfo(uri, width, height, chatId);
if (result == null) return getManuallyCalculatedSlideInfo(uri, width, height);
if (result == null) return getManuallyCalculatedSlideInfo(uri, width, height, msg);
else return result;
}
} catch (IOException e) {
@@ -366,16 +359,21 @@ public class AttachmentManager {
return null;
}
private @NonNull Slide getManuallyCalculatedSlideInfo(Uri uri, int width, int height) throws IOException {
private @NonNull Slide getManuallyCalculatedSlideInfo(Uri uri, int width, int height, @Nullable DcMsg msg) throws IOException {
long start = System.currentTimeMillis();
Long mediaSize = null;
String fileName = null;
String mimeType = null;
if (msg != null) {
fileName = msg.getFilename();
mimeType = msg.getFilemime();
}
if (PartAuthority.isLocalUri(uri)) {
mediaSize = PartAuthority.getAttachmentSize(context, uri);
fileName = PartAuthority.getAttachmentFileName(context, uri);
mimeType = PartAuthority.getAttachmentContentType(context, uri);
if (fileName == null) fileName = PartAuthority.getAttachmentFileName(context, uri);
if (mimeType == null) mimeType = PartAuthority.getAttachmentContentType(context, uri);
}
if (mediaSize == null) {
@@ -680,10 +678,10 @@ public class AttachmentManager {
}
switch (this) {
case IMAGE: return new ImageSlide(context, uri, dataSize, width, height);
case GIF: return new GifSlide(context, uri, dataSize, width, height);
case IMAGE: return new ImageSlide(context, uri, fileName, dataSize, width, height);
case GIF: return new GifSlide(context, uri, fileName, dataSize, width, height);
case AUDIO: return new AudioSlide(context, uri, dataSize, false, fileName);
case VIDEO: return new VideoSlide(context, uri, dataSize);
case VIDEO: return new VideoSlide(context, uri, fileName, dataSize);
case DOCUMENT:
// We have to special-case Webxdc slides: The user can interact with them as soon as a draft
// is set. Therefore we need to create a DcMsg already now.
@@ -692,7 +690,7 @@ public class AttachmentManager {
DcMsg msg = new DcMsg(dcContext, DcMsg.DC_MSG_WEBXDC);
Attachment attachment = new UriAttachment(uri, null, MediaUtil.WEBXDC, AttachmentDatabase.TRANSFER_PROGRESS_STARTED, 0, 0, 0, fileName, null, false);
String path = attachment.getRealPath(context);
msg.setFile(path, MediaUtil.WEBXDC);
msg.setFileAndDeduplicate(path, fileName, MediaUtil.WEBXDC);
dcContext.setDraft(chatId, msg);
return new DocumentSlide(context, msg);
}
@@ -14,8 +14,8 @@ public class GifSlide extends ImageSlide {
super(context, dcMsg);
}
public GifSlide(Context context, Uri uri, long size, int width, int height) {
super(context, constructAttachmentFromUri(context, uri, MediaUtil.IMAGE_GIF, size, width, height, uri, null, false));
public GifSlide(Context context, Uri uri, String fileName, long size, int width, int height) {
super(context, constructAttachmentFromUri(context, uri, MediaUtil.IMAGE_GIF, size, width, height, uri, fileName, false));
}
@Override
@@ -39,8 +39,8 @@ public class ImageSlide extends Slide {
super(context, attachment);
}
public ImageSlide(Context context, Uri uri, long size, int width, int height) {
super(context, constructAttachmentFromUri(context, uri, MediaUtil.IMAGE_JPEG, size, width, height, uri, null, false));
public ImageSlide(Context context, Uri uri, String fileName, long size, int width, int height) {
super(context, constructAttachmentFromUri(context, uri, MediaUtil.IMAGE_JPEG, size, width, height, uri, fileName, false));
}
@Override
@@ -15,8 +15,6 @@ import com.bumptech.glide.Registry;
import com.bumptech.glide.annotation.GlideModule;
import com.bumptech.glide.load.model.UnitModelLoader;
import com.bumptech.glide.module.AppGlideModule;
import com.bumptech.glide.request.RequestOptions;
import com.github.penfeizhou.animation.glide.AnimationDecoderOption;
import com.caverock.androidsvg.SVG;
@@ -42,7 +40,6 @@ public class SignalGlideModule extends AppGlideModule {
@Override
public void applyOptions(Context context, GlideBuilder builder) {
builder.setLogLevel(Log.ERROR);
builder.setDefaultRequestOptions(new RequestOptions().set(AnimationDecoderOption.DISABLE_ANIMATION_APNG_DECODER, true));
// builder.setDiskCache(new NoopDiskCacheFactory());
}
@@ -30,16 +30,16 @@ import java.io.File;
public class VideoSlide extends Slide {
private static Attachment constructVideoAttachment(Context context, Uri uri, long dataSize)
private static Attachment constructVideoAttachment(Context context, Uri uri, String fileName, long dataSize)
{
Uri thumbnailUri = Uri.fromFile(new File(DcHelper.getBlobdirFile(DcHelper.getContext(context), "temp-preview.jpg")));
MediaUtil.ThumbnailSize retWh = new MediaUtil.ThumbnailSize(0, 0);
MediaUtil.createVideoThumbnailIfNeeded(context, uri, thumbnailUri, retWh);
return constructAttachmentFromUri(context, uri, MediaUtil.VIDEO_UNSPECIFIED, dataSize, retWh.width, retWh.height, thumbnailUri, null, false);
return constructAttachmentFromUri(context, uri, MediaUtil.VIDEO_UNSPECIFIED, dataSize, retWh.width, retWh.height, thumbnailUri, fileName, false);
}
public VideoSlide(Context context, Uri uri, long dataSize) {
super(context, constructVideoAttachment(context, uri, dataSize));
public VideoSlide(Context context, Uri uri, String fileName, long dataSize) {
super(context, constructVideoAttachment(context, uri, fileName, dataSize));
}
public VideoSlide(Context context, DcMsg dcMsg) {
@@ -12,7 +12,6 @@ import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import com.b44t.messenger.DcContext;
import com.soundcloud.android.crop.Crop;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
@@ -72,6 +72,9 @@ public class PersistentBlobProvider {
@Nullable String fileName)
{
final long id = System.currentTimeMillis();
if (fileName == null) {
fileName = "file." + MediaUtil.getExtensionFromMimeType(mimeType);
}
return create(context, new ByteArrayInputStream(blobBytes), id, mimeType, fileName, (long) blobBytes.length);
}
@@ -81,6 +84,9 @@ public class PersistentBlobProvider {
@Nullable String fileName,
@Nullable Long fileSize)
{
if (fileName == null) {
fileName = "file." + MediaUtil.getExtensionFromMimeType(mimeType);
}
return create(context, input, System.currentTimeMillis(), mimeType, fileName, fileSize);
}
@@ -99,7 +99,7 @@ public class QrCodeHandler {
showDoneToast(activity);
});
if (rawString.toLowerCase().startsWith("http")) {
builder.setNeutralButton(R.string.open, (d, b) -> IntentUtils.showBrowserIntent(activity, rawString));
builder.setNeutralButton(R.string.open, (d, b) -> IntentUtils.showInBrowser(activity, rawString));
}
builder.setNegativeButton(R.string.cancel, null);
builder.setCancelable(false);
@@ -182,7 +182,7 @@ public class QrCodeHandler {
final String url = qrParsed.getText1();
String msg = String.format(activity.getString(R.string.qrscan_contains_url), url);
builder.setMessage(msg);
builder.setPositiveButton(R.string.open, (dialog, which) -> IntentUtils.showBrowserIntent(activity, url));
builder.setPositiveButton(R.string.open, (dialog, which) -> IntentUtils.showInBrowser(activity, url));
builder.setNegativeButton(android.R.string.cancel, null);
builder.setNeutralButton(R.string.menu_copy_to_clipboard, (dialog, which) -> {
Util.writeTextToClipboard(activity, url);
@@ -16,6 +16,7 @@ import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcMsg;
import com.b44t.messenger.rpc.Reactions;
import com.b44t.messenger.rpc.Rpc;
import com.b44t.messenger.rpc.RpcException;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcHelper;
@@ -124,12 +125,14 @@ public class AddReactionView extends LinearLayout {
String result = null;
try {
final Reactions reactions = rpc.getMsgReactions(dcContext.getAccountId(), msgToReactTo.getId());
final Map<Integer, String[]> reactionsByContact = reactions.getReactionsByContact();
final String [] selfReactions = reactionsByContact.get(DcContact.DC_CONTACT_ID_SELF);
if (selfReactions != null && selfReactions.length > 0) {
result = selfReactions[0];
if (reactions != null) {
final Map<Integer, String[]> reactionsByContact = reactions.getReactionsByContact();
final String [] selfReactions = reactionsByContact.get(DcContact.DC_CONTACT_ID_SELF);
if (selfReactions != null && selfReactions.length > 0) {
result = selfReactions[0];
}
}
} catch(Exception e) {
} catch(RpcException e) {
e.printStackTrace();
}
return result;
@@ -16,6 +16,7 @@ import androidx.recyclerview.widget.RecyclerView;
import com.b44t.messenger.DcContact;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEvent;
import com.b44t.messenger.rpc.Reactions;
import com.b44t.messenger.rpc.RpcException;
import org.thoughtcrime.securesms.ProfileActivity;
@@ -85,17 +86,20 @@ public class ReactionsDetailsFragment extends DialogFragment implements DcEventC
int accId = DcHelper.getContext(requireActivity()).getAccountId();
try {
Map<Integer, String[]> reactionsByContact = DcHelper.getRpc(requireActivity()).getMsgReactions(accId, msgId).getReactionsByContact();
final Reactions reactions = DcHelper.getRpc(requireActivity()).getMsgReactions(accId, msgId);
ArrayList<Pair<Integer, String>> contactsReactions = new ArrayList<>();
String[] selfReactions = reactionsByContact.remove(DcContact.DC_CONTACT_ID_SELF);
for (Integer contact: reactionsByContact.keySet()) {
for (String reaction: reactionsByContact.get(contact)) {
contactsReactions.add(new Pair<>(contact, reaction));
if (reactions != null) {
Map<Integer, String[]> reactionsByContact = reactions.getReactionsByContact();
String[] selfReactions = reactionsByContact.remove(DcContact.DC_CONTACT_ID_SELF);
for (Integer contact: reactionsByContact.keySet()) {
for (String reaction: reactionsByContact.get(contact)) {
contactsReactions.add(new Pair<>(contact, reaction));
}
}
}
if (selfReactions != null) {
for (String reaction: selfReactions) {
contactsReactions.add(new Pair<>(DcContact.DC_CONTACT_ID_SELF, reaction));
if (selfReactions != null) {
for (String reaction: selfReactions) {
contactsReactions.add(new Pair<>(DcContact.DC_CONTACT_ID_SELF, reaction));
}
}
}
adapter.changeData(contactsReactions);
@@ -21,6 +21,8 @@ import org.thoughtcrime.securesms.util.Util;
public final class FetchForegroundService extends Service {
private static final String TAG = FcmReceiveService.class.getSimpleName();
private static final Object SERVICE_LOCK = new Object();
private static final Object STOP_NOTIFIER = new Object();
private static volatile boolean fetchingSynchronously = false;
private static Intent service;
public static void start(Context context) {
@@ -30,15 +32,44 @@ public final class FetchForegroundService extends Service {
}
GenericForegroundService.createFgNotificationChannel(context);
synchronized (SERVICE_LOCK) {
if (service == null) {
service = new Intent(context, FetchForegroundService.class);
ContextCompat.startForegroundService(context, service);
try {
synchronized (SERVICE_LOCK) {
if (service == null) {
service = new Intent(context, FetchForegroundService.class);
ContextCompat.startForegroundService(context, service);
}
}
} catch (Exception e) {
Log.w(TAG, "Failed to start foreground service: " + e + ", fetching in background.");
// According to the documentation https://firebase.google.com/docs/cloud-messaging/android/receive,
// we need to handle the message within 20s, and the time window may be even shorter than 20s,
// so, use 10s to be safe.
fetchingSynchronously = true;
if (ApplicationContext.dcAccounts.backgroundFetch(10)) {
// The background fetch was successful, but we need to wait until all events were processed.
// After all events were processed, we will get DC_EVENT_ACCOUNTS_BACKGROUND_FETCH_DONE,
// and stop() will be called.
synchronized (STOP_NOTIFIER) {
while (fetchingSynchronously) {
try {
// The `wait()` needs to be enclosed in a while loop because there may be
// "spurious wake-ups", i.e. `wait()` may return even though `notifyAll()` wasn't called.
STOP_NOTIFIER.wait();
} catch (InterruptedException ex) {}
}
}
}
}
}
public static void stop(Context context) {
if (fetchingSynchronously) {
fetchingSynchronously = false;
synchronized (STOP_NOTIFIER) {
STOP_NOTIFIER.notifyAll();
}
}
synchronized (SERVICE_LOCK) {
if (service != null) {
context.stopService(service);
@@ -2,14 +2,18 @@ package org.thoughtcrime.securesms.util;
import android.app.PendingIntent;
import android.content.ActivityNotFoundException;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ResolveInfo;
import android.net.Uri;
import android.os.Build;
import android.widget.Toast;
import androidx.annotation.NonNull;
import org.thoughtcrime.securesms.R;
import java.util.List;
public class IntentUtils {
@@ -19,9 +23,13 @@ public class IntentUtils {
return resolveInfoList != null && resolveInfoList.size() > 1;
}
public static void showBrowserIntent(Context context, String url) {
public static void showInBrowser(Context context, String url) {
Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
context.startActivity(browserIntent);
try {
context.startActivity(browserIntent);
} catch (ActivityNotFoundException e) {
Toast.makeText(context, R.string.no_browser_installed, Toast.LENGTH_LONG).show();
}
}
public static int FLAG_MUTABLE() {
@@ -58,18 +58,14 @@ public class LongClickCopySpan extends ClickableSpan {
String addr = prepareUrl(url);
Activity activity = (Activity) widget.getContext();
DcContext dcContext = DcHelper.getContext(activity);
int contactId = dcContext.lookupContactIdByAddr(addr);
DcContact contact = (contactId != 0)? dcContext.getContact(contactId) : null;
if (contact != null && !contact.isBlocked() && dcContext.getChatIdByContactId(contactId) != 0) {
DcContact contact = dcContext.getContact(dcContext.createContact(null, addr));
if (contact.getId() != 0 && !contact.isBlocked() && dcContext.getChatIdByContactId(contact.getId()) != 0) {
openChat(activity, contact);
} else if (contact == null && dcContext.isChatmail()) {
DcHelper.showEncryptionRequiredDialog(activity, addr);
} else {
String nameNAddr = contact != null ? contact.getNameNAddr() : addr;
new AlertDialog.Builder(activity)
.setMessage(activity.getString(R.string.ask_start_chat_with, nameNAddr))
.setMessage(activity.getString(R.string.ask_start_chat_with, contact.getNameNAddr()))
.setPositiveButton(android.R.string.ok, (dialog, which) -> {
openChat(activity, contact == null? dcContext.getContact(dcContext.createContact(null, addr)) : contact);
openChat(activity, contact);
})
.setNegativeButton(R.string.cancel, null)
.show();
@@ -87,7 +83,7 @@ public class LongClickCopySpan extends ClickableSpan {
QrCodeHandler qrCodeHandler = new QrCodeHandler(activity);
qrCodeHandler.handleQrData(url);
} else {
IntentUtils.showBrowserIntent(widget.getContext(), url);
IntentUtils.showInBrowser(widget.getContext(), url);
}
}
}
@@ -172,7 +172,7 @@ public class Prefs {
}
public static boolean isLocationStreamingEnabled(Context context) {
return true;
return false;
}
public static boolean isDeveloperModeEnabled(Context context) {
@@ -110,6 +110,7 @@ public class SendRelayedMessageUtil {
message = new DcMsg(dcContext, DcMsg.DC_MSG_TEXT);
} else if ("sticker".equals(type)) {
message = new DcMsg(dcContext, DcMsg.DC_MSG_STICKER);
message.forceSticker();
} else if ("image".equals(type) || MediaUtil.isImageType(mimeType)) {
message = new DcMsg(dcContext, DcMsg.DC_MSG_IMAGE);
} else if ("audio".equals(type) || MediaUtil.isAudioType(mimeType)) {
@@ -121,7 +122,7 @@ public class SendRelayedMessageUtil {
}
if (uri != null) {
message.setFile(getRealPathFromUri(context, uri), mimeType);
setFileFromUri(context, uri, message, mimeType);
}
if (html != null) {
message.setHtml(html);
@@ -135,11 +136,12 @@ public class SendRelayedMessageUtil {
return message;
}
private static String getRealPathFromUri(Context context, Uri uri) throws NullPointerException {
private static void setFileFromUri(Context context, Uri uri, DcMsg message, String mimeType) {
String path;
DcContext dcContext = DcHelper.getContext(context);
String filename = "cannot-resolve.jpg"; // best guess, this still leads to most images being workable if OS does weird things
try {
String filename = "cannot-resolve.jpg"; // best guess, this still leads to most images being workable if OS does weird things
if (PartAuthority.isLocalUri(uri)) {
filename = uri.getPathSegments().get(PersistentBlobProvider.FILENAME_PATH_SEGMENT);
} else if (uri.getScheme().equals("content")) {
@@ -157,14 +159,7 @@ public class SendRelayedMessageUtil {
}
}
String ext = "";
int i = filename.lastIndexOf(".");
if (i >= 0) {
ext = filename.substring(i);
filename = filename.substring(0, i);
}
String path = DcHelper.getBlobdirFile(dcContext, filename, ext);
path = DcHelper.getBlobdirFile(dcContext, filename, "temp");
// copy content to this file
if (path != null) {
@@ -172,12 +167,11 @@ public class SendRelayedMessageUtil {
OutputStream outputStream = new FileOutputStream(path);
Util.copy(inputStream, outputStream);
}
return path;
} catch (Exception e) {
e.printStackTrace();
return null;
path = null;
}
message.setFileAndDeduplicate(path, filename, mimeType);
}
private static String getHtml(Context context, Uri uri) {
@@ -23,6 +23,7 @@ import com.googlecode.mp4parser.util.Path;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
import java.io.File;
import java.nio.ByteBuffer;
@@ -551,11 +552,9 @@ public class VideoRecoder {
}
// prepareVideo() assumes the msg object is set up properly to being sent;
// the function fills out missing information and also recodes the video as needed;
// to get a responsive ui, DcChat.prepareMsg() may be called.
// the function fills out missing information and also recodes the video as needed.
// return: true=video might be prepared, can be sent, false=error
public static boolean prepareVideo(Context context, int chatId, DcMsg msg) {
try {
String inPath = msg.getFile();
Log.i(TAG, "Preparing video: " + inPath);
@@ -623,7 +622,6 @@ public class VideoRecoder {
msg.setDimension(vei.resultWidth, vei.resultHeight);
}
msg.setDuration((int) resultDurationMs);
DcHelper.getContext(context).prepareMsg(chatId, msg);
// calculate bytes
vei.estimatedBytes = VideoRecoder.calculateEstimatedSize((float) resultDurationMs / vei.originalDurationMs,
@@ -642,10 +640,7 @@ public class VideoRecoder {
return false;
}
if (!Util.moveFile(tempPath, inPath)) {
alert(context, String.format("Recoding failed for %s: cannot move temporary file %s", inPath, tempPath));
return false;
}
msg.setFileAndDeduplicate(tempPath, msg.getFilename(), msg.getFilemime());
Log.i(TAG, String.format("recoding for %s done", inPath));
}
@@ -35,7 +35,7 @@ public class VideochatUtil {
DcContext dcContext = DcHelper.getContext(activity);
DcMsg dcMsg = dcContext.getMsg(msgId);
String videochatUrl = dcMsg.getVideochatUrl();
IntentUtils.showBrowserIntent(activity, videochatUrl);
IntentUtils.showInBrowser(activity, videochatUrl);
}
}
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="2px"
android:bottom="2px">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#55888888" />
<corners
android:topLeftRadius="@dimen/message_corner_radius"
android:topRightRadius="@dimen/message_corner_radius"
android:bottomRightRadius="@dimen/message_corner_radius" />
<solid android:color="?attr/conversation_item_incoming_bubble_color" />
</shape>
</item>
</layer-list>
+10
View File
@@ -0,0 +1,10 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:angle="0"
android:startColor="@color/gray50"
android:endColor="@color/transparent"
android:type="linear" />
</shape>
+10
View File
@@ -0,0 +1,10 @@
<shape xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle" >
<gradient
android:angle="0"
android:startColor="@color/transparent"
android:endColor="@color/gray50"
android:type="linear" />
</shape>
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<layer-list
xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:top="2px"
android:bottom="2px">
<shape android:shape="rectangle">
<stroke android:width="1dp" android:color="#55888888" />
<corners
android:topLeftRadius="@dimen/message_corner_radius"
android:topRightRadius="@dimen/message_corner_radius"
android:bottomLeftRadius="@dimen/message_corner_radius" />
<solid android:color="?attr/conversation_item_incoming_bubble_color" />
</shape>
</item>
</layer-list>
@@ -0,0 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<org.thoughtcrime.securesms.components.emoji.MediaKeyboard
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/emoji_drawer"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:visibility="gone">
<androidx.emoji2.emojipicker.EmojiPickerView
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:id="@+id/emoji_picker"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?emoji_drawer_background"
app:emojiGridColumns="12"/>
</org.thoughtcrime.securesms.components.emoji.MediaKeyboard>
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:orientation="vertical"
android:layout_width="match_parent"
android:layout_height="wrap_content">
<androidx.emoji2.emojipicker.EmojiPickerView
android:id="@+id/emoji_picker"
android:layout_width="match_parent"
android:layout_height="match_parent"
app:emojiGridColumns="10"/>
</RelativeLayout>
@@ -51,12 +51,11 @@
<include layout="@layout/conversation_input_panel"/>
<ViewStub
android:id="@+id/emoji_drawer_stub"
<FrameLayout
android:id="@+id/emoji_picker_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:inflatedId="@+id/emoji_drawer"
android:layout="@layout/conversation_activity_emojidrawer_stub" />
/>
</LinearLayout>
</org.thoughtcrime.securesms.components.InputAwareLayout>
@@ -4,6 +4,7 @@
android:id="@+id/attachment_editor"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:background="?attr/input_panel_bg_color"
android:gravity="center_horizontal"
android:visibility="gone">
@@ -45,7 +46,7 @@
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:padding="8dp"
android:background="@drawable/message_bubble_background_sent_alone"/>
android:background="@drawable/message_bubble_background_sent_alone_with_border"/>
<org.thoughtcrime.securesms.components.DocumentView
android:id="@+id/attachment_document"
@@ -56,7 +57,7 @@
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:padding="8dp"
android:background="@drawable/message_bubble_background_sent_alone"/>
android:background="@drawable/message_bubble_background_sent_alone_with_border"/>
<org.thoughtcrime.securesms.components.WebxdcView
android:id="@+id/attachment_webxdc"
@@ -67,7 +68,7 @@
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:padding="8dp"
android:background="@drawable/message_bubble_background_sent_alone"/>
android:background="@drawable/message_bubble_background_sent_alone_with_border"/>
<org.thoughtcrime.securesms.components.VcardView
android:id="@+id/attachment_vcard"
@@ -78,7 +79,7 @@
android:layout_marginLeft="10dp"
android:layout_marginRight="10dp"
android:padding="8dp"
android:background="@drawable/message_bubble_background_sent_alone"/>
android:background="@drawable/message_bubble_background_sent_alone_with_border"/>
</org.thoughtcrime.securesms.components.RemovableEditableMediaView>
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- WARNING: on modifications also update the layout-land folder. -->
<org.thoughtcrime.securesms.components.emoji.MediaKeyboard
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/emoji_drawer"
@@ -68,6 +68,41 @@
android:layout_marginTop="20dp"
android:text="@string/instant_onboarding_create"/>
<LinearLayout
android:id="@+id/or_divider"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="30dp"
android:paddingBottom="30dp"
android:gravity="center"
android:orientation="horizontal">
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_weight="1"
android:background="@drawable/divider_start"/>
<TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_marginLeft="5dp"
android:layout_marginRight="5dp"
android:layout_weight="0"
android:gravity="center"
android:text="@string/or_separator"
android:textSize="14sp"
android:fontFamily="sans-serif"
android:textColor="@color/gray50"/>
<View
android:layout_width="wrap_content"
android:layout_height="1dp"
android:layout_weight="1"
android:background="@drawable/divider_end"/>
</LinearLayout>
<Button
style="@style/ButtonSecondary"
android:id="@+id/use_other_server"
@@ -75,7 +110,6 @@
android:layout_height="wrap_content"
android:paddingLeft="16dp"
android:paddingRight="16dp"
android:layout_marginTop="16dp"
android:text="@string/instant_onboarding_other_server"/>
<Button
+1
View File
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- WARNING: on modifications also update the layout-land folder. -->
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
+1
View File
@@ -20,6 +20,7 @@
android:layout_width="128dp"
android:layout_height="128dp"
android:scaleType="centerCrop"
app:strokeColor="@null"
app:shapeAppearanceOverlay="@style/ShapeAppearanceOverlay.App.CornerSize10Percent" />
<TextView android:id="@+id/webxdc_app_name"
+2 -2
View File
@@ -5,7 +5,7 @@
<item android:title="@string/menu_scroll_to_top"
android:id="@+id/log_scroll_up" />
<item android:title="@string/global_menu_help_learn_desktop"
<item android:title="@string/delta_chat_homepage"
android:id="@+id/learn_more"
app:showAsAction="never"/>
@@ -13,7 +13,7 @@
android:id="@+id/privacy_policy"
app:showAsAction="never"/>
<item android:title="@string/global_menu_help_contribute_desktop"
<item android:title="@string/contribute"
android:id="@+id/contribute"
app:showAsAction="never"/>
-2
View File
@@ -30,8 +30,6 @@
<group android:id="@+id/extra_services" >
<item android:title="@string/webxdc_apps_store"
android:id="@+id/menu_webxdc_apps_store" />
<item android:title="@string/public_bots"
android:id="@+id/menu_public_bots" />
+3
View File
@@ -46,6 +46,9 @@ window.webxdc = (() => {
deltalab: InternalJSApi.arcanechat(),
isCommunity: InternalJSApi.isCommunity(),
sendUpdateMaxSize: InternalJSApi.sendUpdateMaxSize(),
sendUpdateInterval: InternalJSApi.sendUpdateInterval(),
selfAddr: InternalJSApi.selfAddr(),
+2 -3
View File
@@ -4,7 +4,7 @@
<string name="app_name">Delta Chat</string>
<string name="ok">موافق</string>
<string name="cancel">إلغاء</string>
<string name="yes">نعم</string>
<string name="yes">نعم</string>
<string name="no">لا</string>
<string name="on">يعمل</string>
<string name="off">معطّل</string>
@@ -194,14 +194,13 @@
<string name="pref_app_access">دخول البرنامج</string>
<string name="pref_chats">المحادثات</string>
<string name="pref_in_chat_sounds">أصوات خلال الدردش</string>
<!-- deprecated -->
<string name="pref_message_text_size">حجم الخط في الرسائل</string>
<string name="pref_other">أخرى</string>
<!-- No need to translate "Wallpaper" literally. Chose what is common in your language for a "Wallpaper" or a "Background". Avoid adding the term "image" here, as the "Wallpaper" may also be just a single color. -->
<string name="pref_background">الخلفية</string>
<string name="pref_show_emails_all">كلها</string>
<string name="autocrypt_continue_transfer_retry">أعد المحاولة</string>
<string name="qrscan_fingerprint_label">البصمة</string>
<!-- notifications -->
<string name="notify_reply_button">رد</string>
<string name="notify_new_message">رسالة جديدة</string>
<string name="notify_priority_high">عالي</string>
+3 -3
View File
@@ -4,7 +4,7 @@
<string name="app_name">Delta Chat</string>
<string name="ok">OK</string>
<string name="cancel">Imtina</string>
<string name="yes">Bəli</string>
<string name="yes">Bəli</string>
<string name="no">Xeyir</string>
<string name="on">Açıq</string>
<string name="off">Bağlı</string>
@@ -332,8 +332,6 @@
<string name="pref_app_access">Daxil oldu</string>
<string name="pref_chats">Çatlar</string>
<string name="pref_in_chat_sounds">Çatda olan səslər</string>
<!-- deprecated -->
<string name="pref_message_text_size">Mətnin ölçüsü</string>
<string name="pref_view_log">Log-a bax</string>
<string name="pref_saved_log">Loqi Yükləmələr qovluğuna saxlanıldı</string>
<string name="pref_save_log_failed">Loqu saxlaya bilmədi</string>
@@ -428,6 +426,7 @@
<string name="contact_not_verified">%1$sDoğrula bilmir</string>
<!-- translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message" -->
<string name="contact_setup_changed">%1$süçün quraşdırma dəyişdirildi</string>
<!-- notifications -->
<string name="notify_reply_button">Cavab ver</string>
<string name="notify_new_message">Yeni mesaj</string>
<string name="notify_background_connection_enabled">Arxa fon əlaqəsi aktivdir</string>
@@ -460,6 +459,7 @@
<string name="global_menu_view_developer_desktop">İnkişaf etdirici</string>
<string name="global_menu_view_developer_tools_desktop">İnkişaf etdirici alətləri</string>
<string name="global_menu_help_desktop">Kömək</string>
<!-- deprecated, use contribute instead -->
<string name="global_menu_help_contribute_desktop">GitHub-da kömək et</string>
<string name="global_menu_help_report_desktop">Problemi bildirin</string>
<string name="no_chat_selected_suggestion_desktop">Bir çat seçin və ya yeni bir çat yaradın</string>
+3 -17
View File
@@ -4,8 +4,6 @@
<string name="app_name">Delta Chat</string>
<string name="ok">OK</string>
<string name="cancel">Отказ</string>
<!-- deprecated, the word "or" to separate blocks in the user interface that are mutually exclusive -->
<string name="or_separator">или</string>
<string name="clear_search">Изчистване на търсенето</string>
<string name="yes">Да</string>
<string name="no">Не</string>
@@ -478,6 +476,7 @@
<string name="tab_audio_empty_hint">Аудио файловете и гласовите съобщения, споделени в този чат, ще се появяват тук.</string>
<string name="tab_webxdc_empty_hint">Приложенията, споделени в този чат, ще се появяват тук.</string>
<string name="tab_all_media_empty_hint">Медийните файлове, споделени в кой да е чат, ще се появяват тук.</string>
<string name="all_apps_empty_hint">Приложенията, получени или изпратени в кой да е чат, ще се появяват тук.</string>
<string name="media_preview">Предварителен преглед на медия файл</string>
<!-- option to show images in the gallery with the correct width/height aspect (instead of square); other gallery apps may be a source of inspiration for translation :) -->
<string name="aspect_ratio_grid">Мрежа, запазваща съотношенията</string>
@@ -509,10 +508,6 @@
<string name="multidevice_transfer_done_devicemsg">ℹ️ Акаунтът е прехвърлен на второто Ви устройство.</string>
<!-- Shown beside progress bar, stay short -->
<string name="preparing_account">Акаунтът се подготвя...</string>
<!-- deprecated, shown beside progress bar, stay short -->
<string name="waiting_for_receiver">Изчаква се свързване от получателя...</string>
<!-- deprecated, shown beside progress bar, stay short -->
<string name="receiver_connected">Получателят е свързан...</string>
<!-- Shown beside progress bar, stay short -->
<string name="transferring">Прехвърляне...</string>
<string name="troubleshooting">Отстраняване на проблеми</string>
@@ -690,8 +685,6 @@
<string name="pref_app_access">Достъп до приложението</string>
<string name="pref_chats">Чатове</string>
<string name="pref_in_chat_sounds">Звуци в чата</string>
<!-- deprecated -->
<string name="pref_message_text_size">Размер на шрифта на съобщението</string>
<string name="pref_view_log">Разглеждане на дневника</string>
<string name="pref_saved_log">Дневникът е записан в папката \"Свалени\"</string>
<string name="pref_save_log_failed">Неуспешен запис на дневника</string>
@@ -974,8 +967,6 @@
<string name="mailto_link_could_not_be_decoded">Неуспешно декодиране на mailto връзка: %1$s</string>
<!-- notifications -->
<!-- deprecated, use mark_as_read or mark_as_read_short -->
<string name="notify_dismiss">Затваряне</string>
<string name="notify_reply_button">Отговор</string>
<string name="notify_new_message">Ново съобщение</string>
<string name="notify_background_connection_enabled">Връзката във фонов режим е разрешена</string>
@@ -1031,7 +1022,9 @@
<string name="global_menu_view_developer_desktop">Разработчик</string>
<string name="global_menu_view_developer_tools_desktop">Инструменти за разработчици</string>
<string name="global_menu_help_desktop">Помощ</string>
<!-- deprecated, use delta_chat_homepage instead -->
<string name="global_menu_help_learn_desktop">Научете повече за Delta Chat</string>
<!-- deprecated, use contribute instead -->
<string name="global_menu_help_contribute_desktop">Допринесете в GitHub</string>
<string name="global_menu_help_report_desktop">Съобщаване за проблем</string>
<string name="global_menu_help_about_desktop">Относно Delta Chat</string>
@@ -1104,11 +1097,6 @@
<string name="notifications_avg_minutes">Средно всеки %1$d минути</string>
<string name="notifications_avg_hours">Средно всеки %1$d часа</string>
<string name="last_check_at">Проверено на %1$s</string>
<!-- iOS webxdc selector -->
<string name="webxdc_selector_empty_hint">Приложенията, получени или изпратени в кой да е чат, ще се появяват тук. \"Файлове\" показва току-що свалените приложения.</string>
<!-- iOS webxdc shortcut page -->
<string name="shortcut_step1_tap_share_btn">Натиснете бутона \"Споделяне\"</string>
<string name="shortcut_step2_tap_add_to_home_screen">Изберете \"Добавяне към началния екран\", за да добавите приложението към началния екран. </string>
<!-- iOS permissions, copy from "deltachat-ios/Info.plist", which is used on missing translations in "deltachat-ios/LANG.lproj/InfoPlist.strings" -->
<string name="InfoPlist_NSCameraUsageDescription">Delta Chat използва Вашата камера, за да прави и изпраща снимки и видеоклипове, както и да сканира QR кодове.</string>
<string name="InfoPlist_NSContactsUsageDescription">Delta Chat използва Вашите контакти, за да показва списък на e-mail адресите, до които можете да пишете. Delta Chat няма собствен сървър, Вашите контакти не се пращат никъде.</string>
@@ -1117,8 +1105,6 @@
<string name="InfoPlist_NSMicrophoneUsageDescription">Delta Chat използва Вашия микрофон, за да записва и изпраща гласови съобщения и видеоклипове със звук.</string>
<string name="InfoPlist_NSPhotoLibraryUsageDescription">Delta Chat ще Ви даде да изберете кои снимки от Вашата библотека да изпратите.</string>
<string name="InfoPlist_NSPhotoLibraryAddUsageDescription">Delta Chat иска да запише изображения във Вашата библиотека със снимки.</string>
<string name="pref_background_notifications_rationale">За да се поддържа връзката към Вашия сървър за електронна поща и да получавате съобщения във фонов режим, игнорирайте оптимизациите на батерията на следващата стъпка.\n\nDelta Chat използва малко ресурси и се грижи да не изтощава Вашата батерия.</string>
<!-- disabling "Reliable service" will hide a the maybe annoying permanent-notification with the drawback that new-message-notifications get potentially unreliable -->
<string name="perm_enable_bg_reminder_title">Докоснете тук, за да получавате съобщения, докато Delta Chat е във фонов режим.</string>
+293 -296
View File
@@ -4,380 +4,377 @@
<string name="app_name">دلتا چت</string>
<string name="ok">خا</string>
<string name="cancel">رڌ</string>
<!-- deprecated, the word "or" to separate blocks in the user interface that are mutually exclusive -->
<string name="or_separator">یا</string>
<string name="clear_search">روفتن پیتینیڌن</string>
<string name="yes">هری</string>
<string name="no">na</string>
<string name="select">pêsand</string>
<string name="on">rušên</string>
<string name="off">kur</string>
<string name="def">pîš farz</string>
<string name="default_value">pîš farz (%1$s)</string>
<string name="default_value_as_above">pîš farz (jurê ro\')</string>
<string name="custom">sêfârêši</string>
<string name="none">hičkoyêki</string>
<string name="automatic">xotkār</string>
<string name="strict">saxtger</string>
<string name="open">gušiďên</string>
<string name="download">dānlod</string>
<string name="downloading">honêy dānlod êbu...</string>
<string name="open_attachment">gušiďên zamima</string>
<string name="join">avoďên</string>
<string name="rejoin">zênu avoďên</string>
<string name="delete">pāk kerdên</string>
<string name="info">zêbār</string>
<string name="update">vê ru kerdên</string>
<string name="emoji">êmuji</string>
<string name="attachment">zamima</string>
<string name="back">vorgaštên</string>
<string name="close">bastên</string>
<string name="no">ن</string>
<string name="select">پسند</string>
<string name="on">رۊشن</string>
<string name="off">کۊر</string>
<string name="def">پؽش فرز</string>
<string name="default_value">پؽش فرز (%1$s)</string>
<string name="default_value_as_above">پؽش فرز (جۊر روء)</string>
<string name="custom">سفارشی</string>
<string name="none">هیچکویکی</string>
<string name="automatic">خوتکار</string>
<string name="strict">سختگر</string>
<string name="open">گۊشیڌن</string>
<string name="download">دانلود</string>
<string name="downloading">هونی دانلود ابۊ...</string>
<string name="open_attachment">گۊشیڌن زمینه</string>
<string name="join">ٱووڌن</string>
<string name="rejoin">ز نۊ ٱووڌن</string>
<string name="delete">پاک کردن</string>
<string name="info">زبار</string>
<string name="update">ورۊ کردن</string>
<string name="emoji">ایموجی</string>
<string name="attachment">زمینه</string>
<string name="back">وورگشتن</string>
<string name="close">بستن</string>
<!-- "Resend" means "Sending the selected message(s) again to the same chat". The string is used in a menu and should be as short as possible. Resending may be needed after failures or to repost old messages to new members. -->
<string name="resend">zênu bêfêšn</string>
<string name="resend">ز نۊ بفشن</string>
<!-- Verb "to archive", as in "put a chat in the archive", not a noun "The Archive". -->
<string name="archive">bāyêguvi</string>
<string name="archive">بایگۊوی</string>
<!-- Verb "to unarchive", as in "remove a chat from the archive", opposite of the previous string -->
<string name="unarchive">bêdar zêyďên zê bāyêguvi</string>
<string name="mute">bî dong</string>
<string name="save">zaft</string>
<string name="chat">goftoloft</string>
<string name="media">vārasgar</string>
<string name="profile">porofāyl</string>
<string name="main_menu">balgê asli</string>
<string name="start_chat">nāhāďên pā goftoloft</string>
<string name="show_full_message">nêšow dāďên payomê kāmêl</string>
<string name="unarchive">و در زیڌن ز بایگۊوی</string>
<string name="mute">بؽ دونگ</string>
<string name="save">زفت کردن</string>
<string name="chat">گوفت ۉ لوفت</string>
<string name="media">وارسگر</string>
<string name="profile">پوروفایل</string>
<string name="main_menu">نومگه ٱسلی</string>
<string name="start_chat">ناڌن پا گوفت ۉ لوفت</string>
<string name="show_full_message">نشۉ داڌن پیوم کامل...</string>
<!-- Stay short here, say ~16 characters. The source string could also be "All Read", maybe that hint can make translations easier :) -->
<string name="mark_all_as_read">poy nê xonde biďe bêza</string>
<string name="mark_all_as_read">پوی ن خونده بیڌه بزݩ</string>
<!-- Shortest text for "Mark as being read". In english, this could be "Read" (past tense of "to read"), in german, this could be "Gelesen". -->
<string name="mark_as_read_short">xonde vâbiďa</string>
<string name="mark_as_read_short">علامت و عونوان خونده بیڌه</string>
<!-- Placeholder text when something is loading -->
<string name="loading">honêy bār êvane...</string>
<string name="hide">bîďār kerdên</string>
<string name="activate">faāl kerdên</string>
<string name="load_remote_content">bār vani šîvātā zê dar</string>
<string name="always">hamiša</string>
<string name="once">him ya kêrat</string>
<string name="show_warning">nêšow dāďên hošdār</string>
<string name="show_password">nêšow dāďên razm</string>
<string name="hide_password">bîďār kerdên razm</string>
<string name="not_now">sako na</string>
<string name="never">hič</string>
<string name="one_moment">yadamow...</string>
<string name="done">anjom vâbi</string>
<string name="offline">āflāyn</string>
<string name="loading">هونی بار اونه...</string>
<string name="hide">بؽڌار کردن</string>
<string name="activate">فعال کردن</string>
<string name="load_remote_content">بار ونی شؽواتا ز در</string>
<string name="always">همیشه</string>
<string name="once">هیم ی کرت</string>
<string name="show_warning">نشۉ داڌن هوشدار</string>
<string name="show_password">نشۉ داڌن رزم</string>
<string name="hide_password">بؽڌار کردن رزم</string>
<string name="not_now">سکو ن</string>
<string name="never">هیچ</string>
<string name="one_moment">ی دمۉ...</string>
<string name="done">ٱنجوم وابی</string>
<string name="offline">آفلاین</string>
<!-- For the next view or as "continue". Should be as short as possible. -->
<string name="next">niyâyi</string>
<string name="error">xatā</string>
<string name="error_x">xatā: %1$s</string>
<string name="file_not_found">%1$s najost</string>
<string name="copied_to_clipboard">mênê virga lefgiri vâbi.</string>
<string name="contacts_headline">homdangal</string>
<string name="email_address">nêšuvi imêyl</string>
<string name="password">razm</string>
<string name="existing_password">razmê mowjud</string>
<string name="now">sako</string>
<string name="next">نیایی</string>
<string name="error">ختا</string>
<string name="error_x">ختا: %1$s</string>
<string name="file_not_found">%1$s ن نجوست.</string>
<string name="copied_to_clipboard">من ویرگه لف گیری وابی.</string>
<string name="contacts_headline">هومدنگۉݩ</string>
<string name="email_address">نشۊوی ایمیل</string>
<string name="password">رزم</string>
<string name="existing_password">رزم مۉجۊڌ</string>
<string name="now">سکو</string>
<!-- Headline for destructive actions with no undo. Could also be "Caution" or "Warning". -->
<string name="danger">bêpā</string>
<string name="today">amru</string>
<string name="yesterday">duš</string>
<string name="this_week">i hafta</string>
<string name="this_month">i mā</string>
<string name="last_week">haftê zitari</string>
<string name="last_month">mā zitari</string>
<string name="danger">بپا</string>
<string name="today">ٱمرۊ</string>
<string name="yesterday">دۊش</string>
<string name="this_week">ای هفته</string>
<string name="this_month">ای ما</string>
<string name="last_week">هفته زیتری</string>
<string name="last_month">ما زیتری</string>
<!-- Refers to the time a contact was last seen. Shown below contact name in the profile. The placeholder will be replaced by date or time, resulting in "Last seen at 12:13 AM" or "Last seen Nov 12" -->
<string name="last_seen_at">ritorê dindâyi mênê %1$s</string>
<string name="last_seen_at">ریتور دیندایی من %1$s</string>
<!-- Refers to the time a contact was last seen. Shown below contact name in the profile. The placeholder will be replaced by a relative point in time as "3 minutes ago" (see https://momentjs.com for more examples and languages)-->
<string name="last_seen_relative">ritorê dindâyi %1$s</string>
<string name="last_seen_unknown">ritorê dindâyi: diyār nî</string>
<string name="last_seen_relative">ریتور دیندایی %1$s</string>
<string name="last_seen_unknown">ریتور دیندایی: دیار نؽ</string>
<!-- Shown beside messages that are "N minutes old". Prefer short strings, or well-known abbreviations. -->
<plurals name="n_minutes">
<item quantity="one">%d dîqa</item>
<item quantity="other">%d dîqa</item>
<item quantity="one">%d دؽقه</item>
<item quantity="other">%d دؽقه</item>
</plurals>
<!-- Shown beside messages that are "N hours old". Prefer short strings, or well-known abbreviations. -->
<plurals name="n_hours">
<item quantity="one">%d sāat</item>
<item quantity="other">%d sāat</item>
<item quantity="one">%d ساعت</item>
<item quantity="other">%d ساعت</item>
</plurals>
<plurals name="n_chats">
<item quantity="one">%d čat</item>
<item quantity="other">%d čat</item>
<item quantity="one">%d چت</item>
<item quantity="other">%d چت</item>
</plurals>
<plurals name="n_contacts">
<item quantity="one">%d homdang</item>
<item quantity="other">%d homdang</item>
<item quantity="one">%d هومدنگ</item>
<item quantity="other">%d هومدنگ</item>
</plurals>
<plurals name="n_messages">
<item quantity="one">%d payom</item>
<item quantity="other">%d payom</item>
<item quantity="one">%d پیوم</item>
<item quantity="other">%d پیوم</item>
</plurals>
<plurals name="n_members">
<item quantity="one">%d mėntor</item>
<item quantity="other">%d mėntor</item>
<item quantity="one">%d منتور</item>
<item quantity="other">%d منتور</item>
</plurals>
<!-- Short form for "N Items Selected" -->
<plurals name="n_selected">
<item quantity="one">%d tā pêsand vâbi</item>
<item quantity="other">%d tā pêsand vâbi</item>
<item quantity="one">%d تا پسند وابی</item>
<item quantity="other">%d تا پسند وابی</item>
</plurals>
<string name="self">mo</string>
<string name="draft">pîš hîl</string>
<string name="image">šîvāt</string>
<string name="self">مو</string>
<string name="draft">پؽش هؽل</string>
<string name="image">شؽوات</string>
<!-- Used in summaries as "Draft: Reply", similar as "Draft: Image". Use a noun here, not a verb (not: "to reply") -->
<string name="reply_noun">vêlom</string>
<string name="gif">gif</string>
<string name="reply_noun">ولوم</string>
<string name="gif">گیف</string>
<!-- "Stickers" as known from other messengers; in some languages, the English "Sticker" is fine. -->
<string name="sticker">êstikêr</string>
<string name="images">šîvātā</string>
<string name="audio">dong</string>
<string name="voice_message">payomê dong</string>
<string name="video">film</string>
<string name="documents">sanadā</string>
<string name="contact">homdang</string>
<string name="camera">šîvātgėr</string>
<string name="sticker">استیکر</string>
<string name="images">شؽواتا</string>
<string name="audio">دونگ</string>
<string name="voice_message">پیوم دونگ</string>
<string name="video">فیلم</string>
<string name="documents">سندا</string>
<string name="contact">هومدنگ</string>
<string name="camera">شؽواتگر</string>
<!-- As in "start a video recording" or "take a photo"; eg. the description of the "shutter button" in cameras -->
<string name="capture">gêrîďên</string>
<string name="switch_camera">ālêštê šîvātgêr</string>
<string name="toggle_fullscreen">ālêštê vaziyat poy balga</string>
<string name="location">jāga</string>
<string name="locations">jāgayal</string>
<string name="gallery">šîvātmāl</string>
<string name="images_and_videos">šîvātā vo filmā</string>
<string name="file">fāyl</string>
<string name="files">fāylā</string>
<string name="capture">گرؽڌن</string>
<string name="switch_camera">آلشت شؽواتگر</string>
<string name="toggle_fullscreen">آلشت وزیت پوی بلگه</string>
<string name="location">جاگه</string>
<string name="locations">جاگه یل</string>
<string name="gallery">شؽوات مال</string>
<string name="images_and_videos">شؽواتا وو فیلما</string>
<string name="file">فایل</string>
<string name="files">فایلا</string>
<!-- "App" is used to present "Webxdc App" (https://webxdc.org) in a user friendly way. Please stay close to the original term and keep it short (it is used in menus with few screen space). -->
<string name="webxdc_app">barnoma</string>
<string name="webxdc_app">برنومه</string>
<!-- plural of "App"; used to present "Webxdc App" (https://webxdc.org) in a user friendly way. Please stay close to the original term and keep it short (it is used in menus with few screen space). -->
<string name="webxdc_apps">barnomêyal</string>
<string name="unknown">nāšênās</string>
<string name="webxdc_apps">برنومه یل</string>
<string name="unknown">ناشناس</string>
<string name="green">sawz</string>
<string name="red">so\'r</string>
<string name="blue">kêvu</string>
<string name="purple">bênawš</string>
<string name="white">êsbîď</string>
<string name="green">سوز</string>
<string name="red">سوئر</string>
<string name="blue">کوۊ</string>
<string name="purple">بنوش</string>
<string name="white">اسبؽڌ</string>
<string name="zoom">gap kerdên</string>
<string name="extra_small">qalêvê kučir</string>
<string name="small">kučir</string>
<string name="normal">âdi</string>
<string name="large">gap</string>
<string name="extra_large">qalêvê gap</string>
<string name="zoom">گپ کردن</string>
<string name="extra_small">قلوه کۊچیر</string>
<string name="small">کۊچیر</string>
<string name="normal">عادی</string>
<string name="large">گپ</string>
<string name="extra_large">قلوه گپ</string>
<string name="fast">zêl</string>
<string name="slow">hovār</string>
<string name="fast">زل</string>
<string name="slow">هووار</string>
<!-- menu labels (or icon, buttons...) -->
<string name="menu_new_contact">homdangê nu</string>
<string name="menu_new_chat">goftoloftê nu</string>
<string name="menu_new_group">jarga nu</string>
<string name="menu_new_contact">هومدنگ نۊ</string>
<string name="menu_new_chat">گوفت ۉ لوفت نۊ</string>
<string name="menu_new_group">جرگه نۊ</string>
<!-- consider keeping the term "broadcast" as in WhatsApp or Telegram -->
<string name="broadcast_list">nomga Broadcast</string>
<string name="broadcast_lists">nomgayal Broadcast</string>
<string name="new_broadcast_list">nomga Broadcast nu</string>
<string name="menu_send">fêšnāďên</string>
<string name="menu_edit_group">ālêštê jarga</string>
<string name="menu_group_name_and_image">nom vo šîvātê jarga</string>
<string name="menu_archive_chat">bāyêguvi kerdên goftoloft</string>
<string name="menu_unarchive_chat">bêdar zêyďên goftoloft zê bāyêguvi</string>
<string name="menu_add_attachment">êzāf kerdên zamima</string>
<string name="menu_leave_group">ra\'ďên zê jarga</string>
<string name="menu_delete_chat">pāk kerdên poy goftoloft</string>
<string name="broadcast_list">نومگه Broadcast</string>
<string name="broadcast_lists">نومگه یل Broadcast</string>
<string name="new_broadcast_list">نومگه Broadcast نۊ</string>
<string name="menu_send">فشناڌن</string>
<string name="menu_edit_group">آلشت جرگه</string>
<string name="menu_group_name_and_image">نوم وو شؽوات جرگه</string>
<string name="menu_archive_chat">بایگۊوی گوفت ۉ لوفت</string>
<string name="menu_unarchive_chat">و در زیڌن گوفت ۉ لوفت ز بایگۊوی</string>
<string name="menu_add_attachment">ازاف کردن زمینه</string>
<string name="menu_leave_group">رئڌن ز جرگه</string>
<string name="menu_delete_chat">پاک کردن گوفت ۉ لوفت</string>
<!-- Command to delete all messages in a chat. The chat itself will not be deleted but will be empty afterwards, so make sure to be different from "Delete Chat" here. "Clear" is a verb here, "Empty Chat" would also be fine (eg. in German "Chat leeren") -->
<string name="clear_chat">roftênê virgārê goftoloft</string>
<string name="menu_delete_messages">pāk kerdên payomā</string>
<string name="delete_contact">pāk kerdên homdang</string>
<string name="menu_delete_location">i jāga pāk bu?</string>
<string name="menu_copy_to_clipboard">lefgiri mênê virga</string>
<string name="menu_copy_link_to_clipboard">lefgiri ling</string>
<string name="menu_copy_text_to_clipboard">lefgiri hîl</string>
<string name="menu_copy_image_to_clipboard">lefgiri šîvāt</string>
<string name="menu_copy_email_to_clipboard">lefgiri imêyl</string>
<string name="paste_from_clipboard">jā vandên zê virga</string>
<string name="menu_reply">vêlom bê payom</string>
<string name="menu_mute">bî dong kerdên vārasuviyā</string>
<string name="menu_unmute">vā dong kerdên</string>
<string name="menu_all_media">poy vārasgarā</string>
<string name="clear_chat">روفتن ویرگار گوفت ۉ لوفت</string>
<string name="menu_delete_messages">پاک کردن پیوما</string>
<string name="delete_contact">پاک کردن هومدنگ</string>
<string name="menu_delete_location">ای جاگه پاک بۊ؟</string>
<string name="menu_copy_to_clipboard">لف گیری من ویرگه</string>
<string name="menu_copy_link_to_clipboard">لف گیری لینک</string>
<string name="menu_copy_text_to_clipboard">لف گیری هؽل</string>
<string name="menu_copy_image_to_clipboard">لف گیری شؽوات</string>
<string name="menu_copy_email_to_clipboard">لف گیری ایمیل</string>
<string name="paste_from_clipboard">جا وندن ز ویرگه</string>
<string name="menu_reply">ولوم ب پیوم</string>
<string name="menu_mute">بؽ دونگ کردن وارسۊویا</string>
<string name="menu_unmute">وا دونگ کردن</string>
<string name="menu_all_media">پوی وارسگرا</string>
<!-- Command to jump to the original message corresponding to a gallery image or document -->
<string name="show_in_chat">nêšow dāďên mênê goftoloft</string>
<string name="menu_share">yakrasuvi</string>
<string name="accept">qêvul</string>
<string name="menu_play">pêšk</string>
<string name="menu_pause">vāstāďên</string>
<string name="menu_scroll_to_bottom">ra\'ďên bê lam</string>
<string name="menu_scroll_to_top">ra\'ďên bê ro\'</string>
<string name="menu_help">hayâri</string>
<string name="menu_select_all">pêsandê poy</string>
<string name="select_chat">pêsandê goftoloft</string>
<string name="select_more">pêsandê bištar</string>
<string name="menu_edit_name">ālêštê nom</string>
<string name="menu_settings">sāmovā</string>
<string name="menu_advanced">pîš ra\'ďa</string>
<string name="menu_view_profile">niyaštên porofāyl</string>
<string name="menu_zoom_in">gap kerdên</string>
<string name="menu_zoom_out">kučir kerdên</string>
<string name="menu_save_log">zaft kerdên gozārêš</string>
<string name="menu_more_options">guzinêyalê bištar</string>
<string name="jump_to_message">ra\'ďên bê payom</string>
<string name="device_talk">payomā dasgā</string>
<string name="device_talk_subtitle">payomā mêni</string>
<string name="edit_contact">ālêštê homdang</string>
<string name="show_in_chat">نشۉ داڌن من گوفت ۉ لوفت</string>
<string name="menu_share">یک رسۊوی</string>
<string name="accept">قوۊل</string>
<string name="menu_play">پشک</string>
<string name="menu_pause">واڌاشتن</string>
<string name="menu_scroll_to_bottom">رئڌن ب لم</string>
<string name="menu_scroll_to_top">رئڌن ب روء</string>
<string name="menu_help">هیاری</string>
<string name="menu_select_all">پسند پوی</string>
<string name="select_chat">پسند گوفت ۉ لوفت</string>
<string name="select_more">پسند بیشتر</string>
<string name="menu_edit_name">آلشت نوم</string>
<string name="menu_settings">سامووا</string>
<string name="menu_advanced">پؽش رئڌه</string>
<string name="menu_view_profile">نیشتن پوروفایل</string>
<string name="menu_zoom_in">گپ کردن</string>
<string name="menu_zoom_out">کۊچیر کردن</string>
<string name="menu_save_log">زفت کردن گوزارش</string>
<string name="menu_more_options">گۊزینیل بیشتر</string>
<string name="jump_to_message">رئڌن ب پیوم</string>
<string name="device_talk">پیوما دسگا</string>
<string name="device_talk_subtitle">پیوما منی</string>
<string name="edit_contact">آلشت هومدنگ</string>
<!-- Verb "to pin", making something sticky, not a noun or abbreviation for "pin number". -->
<string name="pin_chat">disniďên goftoloft</string>
<string name="pin_chat">دیسنیڌن گوفت ۉ لوفت</string>
<!-- Verb "to pin", making something sticky, not a noun or abbreviation for "pin number". -->
<string name="pin">disniďên</string>
<string name="source_code">kodê bončak</string>
<string name="mute_for_one_hour">bî dong kerdên si 1 sāat</string>
<string name="mute_for_two_hours">bî dong kerdên si 2 sāat</string>
<string name="mute_for_one_day">bî dong kerdên si 1 ru</string>
<string name="mute_for_seven_days">bî dong kerdên si 7 ru</string>
<string name="mute_forever">bî dong kerdên si hamiša</string>
<string name="pin">دیسنیڌن</string>
<string name="source_code">کود بونچک</string>
<string name="mute_for_one_hour">بؽ دونگ کردن سی 1 ساعت</string>
<string name="mute_for_two_hours">بؽ دونگ کردن سی 2 ساعت</string>
<string name="mute_for_one_day">بؽ دونگ کردن سی 1 رۊ</string>
<string name="mute_for_seven_days">بؽ دونگ کردن سی 7 رۊ</string>
<string name="mute_forever">بؽ دونگ کردن سی همیشه</string>
<string name="share_location_for_5_minutes">si 5 dîqa</string>
<string name="share_location_for_30_minutes">si 30 dîqa</string>
<string name="share_location_for_one_hour">si 1 sāat</string>
<string name="share_location_for_two_hours">si 2 sāat</string>
<string name="share_location_for_six_hours">si 6 sāat</string>
<string name="share_location_for_5_minutes">سی 5 دؽقه</string>
<string name="share_location_for_30_minutes">سی 30 دؽقه</string>
<string name="share_location_for_one_hour">سی 1 ساعت</string>
<string name="share_location_for_two_hours">سی 2 ساعت</string>
<string name="share_location_for_six_hours">سی 6 ساعت</string>
<string name="file_saved_to">fāyl mênê \"%1$s\" zaft vâbi.</string>
<string name="file_saved_to">فایل من «%1$s» زفت وابی.</string>
<string name="videochat">goftoloftê vidiyoyi</string>
<string name="videochat_invitation">mokêš bê goftoloft vidiyoyi</string>
<string name="videochat">گوفت ۉ لوفت ویدیویی</string>
<string name="videochat_invitation">موکش و گوفت ۉ لوفت ویدیویی</string>
<plurals name="ask_delete_messages_simple">
<item quantity="one">êxuy %d payom pāk bu?</item>
<item quantity="other">êxuy %d payom pāk bu?</item>
<item quantity="other">اخۊی %d پیوم پاک بۊ؟</item>
</plurals>
<string name="ask_start_chat_with">goftoloft vā %1$s?</string>
<string name="ask_delete_value">pāk kerdên %s?</string>
<string name="ask_start_chat_with">گوفت ۉ لوفت وا %1$s؟</string>
<string name="ask_delete_value">پاک کردن %s؟</string>
<!-- %1$s is replaced by a comma-separated list of names -->
<string name="ask_remove_members">pāk kerdên %1$s zê jarga?</string>
<string name="ask_remove_members">پاک کردن %1$s ز جرگه؟</string>
<!-- %1$s is replaced by a comma-separated list of names -->
<string name="ask_remove_from_broadcast">%1$s zê nomga Broadcast pāk bu?</string>
<string name="open_url_confirmation">êxuy i lingê nê buguši?</string>
<string name="ask_remove_from_broadcast">%1$s ز نومگه Broadcast پاک بۊ؟</string>
<string name="open_url_confirmation">اخۊی ای لینگن بۊگۊشی؟</string>
<!-- contact list -->
<string name="contacts_title">homdangal</string>
<string name="contacts_empty_hint">bî homdang.</string>
<string name="contacts_title">هومدنگۉݩ</string>
<string name="contacts_empty_hint">بؽ هومدنگ.</string>
<string name="chat_please_enter_message">ya payom bêza</string>
<string name="chat_please_enter_message">ی پیوم بزݩ.</string>
<plurals name="chat_n_new_messages">
<item quantity="one">%d payomê nu</item>
<item quantity="other">%d payomê nu</item>
<item quantity="one">%d پیوم نۊ</item>
<item quantity="other">%d پیوم نۊ</item>
</plurals>
<string name="chat_record_slide_to_cancel">si raď kerdên bêkašês</string>
<string name="chat_share_with_title">yakrasuvi vā</string>
<string name="chat_input_placeholder">payom</string>
<string name="chat_request_label">darxāst</string>
<string name="chat_no_messages">payomi nî.</string>
<string name="chat_self_talk_subtitle">payomāyî ke si xom fêšnāme.</string>
<string name="saved_messages">payomā zaft biďa</string>
<string name="chat_record_slide_to_cancel">سی رڌ کردن بکشس.</string>
<string name="chat_share_with_title">یک رسۊوی وا</string>
<string name="chat_input_placeholder">پیوم</string>
<string name="chat_request_label">درخاست</string>
<string name="chat_no_messages">پیومؽ نؽ.</string>
<string name="chat_self_talk_subtitle">پیومایی ک سی خوم فشنام.</string>
<string name="saved_messages">پیوما زفت بیڌه</string>
<!-- Should match "Saved" from "Saved messages" -->
<string name="saved">zaft vâbi</string>
<string name="save_as">zaft vê onvān</string>
<string name="retry_send">zênu si fêšnāďênê payom taqalā ko</string>
<string name="saved">زفت وابی</string>
<string name="save_as">زفت و عونوان</string>
<string name="retry_send">ز نۊ سی فشناڌن پیوم تقلا کوݩ</string>
<!-- mailing lists -->
<string name="mailing_list">nomga posti</string>
<string name="mailing_list">نومگه پوستی</string>
<!-- title shown above a list of chats where one should be selected (eg. when sharing files from a webxdc). the placeholder will be replaced by a file name -->
<string name="send_file_to">fêšnāďên \"%1$s\" ...</string>
<string name="send_file_to">فشناڌن \"%1$s\" و...</string>
<!-- title shown above a list contacts where one should be selected (eg. when a webxdc attempts to send a message to a chat) -->
<string name="send_message_to">fêšnāďên payom vê...</string>
<string name="show_location_traces">nêšow dāďên jā pā</string>
<string name="send_message_to">فشناڌن پیوم و...</string>
<string name="show_location_traces">نشۉ داڌن جا پا</string>
<!-- search -->
<string name="search">pitiniďên</string>
<string name="search">پیتینیڌن</string>
<!-- create/edit groups, contact/group profile -->
<string name="group_name">nomê jarga</string>
<string name="group_avatar">šîvātê jarga</string>
<string name="remove_group_image">pāk kerdên šîvātê jarga</string>
<string name="change_group_image">ālêštê šîvātê jarga</string>
<string name="group_create_button">vorkêlê jarga</string>
<string name="group_add_members">avordênê mêntor</string>
<string name="tab_contact">homdang</string>
<string name="tab_group">jarga</string>
<string name="tab_gallery">šîvātmāl</string>
<string name="tab_docs">sanadā</string>
<string name="tab_links">lingā</string>
<string name="tab_map">naqša</string>
<string name="media_preview">nêšow dāďên vārasgar</string>
<string name="send_message">fêšnāďên payom</string>
<string name="group_name">نوم جرگه</string>
<string name="group_avatar">شؽوات جرگه</string>
<string name="remove_group_image">پاک کردن شؽوات جرگه</string>
<string name="change_group_image">آلشت شؽوات جرگه</string>
<string name="group_create_button">وورکل جرگه</string>
<string name="group_add_members">ٱووردن منتور</string>
<string name="tab_contact">هومدنگ</string>
<string name="tab_group">جرگه</string>
<string name="tab_gallery">شؽوات مال</string>
<string name="tab_docs">سندا</string>
<string name="tab_links">لینگا</string>
<string name="tab_map">نقشه</string>
<string name="media_preview">نشۉ داڌن وارسگر</string>
<string name="send_message">فشناڌن پیوم</string>
<!-- Headline in the "Connectivity" view. Placeholder will be replaced by the domain of the configured email-address. -->
<string name="storage_on_domain">zaft kerdên mênê %1$s</string>
<string name="storage_on_domain">زفت کردن من %1$s</string>
<!-- Shown in the title bar if the app is "Connecting"; prefer short strings. The ellipsis is a single character (…), not three (...) -->
<string name="connectivity_connecting">honêy menpiz êbu...</string>
<string name="connectivity_connecting">هونی منپیز ابۊ...</string>
<!-- Shown in the title bar if the app is "Updating" (eg. getting new/old message, sync things); prefer short strings. The ellipsis is a single character (…), not three (...) -->
<string name="connectivity_updating">honêy vê ru êbu...</string>
<string name="connectivity_updating">هونی ورۊ ابۊ...</string>
<!-- Shown in the setting if the app is "Connected" -->
<string name="connectivity_connected">menpiz vâbi</string>
<string name="sending">honêy fêšnāďe êbu...</string>
<string name="connectivity_connected">منپیز وابی</string>
<string name="sending">هونی افشنه...</string>
<!-- Subtitle in quota context of "Connetivity" view. Should be be plural always, no number is prefixed. -->
<string name="messages">payomā</string>
<string name="sync_all">vê ru kerdên poy</string>
<string name="pref_your_name">nomê to</string>
<string name="pref_notifications_show">nêšow dāďên</string>
<string name="pref_language">zow</string>
<string name="pref_chats">goftoloftā</string>
<!-- deprecated -->
<string name="pref_message_text_size">hêndā hîlê payom</string>
<string name="pref_log_header">gozārêš</string>
<string name="pref_background_btn_gallery">pêsand zê šîvātmāl</string>
<string name="pref_show_emails_all">poy</string>
<string name="messages">پیوما</string>
<string name="sync_all">ورۊ کردن پوی</string>
<string name="pref_your_name">نوم ایسا</string>
<string name="pref_notifications_show">نشۉ داڌن</string>
<string name="pref_language">زۉݩ</string>
<string name="pref_chats">گوفت ۉ لوفتا</string>
<string name="pref_log_header">گوزارش</string>
<string name="pref_background_btn_gallery">پسند ز شؽوات مال</string>
<string name="pref_show_emails_all">پوی</string>
<!-- %1$s will be replaced by a human-readable number of bytes, eg. 32 KiB, 1 MiB -->
<string name="up_to_x">tā saqfe %1$s</string>
<string name="up_to_x">تا سقف %1$s</string>
<!-- %1$s will be replaced by a human-readable number of bytes, eg. 32 KiB, 1 MiB. Resulting string eg. "1 MiB message" -->
<string name="n_bytes_message">payom %1$s</string>
<string name="profile_image_select">pêsandê šîvātê porofāyl</string>
<string name="profile_image_delete">pāk kerdên šîvātê porofāyl</string>
<string name="pref_edit_profile">ālêštê porofāyl</string>
<string name="n_bytes_message">پیوم %1$s</string>
<string name="profile_image_select">پسند شؽوات پوروفایل</string>
<string name="profile_image_delete">پاک کردن شؽوات پوروفایل</string>
<string name="pref_edit_profile">آلشت پوروفایل</string>
<!-- Emoji picker and categories -->
<string name="emoji_search_results">natijêyalê pitiniďên</string>
<string name="emoji_symbols">nemāďā</string>
<string name="emoji_flags">bêyraqā</string>
<string name="emoji_search_results">نتیجیل پیتینیڌن</string>
<string name="emoji_symbols">نمادا</string>
<string name="emoji_flags">بیرقا</string>
<!-- automatically delete message -->
<string name="delete_old_messages">pāk kerdên payomā qaďimi</string>
<string name="autodel_device_title">pāk kerdên payomā zê dasgā</string>
<string name="autodel_server_title">pāk kerdên payomā zê sêrvêr</string>
<string name="delete_old_messages">پاک کردن پیوما قڌیمی</string>
<string name="autodel_device_title">پاک کردن پیوما ز دسگا</string>
<string name="autodel_server_title">پاک کردن پیوما ز سرور</string>
<!-- "At once" in the meaning of "Immediately", without any intervening time. -->
<string name="autodel_at_once">ya kêrat</string>
<string name="after_30_seconds">ba\'ďê 30 sâniya</string>
<string name="after_1_minute">ba\'ďê 1 dîqa</string>
<string name="after_5_minutes">ba\'ďê 5 dîqa</string>
<string name="after_30_minutes">ba\'ďê 30 dîqa</string>
<string name="autodel_after_1_hour">ba\'ďê 1 sāat</string>
<string name="autodel_after_1_day">ba\'ďê 1 ru</string>
<string name="autodel_after_1_week">ba\'ďê 1 hafta</string>
<string name="after_5_weeks">ba\'ďê 5 hafta</string>
<string name="autodel_after_1_year">ba\'ďê 1 sāl</string>
<string name="autodel_at_once">ی کرت دیندا دانلود</string>
<string name="after_30_seconds">دیندا 30 سانیه</string>
<string name="after_1_minute">دیندا 1 دؽقه</string>
<string name="after_5_minutes">دیندا 5 دؽقه</string>
<string name="after_30_minutes">دیندا 30 دؽقه</string>
<string name="autodel_after_1_hour">دیندا 1 ساعت</string>
<string name="autodel_after_1_day">دیندا 1 رۊ</string>
<string name="autodel_after_1_week">دیندا 1 هفته</string>
<string name="after_5_weeks">دیندا 5 هفته</string>
<string name="autodel_after_1_year">دیندا 1 سال</string>
<!-- "left" in the meaning of "exited"; %1$s will be replaced by name and address of the contact leaving the group -->
<string name="group_left_by_other">%1$s zê jarga ra\'ď.</string>
<string name="qrshow_x_joining">%1$s mêntor vâbi.</string>
<string name="qrshow_x_verified">%1$s taiď vâbi.</string>
<string name="contact_verified">%1$s taiď vâbi.</string>
<string name="group_left_by_other">%1$s ز جرگه رئڌ.</string>
<string name="qrshow_x_joining">%1$s ٱووڌ.</string>
<string name="qrshow_x_verified">%1$s تاییڌ وابی.</string>
<string name="contact_verified">%1$s تاییڌ وابی.</string>
<!-- Shown in contact profile. The placeholder will be replaced by the name of the contact that introduced the contact. -->
<string name="verified_by">taiď vâbiďa vê das %1$s</string>
<string name="notify_reply_button">vėlom</string>
<string name="notify_new_message">payomė nu</string>
<string name="notify_name_and_message">nom vo payom</string>
<string name="notify_name_only">têynā nom</string>
<string name="notify_no_name_or_message">nom yā payomi nî</string>
<string name="global_menu_preferences_language_desktop">zow</string>
<string name="global_menu_file_desktop">fāyl</string>
<string name="global_menu_file_quit_desktop">vê dar zêyďên</string>
<string name="global_menu_edit_desktop">ālêšt</string>
<string name="global_menu_edit_cut_desktop">jā goro kerdên</string>
<string name="global_menu_edit_copy_desktop">lefgiri</string>
<string name="global_menu_edit_paste_desktop">jā vandên</string>
<string name="global_menu_file_open_desktop">gušiďênê dêltā čat</string>
<string name="delete_message_desktop">pāk kerdên payom</string>
<string name="remove_desktop">pāk kerdên</string>
<string name="save_desktop">zaft</string>
<string name="name_desktop">nom</string>
<string name="select_group_image_desktop">pêsandê šîvātê jarga</string>
<string name="message_detail_sent_desktop">fêšnāďe vâbi</string>
<string name="message_detail_received_desktop">gêrîďe vâbi</string>
<string name="show_window">nêšow dāďênê nimdari</string>
<string name="open_settings">gušiďênê sāmovā</string>
<string name="verified_by">تاییڌ وابیڌه و دس %1$s</string>
<!-- notifications -->
<string name="notify_reply_button">ولوم</string>
<string name="notify_new_message">پیوم نۊ</string>
<string name="notify_name_and_message">نوم وو پیوم</string>
<string name="notify_name_only">تینا نوم</string>
<string name="notify_no_name_or_message">بؽ نوم یا پیوم</string>
<string name="global_menu_preferences_language_desktop">زۉݩ</string>
<string name="global_menu_file_desktop">فایل</string>
<string name="global_menu_file_quit_desktop">و در زیڌن</string>
<string name="global_menu_edit_desktop">آلشت</string>
<string name="global_menu_edit_cut_desktop">جا گورو</string>
<string name="global_menu_edit_copy_desktop">لف گیری</string>
<string name="global_menu_edit_paste_desktop">جا وندن</string>
<string name="global_menu_file_open_desktop">گۊشیڌن دلتا چت</string>
<string name="delete_message_desktop">پاک کردن پیوم</string>
<string name="remove_desktop">پاک کردن</string>
<string name="save_desktop">زفت</string>
<string name="name_desktop">نوم</string>
<string name="select_group_image_desktop">پسند شؽوات جرگه</string>
<string name="message_detail_sent_desktop">فشناڌ</string>
<string name="message_detail_received_desktop">گرؽڌه وابی</string>
<string name="show_window">نشۉ داڌن نیمدری</string>
<string name="open_settings">گۊشیڌن سامووا</string>
</resources>
+24 -4
View File
@@ -4,9 +4,11 @@
<string name="app_name">Delta Chat</string>
<string name="ok">OK</string>
<string name="cancel">Cancel·la</string>
<!-- deprecated, the word "or" to separate blocks in the user interface that are mutually exclusive -->
<string name="or_separator">o</string>
<string name="clear_search">Neteja la cerca</string>
<!-- a noun, used on a button, short for "show link" -->
<string name="link">Enllaç</string>
<!-- "scan" in the meaning of "scan QR code" -->
<string name="scan">Escaneja</string>
<string name="yes">Si</string>
<string name="no">No</string>
<string name="select">Trieu</string>
@@ -54,6 +56,7 @@
<string name="show_full_message">Mostra el missatge sencer...</string>
<!-- Stay short here, say ~16 characters. The source string could also be "All Read", maybe that hint can make translations easier :) -->
<string name="mark_all_as_read">Marca-ho tot com a llegit</string>
<string name="mark_as_read">Marca com a llegit</string>
<!-- Shortest text for "Mark as being read". In english, this could be "Read" (past tense of "to read"), in german, this could be "Gelesen". -->
<string name="mark_as_read_short">Llegit</string>
<!-- Placeholder text when something is loading -->
@@ -124,6 +127,10 @@
<item quantity="one">%d missatge</item>
<item quantity="other">%d missatges</item>
</plurals>
<plurals name="n_reactions">
<item quantity="one">%d reacció</item>
<item quantity="other">%d reaccions</item>
</plurals>
<plurals name="n_members">
<item quantity="one">%d membre</item>
<item quantity="other">%d membres</item>
@@ -535,6 +542,8 @@
<string name="pref_profile_info_headline">Informació del vostre perfil</string>
<string name="pref_profile_photo">Fotografia de perfil</string>
<string name="pref_blocked_contacts">Contactes bloquejats</string>
<!-- for classic email, we use the classical term "Account" -->
<string name="pref_password_and_account_settings">Contrasenya i compte</string>
<string name="pref_who_can_see_profile_explain">La vostra imatge de perfil i el vostre nom es mostraran en els missatges que envieu als altres usuaris. La informació que ja s\'hagi enviat no es pot eliminar ni esborrar.</string>
<string name="pref_your_name">El vostre nom</string>
<!-- Translators: Visible only to recipients who DO NOT use Delta Chat, so it's the last line in an E-mail and not a "Status". -->
@@ -566,14 +575,13 @@
<string name="pref_incognito_keyboard_explain">Sol·licita al teclat que deshabiliti l\'aprenentatge personalitzat</string>
<string name="pref_read_receipts">Confirmació de lectura</string>
<string name="pref_read_receipts_explain">Si desactiveu la confirmació de lectura dels vostres missatges, tampoc no rebreu la dels altres usuaris.</string>
<string name="pref_server">Servidor</string>
<string name="pref_manage_keys">Gestioneu les claus</string>
<string name="pref_use_system_emoji">Useu emojis de sistema</string>
<string name="pref_use_system_emoji_explain">Deshabilita el suport de sèrie per emoticones a Delta Chat</string>
<string name="pref_app_access">Accés a l\'aplicació</string>
<string name="pref_chats">Xats</string>
<string name="pref_in_chat_sounds">Sons d\'entrada</string>
<!-- deprecated -->
<string name="pref_message_text_size">Mida de la font del missatge</string>
<string name="pref_view_log">Veure el registre</string>
<string name="pref_other">Altres</string>
<string name="pref_backup">Còpia de seguretat</string>
@@ -601,6 +609,16 @@
<string name="pref_show_emails_no">No, només xats</string>
<string name="pref_show_emails_accepted_contacts">Per a contactes acceptats</string>
<string name="pref_show_emails_all">Tot</string>
<string name="pref_edit_profile">Edita el perfil</string>
<string name="send_stats_to_devs">Envia estadístiques als desenvolupadors del Delta Chat</string>
<!-- Reactions -->
<string name="reactions">Reaccions</string>
<!-- Verb, the action of adding a "Reaction" to a message. Used eg. in context menus, similar to "Reply" or "Forward" -->
<string name="react">Reacciona</string>
<!-- %1$s will be replaced by an emoji. %2$s will be replaced by message summary (the summary is often long and whole string gets truncated; words after %2$s will often not being visible). Eg. 'You reacted 👍 to "Found my suitcase"'. Use less than 20 characters, otherwise the string will be truncated too soon and too few information are shown. Do not try to translate "reacted to" too strict. Depending on the language, "added 👍 to" or "gave 👍 to" or just "👍 to" may be shorter and/or clearer and work as well. -->
<string name="reaction_by_you">Heu reaccionat amb %1$s a «%2$s»</string>
<!-- autocrypt -->
<string name="autocrypt_send_asm_title">Envia el missatge de configuració Autocrypt</string>
<string name="autocrypt_send_asm_explain_before">Un \"missatge de configuració Autocrypt\" comparteix de forma segura la vostra configuració d\'extrem a extrem amb altres aplicacions compatibles amb Autocrypt.\n\nLa configuració es xifrarà amb un codi de configuració que es mostrarà aquí i que haureu d\'escriure a laltre dispositiu.</string>
@@ -662,6 +680,7 @@
<string name="contact_not_verified">No es pot verificar%1$s</string>
<!-- translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message" -->
<string name="contact_setup_changed">Configuració canviada per %1$s</string>
<!-- notifications -->
<string name="notify_reply_button">Respondre</string>
<string name="notify_new_message">Missatge nou</string>
<string name="notify_background_connection_enabled">Connexió habilitada en segon pla</string>
@@ -694,6 +713,7 @@
<string name="global_menu_view_developer_desktop">Desenvolupador</string>
<string name="global_menu_view_developer_tools_desktop">Eines de desenvolupador</string>
<string name="global_menu_help_desktop">Ajuda</string>
<!-- deprecated, use contribute instead -->
<string name="global_menu_help_contribute_desktop">Col·labora a GitHub</string>
<string name="global_menu_help_report_desktop">Informa d\'un problema</string>
<string name="no_chat_selected_suggestion_desktop">Tria un xat o crea\'n un de nou</string>
+3 -5
View File
@@ -4,7 +4,7 @@
<string name="app_name">دێڵتا چات</string>
<string name="ok">باشە</string>
<string name="cancel">وازبێنە</string>
<string name="yes">بەڵێ</string>
<string name="yes">بەڵێ</string>
<string name="no">نا</string>
<string name="select">هەڵبژاردن</string>
<string name="on">چالاک</string>
@@ -420,8 +420,6 @@
<string name="pref_app_access">ڕێگەپێدان</string>
<string name="pref_chats">وتووێژەکان</string>
<string name="pref_in_chat_sounds">دەنگەکانی نێو-وتووێژی</string>
<!-- deprecated -->
<string name="pref_message_text_size">قەبارەی فۆنتی پەیامەکان</string>
<string name="pref_other">کەسانی دی</string>
<string name="pref_backup">یەدەک</string>
<string name="pref_backup_explain">یەدەک گرتن لە وتووێژەکان و دانانی لەسەر بیرگەی دەرەکی</string>
@@ -524,6 +522,7 @@
<!-- translators: "setup" is the "encryption setup" here, as in "Autocrypt Setup Message" -->
<string name="contact_setup_changed">ڕێکخستن بۆ %1$s گۆڕا.</string>
<string name="copy_qr_data_success">ناونیشانی وێبی QRەکە ڕوونووس کرا.</string>
<!-- notifications -->
<string name="notify_reply_button">وەڵام دانەوە</string>
<string name="notify_new_message">پەیامی نوێ</string>
<string name="notify_background_connection_enabled">پەیوەندی پشتخان چالاک کرا</string>
@@ -556,6 +555,7 @@
<string name="global_menu_edit_paste_desktop">لکاندن</string>
<string name="global_menu_view_desktop">دیتن</string>
<string name="global_menu_help_desktop">یارمەتی</string>
<!-- deprecated, use delta_chat_homepage instead -->
<string name="global_menu_help_learn_desktop">زۆرتر سەبارەت بە دێڵتاچات_ەوە بزانە</string>
<string name="global_menu_help_report_desktop">کێشەیەک گوزارشت بکە</string>
<string name="global_menu_help_about_desktop">سەبارەت بە دێڵتا چات</string>
@@ -588,8 +588,6 @@
<string name="InfoPlist_NSMicrophoneUsageDescription">دێڵتا چات بۆ تۆمار کردن و هەناردنی دەنگ و هەروەها ڤیدیۆی دەنگدار، مایکەکەت بەکاردەهێنێت.</string>
<string name="InfoPlist_NSPhotoLibraryUsageDescription">دێڵتا چات ڕێگە دەدات خۆت هەڵیبژێری کە کام وێنە لە پیشانگاکەتەوە بنێردرێت.</string>
<string name="InfoPlist_NSPhotoLibraryAddUsageDescription">دێڵتا چات دەیەوێت وێنە پاشەکەوت بکاتە نێو پیشانگاکەت.</string>
<!-- disabling "Reliable service" will hide a the maybe annoying permanent-notification with the drawback that new-message-notifications get potentially unreliable -->
<string name="perm_enable_bg_reminder_title">بۆ وەرگرتنی پەیامەکان لەو کاتانەدا کە دێڵتا چات لە پشتخانەوەیە، لێرە کرتە بکە.</string>
<string name="perm_enable_bg_already_done">تۆ ئێستا ڕێگەت بە دێڵتا چات دا کە لە پشتخانەوە پەیامەکان وەربگرێت.\n\n ئەگەر هێشتا لە پشخاندا پەیامەکان نایەن، سەرنجێکیش لە ڕێکخستنەکانی سیستەم بدەوە.</string>

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