Compare commits

...

149 Commits

Author SHA1 Message Date
adbenitez 6f1f446aa8 Merge remote-tracking branch 'upstream/main' 2025-12-08 19:17:03 +01:00
adbenitez e5149ac255 Merge remote-tracking branch 'upstream/main' 2025-12-08 19:16:02 +01:00
adb 403539da35 Merge pull request #4100 from deltachat/prep-2.33.0
prepare 2.33.0
2025-12-08 17:40:18 +01:00
adbenitez 443501112d prepare 2.33.0 2025-12-08 17:39:31 +01:00
adb bea2effb89 Merge pull request #4099 from deltachat/adb/update-translations-2025.12.08
update translations
2025-12-08 17:34:41 +01:00
adbenitez b2d875cc61 update translations 2025-12-08 17:30:55 +01:00
B. Petersen e94f571744 remove more deprecated strings 2025-12-08 16:25:19 +01:00
adb 69c6fdd070 Merge pull request #4096 from deltachat/adb/rename-relayutil
Rename RelayUtil to ShareUtil
2025-12-08 15:37:39 +01:00
B. Petersen 1b9bfc37ad remove deprecated strings 2025-12-08 15:20:30 +01:00
B. Petersen 8cb1c195b1 mark unused string as deprecated 2025-12-08 13:38:20 +01:00
B. Petersen 41f963332c remove 'email' from welcome message 2025-12-08 13:38:20 +01:00
B. Petersen dc6dee6a1a reword 'transport' to 'relay' 2025-12-08 13:38:20 +01:00
adbenitez 35becfc63b rename RelayUtil to ShareUtil 2025-12-08 12:54:42 +01:00
adb f6c25a2015 Merge pull request #4085 from deltachat/adb/issue-4082
improve KeepAliveService
2025-12-08 12:47:58 +01:00
adb be01c3b14f Merge branch 'main' into adb/issue-4082 2025-12-07 17:21:50 +01:00
adb bf435f4303 Merge pull request #4090 from deltachat/adb/issue-4089
only save common image formats to Pictures
2025-12-07 17:21:31 +01:00
adb 1f455c435f Merge pull request #4093 from deltachat/adb/improve-relay-list-item-layout
improve realy_list_item layout
2025-12-07 12:55:03 +01:00
adbenitez db8d4b5daf improve realy_list_item layout 2025-12-07 12:53:29 +01:00
adb 5ac7f9ee11 Merge branch 'main' into adb/issue-4082 2025-12-07 12:34:43 +01:00
adb 6c80f85290 Merge branch 'main' into adb/issue-4089 2025-12-07 12:34:30 +01:00
adb 744bca93e8 Merge pull request #4092 from deltachat/link2xt/flake-android-36
flake.nix: update Android SDK from 35 to 36
2025-12-07 12:34:13 +01:00
adb 601a65a1cb Merge pull request #4080 from deltachat/adb/add-transport-list-activity
add screen to list/add/remove transports/relays
2025-12-07 12:33:50 +01:00
adbenitez 9f2523da21 use R.string.def, don't add extra string 2025-12-07 11:50:47 +01:00
link2xt c936d51bac flake.nix: update Android SDK from 35 to 36
Closes <https://github.com/deltachat/deltachat-android/issues/4091>
2025-12-06 21:02:00 +00:00
adbenitez b77862c290 update changelog 2025-12-05 23:48:21 +01:00
adbenitez c495c3936b only save common image formats to Pictures 2025-12-05 23:45:27 +01:00
adbenitez a5a5819eec add makefile 2025-12-05 23:18:41 +01:00
adbenitez 429c3fb57c tweak changelog 2025-12-05 23:08:10 +01:00
adb 0c9bec1d3d Merge branch 'main' into adb/add-transport-list-activity 2025-12-05 23:07:06 +01:00
adb 51771669d3 Merge pull request #4088 from deltachat/update-core-and-stuff-2025.12.5
Update core to 2.33.0
2025-12-05 23:06:18 +01:00
adbenitez f32651cd9d update RPC bindings 2025-12-05 23:03:33 +01:00
adbenitez 07a2663591 update translations 2025-12-05 22:59:22 +01:00
adbenitez fe9ee4c484 update changelog 2025-12-05 22:55:12 +01:00
adbenitez 1425815467 update deltachat-core-rust to 'chore(release): prepare for 2.33.0' of 'v2.33.0' 2025-12-05 22:52:47 +01:00
adbenitez eea4a1b124 Merge remote-tracking branch 'upstream/main' 2025-12-05 22:37:50 +01:00
adb 72c7772e89 Merge pull request #4086 from deltachat/adb/set-clipToPadding-in-xml
set clipToPadding in xml instead of dynamically
2025-12-05 22:37:18 +01:00
adb c4f0dc2f2d Merge branch 'main' into adb/set-clipToPadding-in-xml 2025-12-05 22:36:47 +01:00
adb 2d0645465e Merge pull request #4087 from deltachat/adb/make-last-item-visible-in-chatlist
make last item fully visible when scrolling bottom of chat list
2025-12-05 22:27:06 +01:00
adbenitez 5031993289 update changelog 2025-12-05 21:22:07 +01:00
adbenitez 8e944552b3 make last item fully visible in chat list 2025-12-05 21:18:16 +01:00
adbenitez 342b071189 set clipToPadding in xml instead of dynamically 2025-12-05 21:12:11 +01:00
Korb 32248b4635 Adding Russian metadata translation (#62)
* Create ru-RU/title.txt

* Create ru-RU/short_description.txt
2025-12-05 19:00:30 +01:00
adbenitez 89b4be49c8 tweak dialog buttons's color 2025-12-05 01:55:04 +01:00
adbenitez b3230abd68 update changelog 2025-12-05 01:40:17 +01:00
adbenitez e26ac3d264 improve KeepAliveService 2025-12-05 00:29:58 +01:00
adbenitez fcc98e81d5 Merge remote-tracking branch 'upstream/main' 2025-12-04 23:19:42 +01:00
adb bd4fa0b032 Merge branch 'main' into adb/add-transport-list-activity 2025-12-04 23:16:58 +01:00
adb d4675f25ec Merge pull request #4084 from deltachat/adb/fix-log-view
use DcContext.getInfo() in LogViewFragment
2025-12-04 21:49:05 +01:00
adbenitez a2a440e57b use DcContext.getInfo() in LogViewFragment 2025-12-04 21:19:17 +01:00
adbenitez f24b2e2540 update changelog 2025-12-04 20:15:55 +01:00
adbenitez f8d2cd7bf3 Merge branch 'adb/add-transport-list-activity' of https://github.com/deltachat/deltachat-android into adb/add-transport-list-activity 2025-12-04 20:12:14 +01:00
adbenitez 1ff99ddbe4 add "add transport" floating button 2025-12-04 20:11:42 +01:00
adb 13bf0d6f9f Merge branch 'main' into adb/add-transport-list-activity 2025-12-04 18:42:58 +01:00
adbenitez d24f53895e allow to add transport from QR scanner 2025-12-04 18:42:14 +01:00
B. Petersen 66e8fa9d9e clearly say that experiments may be unstable/changed/removed
by the bare title, this is not clear to everyone.
technically, i also tried <PreferenceCategory summary>,
but that does not wrap text.

moved down 'app picker' for better layout and to match
order of other UI.
2025-12-03 20:28:33 +01:00
adbenitez 230fb79584 allow removing transports 2025-12-02 05:32:21 +01:00
adbenitez 9181a9c398 add uncommited/missing import in RelayListActivity 2025-12-02 05:21:02 +01:00
adbenitez 2f05b20b0f allow editing transports 2025-12-02 05:20:42 +01:00
adbenitez 115ffae588 create RelayListActivity with basic listing of relays/transports 2025-12-02 04:46:30 +01:00
adb 7455e56f11 Merge branch 'main' into adb/add-transport-list-activity 2025-12-01 23:34:05 +01:00
adb d4b8e4bafa Merge pull request #4081 from deltachat/adb/remove-superfluous-dynamic-theme-usage
remove superfluous DynamicTheme usage
2025-12-01 23:21:15 +01:00
adbenitez 67a2e3fcd9 Merge remote-tracking branch 'upstream/main' 2025-12-01 22:04:51 +01:00
adbenitez f12d6855e9 remove superfluous DynamicTheme usage 2025-12-01 21:46:09 +01:00
adbenitez 56459e7e7a add TransportListActivity 2025-12-01 21:26:37 +01:00
adb d5244f5f96 Merge pull request #4079 from deltachat/update-core-and-stuff-2025.12.01
update core to 2.29.0
2025-12-01 21:02:16 +01:00
adbenitez c8722ddcc6 update translations 2025-12-01 20:59:37 +01:00
adbenitez 5874001ec2 update changelog 2025-12-01 20:58:00 +01:00
adbenitez b94a4cbe8b update deltachat-core-rust to 'chore(release): prepare for 2.29.0' of 'v2.29.0' 2025-12-01 20:04:20 +01:00
B. Petersen 5d0b5f7947 remove InfoPlist_NSContactsUsageDescription, this should no longer go to InfoPlist files 2025-12-01 17:54:57 +01:00
adbenitez a193ee6cdf add publishing to ZapStore to CI 2025-11-30 03:00:58 +01:00
B. Petersen ff438731d8 mark strings as deprecated 2025-11-29 13:20:55 +01:00
B. Petersen 08913a5e76 adapt wording to 'delete contact' question; we no longer check the address book 2025-11-29 13:19:24 +01:00
adb e7d2656613 Merge pull request #4074 from deltachat/adb/remove-read-contacts-permission
remove need for READ_CONTACS permission
2025-11-29 02:42:58 +01:00
adbenitez f3210f2626 remove need for READ_CONTACS permission 2025-11-29 02:25:23 +01:00
adb 0b1fa7c7d1 Merge pull request #4073 from deltachat/adb/remove-dev-mode
remove mostly unused dev mode
2025-11-29 02:14:27 +01:00
adbenitez 6b6d48f5da remove mostly unused dev mode 2025-11-29 02:02:22 +01:00
adbenitez 3b9e989195 Merge remote-tracking branch 'upstream/main' 2025-11-29 01:56:03 +01:00
adbenitez 4af065aad9 Merge remote-tracking branch 'upstream/main' 2025-11-29 00:46:41 +01:00
B. Petersen b0e918caab remove explains partly refering to shared usage 2025-11-28 23:55:11 +01:00
B. Petersen a6384dc679 clearer category name 2025-11-28 23:55:11 +01:00
B. Petersen 838db45a74 hiding a categoty hides its options 2025-11-28 23:55:11 +01:00
B. Petersen 44328f1086 update advanced settings
- move 'server' up
- move other options down, after experimental
- introduce 'legacy' section
2025-11-28 23:55:11 +01:00
adb 2064a2f0ea Merge pull request #4071 from deltachat/adb/edge-to-edge3
use recommended way of enabling edge-to-edge
2025-11-28 22:01:58 +01:00
adbenitez 6b066d9428 update comment in BaseActionBarActivity 2025-11-28 21:56:25 +01:00
adb d68508c0cf Merge pull request #4070 from deltachat/adb/update-changelog-2025.11.28
update changelog
2025-11-28 18:15:50 +01:00
adbenitez 5f5f303a93 update changelog 2025-11-28 18:14:38 +01:00
adb 71bb0105ab Merge pull request #4066 from deltachat/adb/webview-links-tweaks
add URL schemes whitelist
2025-11-28 18:12:23 +01:00
adb 796c81af61 Merge pull request #4067 from deltachat/adb/target-sdk-36
Target SDK 36
2025-11-28 18:11:39 +01:00
adb 329c7a52a7 Merge pull request #4064 from deltachat/adb/edge-to-edge2
Make  edge-to-edge great again
2025-11-28 18:10:16 +01:00
B. Petersen b19d39b794 use updated texts in tests 2025-11-28 14:27:18 +01:00
B. Petersen b4d8f1e04f remove all png files before help creation 2025-11-28 14:25:03 +01:00
adbenitez febf2cb105 (temporarily) opt-out predictive back 2025-11-28 02:19:00 +01:00
adbenitez ef00e04638 update compileSdk and targetSdkVersion to 36 in build.gradle 2025-11-28 01:49:49 +01:00
adb 1042f4b4f8 Merge branch 'adb/edge-to-edge2' into adb/webview-links-tweaks 2025-11-28 01:38:39 +01:00
adb 0180d63821 Merge branch 'main' into adb/edge-to-edge2 2025-11-28 01:38:20 +01:00
adb 8b8c6b6bbb Merge pull request #4050 from deltachat/adb/issue-4049
garbage-collect storage of deleted webxdc apps
2025-11-28 01:37:31 +01:00
adbenitez fe8ad85f89 assume core will handle unexisting accounts 2025-11-28 01:35:03 +01:00
adbenitez c938c4dcd9 check for existing account IDs 2025-11-28 01:26:51 +01:00
adb 35f6a06406 Merge branch 'main' into adb/issue-4049 2025-11-27 19:28:49 +01:00
adbenitez db7365c3b3 restrict supported URL schemas 2025-11-27 19:10:18 +01:00
adbenitez 51d7e5df62 update changelog 2025-11-27 07:39:51 +01:00
adb 28f7fbf806 Merge branch 'main' into adb/edge-to-edge2 2025-11-27 07:39:00 +01:00
adbenitez d6d3dd8930 enable edge-to-edge only in SDK 30+ 2025-11-27 07:20:05 +01:00
adbenitez 83571ba0bf ConversationListActivity: fix display of searchToolbar 2025-11-26 23:55:51 +01:00
adbenitez 34fc888c5e WebViewActivity: improve integrated map's edge-to-edge 2025-11-26 23:40:23 +01:00
adbenitez 0a7be040c3 NewContactActivity: small tweaks 2025-11-26 23:11:27 +01:00
adbenitez 448334a8a2 ShareActivity: properly implement edge-to-edge 2025-11-26 23:01:28 +01:00
adbenitez 5141116f38 QrShowActivity: properly implement edge-to-edge 2025-11-26 22:54:20 +01:00
adbenitez 310500b8d7 ProfileActivity: properly implement edge-to-edge 2025-11-26 22:20:59 +01:00
adbenitez 7bc0ab858a ContactSelectionActivity: properly implement edge-to-edge 2025-11-26 22:13:49 +01:00
adbenitez ca438ca3a3 AllMediaActivity: properly implement edge-to-edge 2025-11-26 21:55:45 +01:00
adbenitez 2a2cb7c26e QrActivity: properly implement edge-to-edge 2025-11-26 21:24:58 +01:00
adbenitez 9e5a2d30ed WelcomeActivity: properly implement edge-to-edge 2025-11-26 20:57:50 +01:00
adbenitez 5b8c0db287 WebxdcStoreActivity: properly implement edge-to-edge 2025-11-26 20:32:06 +01:00
adbenitez 08864ae250 WebViewActivity: properly implement edge-to-edge 2025-11-26 20:26:48 +01:00
adbenitez ea6bd9283c EditTransportActivity: properly implement edge-to-edge 2025-11-26 20:11:49 +01:00
adbenitez 83dfca249d LogViewActivity: properly implement edge-to-edge 2025-11-26 19:59:23 +01:00
adbenitez c7d41d1b84 InstantOnboardingActivity: properly implement edge-to-edge 2025-11-26 19:38:55 +01:00
adbenitez b09838f033 ConversationListActivity: properly implement edge-to-edge 2025-11-26 07:55:35 +01:00
adbenitez 10164032f0 GroupCreateActivity: properly implement edge-to-edge 2025-11-26 06:28:25 +01:00
adbenitez 7829ff0a83 CreateProfileActivity: properly implement edge-to-edge 2025-11-26 06:01:49 +01:00
adbenitez aaa8a07511 ConversationListArchiveActivity: properly implement edge-to-edge 2025-11-26 05:43:12 +01:00
adbenitez cd2aedcc6b ConversationActivity: properly implement edge-to-edge 2025-11-26 04:05:09 +01:00
adbenitez 553610cfa4 BlockedContactsActivity: properly implement edge-to-edge 2025-11-26 03:14:43 +01:00
adbenitez ceea00e2cc ApplicationPreferencesActivity: properly implement edge-to-edge 2025-11-26 02:41:33 +01:00
adbenitez ef512b0f14 RegistrationQrActivity: properly implement edge-to-edge 2025-11-26 01:10:57 +01:00
adbenitez 83a7e4df3f BackupTransferActivity: properly implement edge-to-edge 2025-11-26 00:49:08 +01:00
adbenitez d4aa90cc0c ProxySettingsActivity: properly implement edge-to-edge 2025-11-26 00:31:12 +01:00
adbenitez 342d820095 ChatBackgroundActivity: properly implement edge-to-edge 2025-11-25 23:29:19 +01:00
adbenitez 18d9c00d13 NewContactActivity: properly implement edge-to-edge 2025-11-25 22:30:20 +01:00
B. Petersen 8df792a8e3 mark strings that are about to be no longer needed as deprecated 2025-11-25 20:25:06 +01:00
B. Petersen 0693f8ad60 mark strings that are about to be no longer needed as deprecated 2025-11-25 13:50:39 +01:00
adb eaa6a68e4f Merge pull request #4060 from deltachat/adb/issue-4058
add output of `Rpc.getStorageUsageReportString()` to log
2025-11-24 21:16:23 +01:00
adbenitez 174170ee4f update changelog 2025-11-24 00:54:09 +01:00
adbenitez 3ee2c3f0be add output of Rpc.getStorageUsageReportString() to log 2025-11-24 00:44:34 +01:00
adbenitez 339ab13f64 update changelog 2025-11-24 00:18:54 +01:00
adbenitez 777e6f40cb use getExistingMsgIds() 2025-11-23 23:39:47 +01:00
adb 577ec92c53 Merge branch 'main' into adb/issue-4049 2025-11-23 23:29:50 +01:00
adb 9f40d84a51 Merge branch 'main' into adb/issue-4049 2025-11-23 22:50:04 +01:00
adb f1d9ddeed6 Merge branch 'main' into adb/issue-4049 2025-11-23 16:20:05 +01:00
adb da1e71b2d2 Merge branch 'main' into adb/issue-4049 2025-11-22 22:28:03 +01:00
adbenitez 00027ad8f3 remove unused imports 2025-11-22 20:05:46 +01:00
adbenitez 81e7f37d61 move WebxdcGarbageCollectionWorker to webxdc package 2025-11-22 20:05:21 +01:00
adb 4e6c1e3eaf Merge pull request #4051 from deltachat/link2xt/webxdc-garbage-collector-worker
Add WebxdcGarbageCollectionWorker
2025-11-22 19:25:01 +01:00
link2xt 77eda90923 Add WebxdcGarbageCollectionWorker 2025-11-22 16:40:58 +00:00
adbenitez e96b4db126 Merge branch 'adb/issue-4049' of https://github.com/deltachat/deltachat-android into adb/issue-4049 2025-11-22 00:06:02 +01:00
adbenitez 118d4f864f add startup delay to avoid bottleneck on app start 2025-11-22 00:05:40 +01:00
adb d6259f112e Merge branch 'main' into adb/issue-4049 2025-11-22 00:03:16 +01:00
adbenitez 2a3934cbd7 garbage-collect storage of deleted webxdc apps 2025-11-21 22:47:25 +01:00
163 changed files with 2414 additions and 2363 deletions
+12 -1
View File
@@ -60,7 +60,7 @@ jobs:
./gradlew assembleGplayRelease
mv build/outputs/apk/gplay/release/*universal* build/outputs/apk/foss/release/ArcaneChat-gplay.apk
- name: Release
- name: Release on GitHub
uses: softprops/action-gh-release@v1
with:
token: "${{ secrets.GITHUB_TOKEN }}"
@@ -68,3 +68,14 @@ jobs:
prerelease: ${{ contains(github.event.ref, '-beta') }}
fail_on_unmatched_files: true
files: build/outputs/apk/foss/release/*.apk
- name: Release on ZapStore
run: |
export CHECKSUM=6e2c7cf6da53c3f1a78b523a6aacd6316dce3d74ace6f859c2676729ee439990
curl -sL https://cdn.zapstore.dev/$CHECKSUM -o zapstore
if echo "$CHECKSUM zapstore" | sha256sum -c --status; then
chmod +x zapstore
SIGN_WITH=${{ secrets.NOSTR_KEY }} ./zapstore publish --indexer-mode
else
echo "ERROR: checksum doesn't match!"
fi
+13 -2
View File
@@ -1,19 +1,30 @@
# Delta Chat Android Changelog
## Unreleased
## v2.33.0
2025-12
* Target Android 16
* Change color of links in text messages
* Improve edge-to-edge support
* Metadata protection: protect message recipients
* Allow to withdraw channel invite links and QR codes
* Allow to open externally links clicked inside in-chat apps
* Do not show "1 member" when the process of joining the group is not finished
* Make search case-insensitive for non-ASCII chat and contact names
* Improve handling of video recoding
* Send .webm videos as file, they are not supported by all platforms
* Tweak advanced section and wording of some advanced options
* Fix: avoid crash in push notifications handling
* Fix: avoid freezing in background
* Fix: clean up web storage of deleted in-chat apps
* Fix: avoid crash when exporting some files with wrong image MIME type
* Expose new "Multi-device mode" option instead of "Delete from server" for chatmail profiles
* Opened in-chat apps got a 'About Apps' menu item
* Avoid gray avatar on profile creation
* Update to core 2.28.0
* Avoid last item in chat list being covered by the floating button
* Add disk usage statistics to log
* New experimental feature: several addresses per profile
* Update to core 2.33.0
## v2.25.0
2025-11
+5 -4
View File
@@ -21,7 +21,7 @@ android {
}
namespace "org.thoughtcrime.securesms"
flavorDimensions "none"
compileSdk 35
compileSdk 36
// Set NDK version to strip native libraries.
// Even though we compile our libraries outside Gradle with `scripts/ndk-make.sh`,
@@ -33,14 +33,14 @@ android {
useLibrary 'org.apache.http.legacy'
defaultConfig {
versionCode 30000732
versionName "2.25.0"
versionCode 30000733
versionName "2.33.0"
applicationId "chat.delta.lite"
multiDexEnabled true
minSdkVersion 21
targetSdkVersion 35
targetSdkVersion 36
vectorDrawables.useSupportLibrary = true
@@ -211,6 +211,7 @@ dependencies {
implementation "io.noties.markwon:inline-parser:$markwon_version"
implementation 'com.airbnb.android:lottie:4.2.2' // Lottie animations support.
implementation 'androidx.concurrent:concurrent-futures:1.3.0'
implementation 'androidx.sharetarget:sharetarget:1.2.0'
implementation 'androidx.webkit:webkit:1.14.0'
implementation 'androidx.multidex:multidex:2.0.1'
@@ -0,0 +1,36 @@
ArcaneChat — децентрализованный и защищённый мессенджер, удобный для друзей и семьи.
• Анонимность. Мгновенный вход без номера телефона, e-mail или других личных данных.
• Гибкость. Поддерживает несколько профилей чатов и легко настраивается на нескольких устройствах.
• Расширяемость. В чатах можно использовать мини-приложения: списки покупок, календари или игры.
• Надёжность. Работает даже при плохом соединении и в сложных сетевых условиях.
• Безопасность. Проверенное сквозное шифрование, защищённое от сетевых и серверных атак.
• Самостоятельность. Может работать с вашим собственным e-mail-адресом или сервером.
ArcaneChat — клиент Delta Chat, разработанный с акцентом на удобство, качественный UX и экономию трафика. Также приложение часто экспериментирует с новыми функциями, которые со временем могут быть добавлены в официальный клиент Delta Chat.
<b>Основные отличия от официального клиента Delta Chat:</b>
<ul>
<li>Поддержка некоторых стилей markdown в текстовых сообщениях (жирный, курсив, зачёркнутый и т.д.)</li>
<li>Поддержка отображения анимированных стикеров Telegram (.tgs-файлы)</li>
<li>Поддержка предпросмотра SVG-изображений</li>
<li>Несколько цветовых тем/скинов</li>
<li>Возможность отключать профили, полностью отключая им доступ в сеть для экономии трафика</li>
<li>На панели переключения профилей видно состояние подключения каждого профиля</li>
<li>Дополнительная опция для обмена местоположением на 12 часов</li>
<li>Нажатие на сообщение с POI открывает его на карте</li>
<li>Статус «был(а) в сети» отображается в списке контактов, как в WhatsApp, Telegram и т.д.</li>
<li>Видео воспроизводятся по кругу — удобно для коротких GIF-видео</li>
<li>У чата «Device Messages» в списке чатов отображается значок подтверждения</li>
<li>В режиме «низкое качество» голосовые сообщения сжимаются сильнее для экономии трафика</li>
<li>Автоматическая загрузка сообщений по умолчанию ограничена 640KB</li>
<li>Отображаемое имя профиля всегда видно в заголовке приложения вместо названия приложения</li>
<li>Для разработчиков мини-приложений: доступны дополнительные возможности WebXDC API, см. https://github.com/ArcaneChat/android/#webxdc</li>
<li>Более удобная организация настроек с дополнительным разделом «Privacy»</li>
</ul>
@@ -0,0 +1 @@
⚡ Быстрые зашифрованные чаты для семьи 🎉
@@ -0,0 +1 @@
ArcaneChat
+1 -1
View File
@@ -18,7 +18,7 @@
build-tools-35-0-0
cmdline-tools-latest
platform-tools
platforms-android-35
platforms-android-36
ndk-27-2-12479018
]);
rust-version = pkgs.lib.removeSuffix "\n"
+83
View File
@@ -0,0 +1,83 @@
.PHONY: apk
apk:
./scripts/rebrand.sh
./gradlew --offline assembleGplayRelease
./scripts/undo_rebrand.sh
.PHONY: aab
aab:
./scripts/rebrand.sh
sed -i 's/signingConfigs.releaseApk/signingConfigs.releaseBundle/g' build.gradle
./gradlew --offline bundleGplayRelease
sed -i 's/signingConfigs.releaseBundle/signingConfigs.releaseApk/g' build.gradle
./scripts/undo_rebrand.sh
.PHONY: foss
foss:
./scripts/rebrand.sh
./gradlew --offline assembleFossRelease
./scripts/undo_rebrand.sh
.PHONY: install
install:
adb -d install -r build/outputs/apk/gplay/release/*universal*.apk
.PHONY: emulator-install
emulator-install:
adb install -r build/outputs/apk/gplay/release/*universal*.apk
.PHONY: fetch
fetch:
git fetch upstream
.PHONY: clean
clean:
./gradlew --offline clean
# CORE:
.PHONY: fetch-core
fetch-core:
cd ../core && git fetch upstream
.PHONY: core
core:
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
./scripts/ndk-make.sh; true
./scripts/undo_rebrand.sh
mv jni/deltachat-core-rust ../core
mkdir jni/deltachat-core-rust
.PHONY: core-fast
core-fast:
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
./scripts/ndk-make.sh arm64-v8a; true
./scripts/undo_rebrand.sh
mv jni/deltachat-core-rust ../core
mkdir jni/deltachat-core-rust
.PHONY: core-v7
core-v7:
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
./scripts/ndk-make.sh armeabi-v7a; true
./scripts/undo_rebrand.sh
mv jni/deltachat-core-rust ../core
mkdir jni/deltachat-core-rust
.PHONY: core-x86
core-x86:
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
./scripts/ndk-make.sh x86; true
./scripts/undo_rebrand.sh
mv jni/deltachat-core-rust ../core
mkdir jni/deltachat-core-rust
.PHONY: link
link:
rmdir jni/deltachat-core-rust; mv ../core jni/deltachat-core-rust; true
.PHONY: unlink
unlink:
mv jni/deltachat-core-rust ../core
mkdir jni/deltachat-core-rust
+1
View File
@@ -1 +1,2 @@
rm src/main/assets/help/*.png
../deltachat-pages/tools/create-local-help.py ../deltachat-pages/result src/main/assets/help
@@ -41,7 +41,7 @@ public class OnboardingTest {
}
onView(withText(R.string.scan_invitation_code)).check(matches(isClickable()));
onView(withText(R.string.import_backup_title)).check(matches(isClickable()));
onView(withText(R.string.login_header)).perform(click());
onView(withText(R.string.manual_account_setup_option)).perform(click());
onView(withHint(R.string.email_address)).perform(replaceText(BuildConfig.TEST_ADDR));
onView(withHint(R.string.existing_password)).perform(replaceText(BuildConfig.TEST_MAIL_PW));
onView(withContentDescription(R.string.ok)).perform(click());
+14
View File
@@ -0,0 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
<application>
<service
android:name=".connect.KeepAliveService"
android:foregroundServiceType="specialUse"
android:enabled="true" />
</application>
</manifest>
+5
View File
@@ -10,6 +10,11 @@
<meta-data android:name="firebase_messaging_auto_init_enabled" android:value="false" />
<application>
<service
android:name=".connect.KeepAliveService"
android:foregroundServiceType="dataSync"
android:enabled="true" />
<service
android:name=".notifications.FcmReceiveService"
android:foregroundServiceType="dataSync"
+6 -7
View File
@@ -13,7 +13,6 @@
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
<!-- dangerous permissions - we need to as the user with a PermissionsRequest -->
<uses-permission android:name="android.permission.READ_CONTACTS" />
<uses-permission android:name="android.permission.READ_MEDIA_IMAGES" />
<uses-permission android:name="android.permission.READ_MEDIA_VIDEO" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" android:maxSdkVersion="32" />
@@ -55,6 +54,7 @@
android:requestLegacyExternalStorage="true"
tools:targetApi="TIRAMISU"
android:hasFragileUserData="true"
android:enableOnBackInvokedCallback="false"
>
<!-- android car support, see https://developer.android.com/training/auto/start/,
@@ -233,13 +233,17 @@
android:theme="@style/TextSecure.LightNoActionBar"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".EditTransportActivity"
<activity android:name=".relay.EditRelayActivity"
android:launchMode="singleTask"
android:windowSoftInputMode="stateUnchanged"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"
android:exported="true">
</activity>
<activity android:name=".relay.RelayListActivity"
android:windowSoftInputMode="stateHidden"
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize"/>
<activity android:name=".proxy.ProxySettingsActivity"
android:label="@string/proxy_settings"
android:windowSoftInputMode="stateHidden"
@@ -387,11 +391,6 @@
android:configChanges="touchscreen|keyboard|keyboardHidden|orientation|screenLayout|screenSize">
</activity>
<service
android:name=".connect.KeepAliveService"
android:foregroundServiceType="dataSync"
android:enabled="true" />
<service
android:name=".geolocation.LocationBackgroundService"
android:foregroundServiceType="location" />
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#mám-zájem-o-technické-podrobnosti-kde-najdu-víc">Mám zájem o technické podrobnosti. Kde najdu víc?</a></li>
</ul>
@@ -649,7 +649,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1055,7 +1055,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1067,7 +1067,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1076,7 +1076,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1435,12 +1435,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+85 -102
View File
@@ -16,23 +16,23 @@
<li><a href="#edit">Schreibfehler korrigieren und Nachrichten nach dem Senden löschen</a></li>
<li><a href="#ephemeralmsgs">Wie funktionieren “Verschwindende Nachrichten”?</a></li>
<li><a href="#delold">Was passiert, wenn ich “Alte Nachrichten vom Gerät löschen” aktiviere?</a></li>
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
<li><a href="#remove-account">Wie kann ich mein Chat-Profil löschen?</a></li>
</ul>
</li>
<li><a href="#groups">Groups</a>
<li><a href="#groups">Gruppen</a>
<ul>
<li><a href="#eine-gruppe-anlegen">Eine Gruppe anlegen</a></li>
<li><a href="#addmembers">Add and remove members</a></li>
<li><a href="#addmembers">Mitglieder hinzufügen und entfernen</a></li>
<li><a href="#ich-habe-mich-selbst-versehentlich-gelöscht">Ich habe mich selbst versehentlich gelöscht.</a></li>
<li><a href="#ich-möchte-keine-nachrichten-einer-gruppe-mehr-empfangen">Ich möchte keine Nachrichten einer Gruppe mehr empfangen.</a></li>
<li><a href="#cloning-a-group">Cloning a group</a></li>
<li><a href="#eine-gruppe-klonen">Eine Gruppe klonen</a></li>
</ul>
</li>
<li><a href="#webxdc">In-chat apps</a>
<li><a href="#webxdc">In-Chat-Apps</a>
<ul>
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
<li><a href="#how-private-are-in-chat-apps">How private are in-chat apps?</a></li>
<li><a href="#create-xdc">How can I create my own in-chat apps?</a></li>
<li><a href="#wo-bekomme-ich-in-chat-apps">Wo bekomme ich In-Chat-Apps?</a></li>
<li><a href="#wie-privat-sind-in-chat-apps">Wie privat sind In-Chat-Apps?</a></li>
<li><a href="#create-xdc">Wie kann mich meine eigene In-Chat-Apps erstellen?</a></li>
</ul>
</li>
<li><a href="#instant-delivery">Sofortige Nachrichtenzustellung und Push-Benachrichtigungen</a>
@@ -54,10 +54,10 @@
</li>
<li><a href="#erweitert">Erweitert</a>
<ul>
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#experimentelle-features">Experimentelle Features</a></li>
<li><a href="#statssending">Was ist “Statistik an Delta Chat Entwickler senden”?</a></li>
<li><a href="#kann-ich-eine-klassische-e-mail-adresse-mit-delta-chat-verwenden">Kann ich eine klassische E-Mail-Adresse mit Delta Chat verwenden?</a></li>
<li><a href="#classic-email">Wie kann ich ein Chat-Profil mit einer klassischen E-Mail-Adresse als Relay konfigurieren?</a></li>
<li><a href="#ich-möchte-meinen-eigenen-server-für-delta-chat-verwalten-gibt-es-empfehlungen">Ich möchte meinen eigenen Server für Delta Chat verwalten. Gibt es Empfehlungen?</a></li>
<li><a href="#ich-bin-an-technischen-details-interessiert-gibt-es-hierzu-weitere-infos">Ich bin an technischen Details interessiert. Gibt es hierzu weitere Infos?</a></li>
</ul>
@@ -65,8 +65,8 @@
<li><a href="#e2ee">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">How can I know if messages are end-to-end encrypted?</a></li>
<li><a href="#can-i-still-receive-or-send-messages-without-end-to-end-encryption">Can I still receive or send messages without end-to-end encryption?</a></li>
<li><a href="#whene2e">Wie kann ich wissen, ob Nachrichten Ende-zu-Ende-verschlüsselt sind?</a></li>
<li><a href="#kann-ich-nachrichten-ohne-ende-zu-ende-verschlüsselung-empfangen-oder-senden">Kann ich Nachrichten ohne Ende-zu-Ende-Verschlüsselung empfangen oder senden?</a></li>
<li><a href="#e2eeguarantee">Was bedeutet das grüne Häkchen in einem Kontaktprofil?</a></li>
<li><a href="#sind-anhänge-bilder-dateien-audio-usw-ende-zu-ende-verschlüsselt">Sind Anhänge (Bilder, Dateien, Audio usw.) Ende-zu-Ende-verschlüsselt?</a></li>
<li><a href="#openpgp-secure">Ist OpenPGP sicher?</a></li>
@@ -102,30 +102,26 @@
</h2>
<p>Delta Chat is a reliable, decentralized and secure instant messaging app,
available for mobile and desktop platforms.</p>
<p>Delta Chat ist eine zuverlässige, dezentralisierte und sichere Instant-Messaging-App, verfügbar für Mobile- und Desktop-Plattformen.</p>
<ul>
<li>
<p>Instant creation of <strong>private chat profiles</strong>
with secure and interoperable <a href="https://chatmail.at/relays">chatmail relays</a>
that offer instant message delivery, and Push Notifications for iOS and Android devices.</p>
<p>Einfache Erstellung von <strong>privaten Chat-Profile</strong> mit sicheren, schnellen und interoperablen <a href="https://chatmail.at/relays">Chatmail-Servern</a>,
die sofortige Push-Benachrichtigungen für iOS- und Android-Geräte bieten.</p>
</li>
<li>
<p>Pervasive <a href="#multiple-accounts">multi-profile</a> and
<a href="#multiclient">multi-device</a> support on all platforms
and between different <a href="https://chatmail.at/clients">chatmail apps</a>.</p>
<p>Durchgängige <a href="#multiple-accounts">Mehrprofil</a>- und <a href="#multiclient">Mehrgeräte</a>-Unterstützung auf allen Plattformen und zwischen verschiedenen <a href="https://chatmail.at/clients">Chatmail Apps</a></p>
</li>
<li>
<p>Interactive <a href="#webxdc">in-chat apps</a> for gaming and collaboration</p>
<p>Interaktive <a href="#webxdc">In-Chats-Apps</a> zum Spielen und für die Zusammenarbeit</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">Geprüfte Ende-zu-Ende-Verschlüsselung</a>,
sicher gegen Netzwerk- und Serverangriffe.</p>
</li>
<li>
<p>Free and Open Source software, both app and server side,
built on <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Internet Standards</a>.</p>
<p>Freie und quelloffene Software, sowohl app- als auch serverseitig,
basierend auf <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Internet-Standards</a>.</p>
</li>
</ul>
@@ -137,41 +133,35 @@ built on <a href="https://github.com/chatmail/core/blob/main/standards.md#standa
</h3>
<p>First, note that Delta Chat is a private messenger.
There is no public discovery, <em>you</em> decide about your contacts.</p>
<p>Beachte zunächst, dass Delta Chat ein privater Messenger ist.
Es gibt keine öffentliches Verzeichnis, du entscheiden selbst über deine Kontakte.</p>
<ul>
<li>Wenn du <strong>persönlich</strong> mit deinen Freunden oder Familie zusammen bist,
tippe auf das <strong>QR-Code</strong>-Symbol <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
auf dem Hauptbildschirm.<br />
Bitte deinen Chatpartner den QR-Code mit Delta Chat zu <strong>scannen</strong>.</li>
</ul>
<p>Für eine Kontaktaufnahme <strong>aus der Ferne</strong>, klicke im selben Bildschirm auf “Kopieren” oder “Teilen” und sende den <strong>Einladungslink</strong> über einen anderen privaten Chat.</p>
<p>Wartet nun, bis die Verbindung hergestellt ist.</p>
<ul>
<li>
<p>If you are <strong>face to face</strong> with your friend or family,
tap the <strong>QR Code</strong> icon <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
on the main screen.<br />
Ask your chat partner to <strong>scan</strong> the QR image
with their Delta Chat app.</p>
<p>Wenn beide Seiten online sind, wird ein Chat angezeigt und ihr könnt sicher miteinander chatten.</p>
</li>
<li>
<p>For a <strong>remote</strong> contact setup,
from the same screen,
click “Copy” or “Share” and send the <strong>invite link</strong>
through another private chat.</p>
<p>Wenn eine Seite offline ist oder eine schlechte Netzwerkverbindung hat,
wird die Chat-Funktion verzögert, bis die Verbindung wiederhergestellt ist.</p>
</li>
</ul>
<p>Now wait while connection gets established.</p>
<ul>
<li>
<p>If both sides are online, they will soon see a chat
and can start messaging securely.</p>
</li>
<li>
<p>If one side is offline or in bad network,
the ability to chat is delayed until connectivity is restored.</p>
</li>
</ul>
<p>Congratulations!
You now will automatically use <a href="#e2ee">end-to-end encryption</a> with this contact.
If you add each other to <a href="#groups">groups</a>, end-to-end encryption will be established among all members.</p>
<p>Glückwunsch!
Du verwendest jetzt automatisch eine <a href="#e2ee">Ende-zu-Ende-Verschlüsselung</a>
mit deinem Kontakt.
Wenn man sich gegenseitig zu <a href="#groups">Gruppen</a> hinzufügt,
wird eine Ende-zu-Ende-Verschlüsselung zwischen allen Mitgliedern eingerichtet.</p>
<h3 id="warum-ist-ein-chat-als-anfrage-markiert">
@@ -207,11 +197,11 @@ receive messages from this person, consider <strong>blocking</strong> them.</p>
</h3>
<p>Attach the first contact to the chat of the second using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → Contact</strong>.
You can also add a little introduction message.</p>
<p>Füge den ersten Kontakt zum Chat des zweiten Kontakts hinzu, indem du auf <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Anhängen → Kontakt</strong> klickst.
Du kannst auch eine kurze Nachricht hinzufügen.</p>
<p>The second contact will receive a <strong>card</strong> then
and can tap it to start chatting with the first contact.</p>
<p>Der zweite Kontakt erhält dann die <strong>Kontaktdaten</strong> und
kann darauf tippen, um mit dem ersten Kontakt zu chatten.</p>
<h3 id="unterstützt-delta-chat-bilder-videos-und-dateianhänge">
@@ -431,9 +421,7 @@ als auch in den Apps selbst gelöscht.</p>
böswillige Chatpartner können Fotos machen,
oder auf andere Weise Nachrichten vor dem Löschen speichern, kopieren oder weiterleiten.</p>
<p>Apart from that,
if one chat partner uninstalls Delta Chat,
the (anyway encrypted) messages may take longer to get deleted from their server.</p>
<p>Abgesehen davon, wenn ein Chat-Partner Delta Chat deinstalliert, kann es länger dauern, bis die (ohnehin verschlüsselten) Nachrichten vom Server gelöscht werden.</p>
<h3 id="delold">
@@ -451,7 +439,7 @@ the (anyway encrypted) messages may take longer to get deleted from their server
<h3 id="remove-account">
How can I delete my chat profile? <a href="#remove-account" class="anchor"></a>
Wie kann ich mein Chat-Profil löschen? <a href="#remove-account" class="anchor"></a>
</h3>
@@ -470,7 +458,7 @@ or the respective page from your chosen <a href="https://chatmail.at/relays">3rd
<h2 id="groups">
Groups <a href="#groups" class="anchor"></a>
Gruppen <a href="#groups" class="anchor"></a>
</h2>
@@ -502,7 +490,7 @@ and <a href="#edit">delete their own messages</a> from all members devices.</
<h3 id="addmembers">
Add and remove members <a href="#addmembers" class="anchor"></a>
Mitglieder hinzufügen und entfernen <a href="#addmembers" class="anchor"></a>
</h3>
@@ -562,10 +550,10 @@ Wenn du der Gruppe später erneut beitreten möchtest, bitten ein anderes Gruppe
</li>
</ul>
<h3 id="cloning-a-group">
<h3 id="eine-gruppe-klonen">
Cloning a group <a href="#cloning-a-group" class="anchor"></a>
Eine Gruppe klonen <a href="#eine-gruppe-klonen" class="anchor"></a>
</h3>
@@ -589,7 +577,7 @@ which continues to work as before.</p>
<h2 id="webxdc">
In-chat apps <a href="#webxdc" class="anchor"></a>
In-Chat-Apps <a href="#webxdc" class="anchor"></a>
</h2>
@@ -597,10 +585,10 @@ which continues to work as before.</p>
<p>You can send apps to a chat - games, editors, polls and other tools.
This makes Delta Chat a truly extensible messenger.</p>
<h3 id="where-can-i-get-in-chat-apps">
<h3 id="wo-bekomme-ich-in-chat-apps">
Where can I get in-chat apps? <a href="#where-can-i-get-in-chat-apps" class="anchor"></a>
Wo bekomme ich In-Chat-Apps? <a href="#wo-bekomme-ich-in-chat-apps" class="anchor"></a>
</h3>
@@ -614,10 +602,10 @@ This makes Delta Chat a truly extensible messenger.</p>
</li>
</ul>
<h3 id="how-private-are-in-chat-apps">
<h3 id="wie-privat-sind-in-chat-apps">
How private are in-chat apps? <a href="#how-private-are-in-chat-apps" class="anchor"></a>
Wie privat sind In-Chat-Apps? <a href="#wie-privat-sind-in-chat-apps" class="anchor"></a>
</h3>
@@ -627,7 +615,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -643,7 +631,7 @@ trust the people you chat with, you can trust the in-chat app as well.</p>
<h3 id="create-xdc">
How can I create my own in-chat apps? <a href="#create-xdc" class="anchor"></a>
Wie kann mich meine eigene In-Chat-Apps erstellen? <a href="#create-xdc" class="anchor"></a>
</h3>
@@ -910,7 +898,7 @@ versuche, einen <strong>Mobilen Hotspot</strong> auf einem Gerät zu öffnen und
<ul>
<li>Auf dem alten Gerät, gehe zu “Einstellungen → Chats und Medien → Chats auf externem Speicher speichern”. Gib deine PIN, dein Muster oder dein Passwort zum Entsperren des Bildschirms ein. Anschließend kannst du auf “Backup starten” klicken. Dadurch wird die Backup-Datei auf deinem Gerät gespeichert. Jetzt musst du sie auf das andere Gerät übertragen.</li>
<li>Auf dem neuen Gerät, auf dem Anmeldebildschirm, wählen, anstatt sich bei Ihrem E-Mail-Konto anzumelden, “Wiederherstellen aus Backup”. Nach dem Import sollten Ihre Unterhaltungen, Verschlüsselungsschlüssel und Medien auf das neue Gerät kopiert sein.
<li>Auf dem neuen Gerät, auf dem Anmeldebildschirm, wähle “Ich habe bereits ein Profil” und dann “Wiederherstellen aus Backup”. Nach dem Import sind deine Chats, Medien und Einstellungen auf das neue Gerät kopiert.
<ul>
<li><strong>Wenn du iOS verwendest</strong> und auf Schwierigkeiten stößt, hilft dir vielleicht <a href="https://support.delta.chat/t/import-backup-to-ios/1628">diese Anleitung</a>.</li>
</ul>
@@ -940,18 +928,18 @@ versuche, einen <strong>Mobilen Hotspot</strong> auf einem Gerät zu öffnen und
</h2>
<h3 id="experimental-features">
<h3 id="experimentelle-features">
Experimental Features <a href="#experimental-features" class="anchor"></a>
Experimentelle Features <a href="#experimentelle-features" class="anchor"></a>
</h3>
<p>At <strong>Settings → Advanced → Experimental Features</strong>
you can try out features we are working on.</p>
<p>Unter <strong>Einstellungen → Erweitert → Experimentelle Features</strong>
kannst du unfertige Features ausprobieren, an denen gearbeitet wird.</p>
<p>The features may be <strong>unstable</strong> and may be <strong>changed or removed</strong>.</p>
<p>Die Features können <strong>instabil</strong> sein und <strong>geändert oder entfernt</strong> werden.</p>
<p>You can find more information
and give feedback in the <a href="https://support.delta.chat">Forum</a>.</p>
@@ -959,7 +947,7 @@ and give feedback in the <a href="https://support.delta.chat">Forum</a>.</p>
<h3 id="statssending">
What is “Send statistics to Delta Chats developers”? <a href="#statssending" class="anchor"></a>
Was ist “Statistik an Delta Chat Entwickler senden”? <a href="#statssending" class="anchor"></a>
</h3>
@@ -984,10 +972,10 @@ weekly statistics will be automatically sent to a bot.</p>
<p>We will <em>not</em> collect any personally identifiable information about you.</p>
<h3 id="can-i-use-a-classic-email-address-with-delta-chat">
<h3 id="kann-ich-eine-klassische-e-mail-adresse-mit-delta-chat-verwenden">
Can I use a classic email address with Delta Chat? <a href="#can-i-use-a-classic-email-address-with-delta-chat" class="anchor"></a>
Kann ich eine klassische E-Mail-Adresse mit Delta Chat verwenden? <a href="#kann-ich-eine-klassische-e-mail-adresse-mit-delta-chat-verwenden" class="anchor"></a>
</h3>
@@ -1004,7 +992,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1016,7 +1004,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
Wie kann ich ein Chat-Profil mit einer klassischen E-Mail-Adresse als Relay konfigurieren? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1025,7 +1013,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1098,7 +1086,7 @@ ermöglicht es den Empfängern, eine Ende-zu-Ende-Verschlüsselung mit dem Konta
<h3 id="whene2e">
How can I know if messages are end-to-end encrypted? <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>
@@ -1106,10 +1094,10 @@ ermöglicht es den Empfängern, eine Ende-zu-Ende-Verschlüsselung mit dem Konta
<p>Alle Nachrichten in Delta Chat sind <strong>standardmäßig Ende-zu-Ende-verschlüsselt</strong>.
Seit der Veröffentlichung von Delta Chat Version 2 (Juli 2025) gibt es keine Schlösser oder ähnliche Markierungen mehr an EndezuEnde-verschlüsselten Nachrichten.</p>
<h3 id="can-i-still-receive-or-send-messages-without-end-to-end-encryption">
<h3 id="kann-ich-nachrichten-ohne-ende-zu-ende-verschlüsselung-empfangen-oder-senden">
Can I still receive or send messages without end-to-end encryption? <a href="#can-i-still-receive-or-send-messages-without-end-to-end-encryption" class="anchor"></a>
Kann ich Nachrichten ohne Ende-zu-Ende-Verschlüsselung empfangen oder senden? <a href="#kann-ich-nachrichten-ohne-ende-zu-ende-verschlüsselung-empfangen-oder-senden" class="anchor"></a>
</h3>
@@ -1376,11 +1364,12 @@ ist die Verbindung sicher.</p>
<p>Nein.</p>
<p>Delta Chat erzeugt sichere OpenPGP-Schlüssel gemäß der Autocrypt-Spezifikation 1.1.
Du kannst deinen privaten Schlüssel exportieren, aber du kannst keinen weiteren privaten Schlüssel importieren.</p>
<p>Im Allgemeinen empfehlen wir, die Schlüsselverwaltung nicht manuell vorzunehmen, und bieten dies auch nicht an.
Wir wollen sicherstellen, dass sich Sicherheitsaudits auf wenige, bewährte kryptographische Algorithmen konzentrieren können - statt einen Strauß möglicher Algorithmen, die mit OpenPGP erlaubt sind.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
@@ -1465,8 +1454,7 @@ e.g. you need to grant camera permission if you want to <a href="#howtoe2ee">sca
<p>Falls nicht verfügbar, verwende den <strong>Mirror</strong> auf <a href="https://deltachat.github.io/deltachat-pages">https://deltachat.github.io/deltachat-pages</a></p>
</li>
<li>
<p>Open one of the following <strong>app stores and search for “Delta Chat:</strong>
Google Play Store, F-Droid, Huawei App Gallery, iOS and macOS App Store, Microsoft Store</p>
<p>Öffne einen der folgenden <strong>App-Stores und suchen Sie nach „Delta Chat:</strong> Google Play Store, F-Droid, Huawei App Gallery, iOS und macOS App Store, Microsoft Store</p>
</li>
<li>
<p>Im <strong>Paketmanager</strong> Ihrer Linux-Distribution nachschauen</p>
@@ -1501,15 +1489,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>In 2021 we received further EU funding for two Next-Generation-Internet
proposals, namely for <a href="https://dapsi.ngi.eu/hall-of-fame/eppd/">EPPD - email provider portability directory</a> (~97K EUR) and <a href="https://nlnet.nl/project/EmailPorting/">AEAP - email address porting</a> (~90K EUR) which resulted in better multi-profile support, improved QR-code contact and group setups and many networking improvements on all platforms.</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>From End 2021 till March 2023 we received <em>Internet Freedom</em> funding (500K USD) from the
U.S. Bureau of Democracy, Human Rights and Labor (DRL).
This funding supported our long-running goals to make Delta Chat more usable
and compatible with a wide range of email servers world-wide, and more resilient and secure
in places often affected by internet censorship and shutdowns.</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
Binary file not shown.

Before

Width:  |  Height:  |  Size: 16 KiB

+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#im-interested-in-the-technical-details-can-you-tell-me-more">Im interested in the technical details. Can you tell me more?</a></li>
</ul>
@@ -650,7 +650,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1057,7 +1057,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1069,7 +1069,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1078,7 +1078,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1437,12 +1437,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#estoy-interesado-en-los-detalles-técnicos-pueden-decirme-más">Estoy interesado en los detalles técnicos. ¿Pueden decirme más?</a></li>
</ul>
@@ -648,7 +648,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1055,7 +1055,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1067,7 +1067,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1076,7 +1076,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1428,12 +1428,12 @@ in collaboration with other OpenPGP implementers.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#les-détails-techniques-mintéressent-pouvez-vous-men-dire-plus-">Les détails techniques mintéressent. Pouvez-vous men dire plus ?</a></li>
</ul>
@@ -641,7 +641,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1042,7 +1042,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1054,7 +1054,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1063,7 +1063,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1422,12 +1422,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#im-interested-in-the-technical-details-can-you-tell-me-more">Im interested in the technical details. Can you tell me more?</a></li>
</ul>
@@ -650,7 +650,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1057,7 +1057,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1069,7 +1069,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1078,7 +1078,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1437,12 +1437,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+54 -54
View File
@@ -19,20 +19,20 @@
<li><a href="#remove-account">Come posso eliminare il mio profilo chat?</a></li>
</ul>
</li>
<li><a href="#gruppi">Gruppi</a>
<li><a href="#groups">Gruppi</a>
<ul>
<li><a href="#creazione-di-un-gruppo">Creazione di un gruppo</a></li>
<li><a href="#addmembers">Aggiungi e rimuovi membri</a></li>
<li><a href="#mi-sono-cancellato-per-sbaglio">Mi sono cancellato per sbaglio.</a></li>
<li><a href="#non-desidero-più-ricevere-i-messaggi-di-un-gruppo">Non desidero più ricevere i messaggi di un gruppo.</a></li>
<li><a href="#cloning-a-group">Cloning a group</a></li>
<li><a href="#clonazione-di-un-gruppo">Clonazione di un gruppo</a></li>
</ul>
</li>
<li><a href="#webxdc">In-chat apps</a>
<li><a href="#webxdc">Apps in chat</a>
<ul>
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
<li><a href="#how-private-are-in-chat-apps">How private are in-chat apps?</a></li>
<li><a href="#create-xdc">How can I create my own in-chat apps?</a></li>
<li><a href="#dove-posso-trovare-le-apps-in-chat">Dove posso trovare le apps in chat?</a></li>
<li><a href="#quanto-sono-private-le-apps-di-chat">Quanto sono private le apps di chat?</a></li>
<li><a href="#create-xdc">Come posso creare le mie app di chat?</a></li>
</ul>
</li>
<li><a href="#instant-delivery">Consegna messaggi istantanei e Notifiche Push</a>
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#vorrei-gestire-il-mio-server-per-delta-chat-cosa-mi-consigliate">Vorrei gestire il mio server per Delta Chat. Cosa mi consigliate?</a></li>
<li><a href="#sono-interessato-ai-dettagli-tecnici-mi-puoi-dire-di-più">Sono interessato ai dettagli tecnici. Mi puoi dire di più?</a></li>
</ul>
@@ -489,10 +489,10 @@ Ciò attiverà comunque leliminazione automatica di tutti i dati di indirizzo
Per maggiori informazioni, consulta <a href="https://nine.testrun.org/info.html#account-deletion">nine.testrun.org cancellazione dellindirizzo</a>
o la pagina corrispondente del <a href="https://chatmail.at/relays">server chatmail di 3e parti</a> da te scelto.</p>
<h2 id="gruppi">
<h2 id="groups">
Gruppi <a href="#gruppi" class="anchor"></a>
Gruppi <a href="#groups" class="anchor"></a>
</h2>
@@ -535,23 +535,23 @@ ed <a href="#edit">eliminare i propri messaggi</a> dai dispositivi di tutti i me
Per questo motivo, tutti possono eliminare qualsiasi membro o aggiungerne di nuovi.</p>
</li>
<li>
<p>To <strong>add or delete members</strong>, tap the group name in the chat and select the member to add or remove.</p>
<p>Per <strong>aggiungere o eliminare membri</strong>, tocca il nome del gruppo nella chat e seleziona il membro da aggiungere o rimuovere.</p>
</li>
<li>
<p>If the member is not yet in your contact list, but <strong>face to face</strong> with you,
from the same screen, show a <strong>QR code</strong>.<br />
Ask your chat partner to <strong>scan</strong> the QR image with their Delta Chat app by tapping
<img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> on the main screen.</p>
<p>Se il membro non è ancora nella tua lista contatti, ma è <strong>faccia a faccia</strong> con te,
dalla stessa schermata, mostra un <strong>codice QR</strong>.
Chiedi al tuo interlocutore di <strong>scansionare</strong> limmagine QR con la sua app Delta Chat toccando
<img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> nella schermata principale.</p>
</li>
<li>
<p>For a <strong>remote</strong> member addition,
click “Copy” orShare” and send the <strong>invite link</strong>
through another private chat to the new member.</p>
<p>Per aggiungere un membro <strong>da remoto</strong>,
clicca su “Copia” o “Condividi” e invia il <strong>link di invito</strong>
tramite unaltra chat privata al nuovo membro.</p>
</li>
</ul>
<p>QR code and invite link can be used to add several members.
However, since groups are <a href="#groups">meant for trusted people</a>, avoid sharing them publicly.</p>
<p>Il codice QR e il link di invito possono essere utilizzati per aggiungere più membri.
Tuttavia, poiché i gruppi sono <a href="#groups">destinati a persone fidate</a>, evita di condividerli pubblicamente.</p>
<h3 id="mi-sono-cancellato-per-sbaglio">
@@ -585,88 +585,88 @@ puoi ancora scrivere, ma non viene più notificato alcun nuovo messaggio.</p>
</li>
</ul>
<h3 id="cloning-a-group">
<h3 id="clonazione-di-un-gruppo">
Cloning a group <a href="#cloning-a-group" class="anchor"></a>
Clonazione di un gruppo <a href="#clonazione-di-un-gruppo" class="anchor"></a>
</h3>
<p>You can duplicate a group to start a separate discussion
or to exclude members without them noticing.</p>
<p>Puoi duplicare un gruppo per avviare una discussione separata
o per escludere membri senza che se ne accorgano.</p>
<ul>
<li>
<p>Open the group profile and tap <strong>Clone Chat</strong> (Android/iOS),
or right-click the group in the chat list (Desktop).</p>
<p>Apri il profilo del gruppo e tocca <strong>Clona Chat</strong> (Android/iOS),
oppure fai clic con il pulsante destro del mouse sul gruppo nellelenco delle chat (Desktop).</p>
</li>
<li>
<p>Set a new name, choose an avatar, and adjust the member list if needed.</p>
<p>Imposta un nuovo nome, scegli un avatar e modifica lelenco dei membri, se necessario.</p>
</li>
</ul>
<p>The new group is <strong>fully independent</strong> from the original,
which continues to work as before.</p>
<p>Il nuovo gruppo è <strong>completamente indipendente</strong> dalloriginale,
che continua a funzionare come prima.</p>
<h2 id="webxdc">
In-chat apps <a href="#webxdc" class="anchor"></a>
Apps in chat <a href="#webxdc" class="anchor"></a>
</h2>
<p>You can send apps to a chat - games, editors, polls and other tools.
This makes Delta Chat a truly extensible messenger.</p>
<p>È possibile inviare apps a una chat: giochi, editor, sondaggi e altri strumenti.
Questo rende Delta Chat un servizio di messaggistica davvero espandibile.</p>
<h3 id="where-can-i-get-in-chat-apps">
<h3 id="dove-posso-trovare-le-apps-in-chat">
Where can I get in-chat apps? <a href="#where-can-i-get-in-chat-apps" class="anchor"></a>
Dove posso trovare le apps in chat? <a href="#dove-posso-trovare-le-apps-in-chat" class="anchor"></a>
</h3>
<ul>
<li>
<p>In a chat, using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → Apps</strong></p>
<p>In una chat, utilizzando <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Pulsante Allegato → Apps</strong></p>
</li>
<li>
<p>You can also <a href="#create-xdc">create your own app</a> and attach it using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → File</strong></p>
<p>Puoi anche <a href="#create-xdc">creare la tua app</a> e allegarla usando <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Pulsante Allegato → File</strong></p>
</li>
</ul>
<h3 id="how-private-are-in-chat-apps">
<h3 id="quanto-sono-private-le-apps-di-chat">
How private are in-chat apps? <a href="#how-private-are-in-chat-apps" class="anchor"></a>
Quanto sono private le apps di chat? <a href="#quanto-sono-private-le-apps-di-chat" class="anchor"></a>
</h3>
<ul>
<li>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
<p>Le apps di chat non possono inviare dati a Internet né scaricare nulla.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
<p>Unapp in-chat può scambiare dati solo allinterno di una chat Delta Chat, con le sue
copie sui dispositivi dei tuoi interlocutori. A parte questo, è completamente
isolata da Internet.</p>
</li>
<li>
<p>The privacy an in-chat app offers is the privacy of your chat - as long as you
trust the people you chat with, you can trust the in-chat app as well.</p>
<p>La privacy offerta da unapp di chat è la privacy della tua chat: finché
ti fidi delle persone con cui chatti, puoi fidarti anche dellapp di chat.</p>
</li>
<li>
<p>This also means: Just like for web links, do not open apps from untrusted contacts.</p>
<p>questo significa anche: proprio come per i link web, non aprire app provenienti da contatti non attendibili.</p>
</li>
</ul>
<h3 id="create-xdc">
How can I create my own in-chat apps? <a href="#create-xdc" class="anchor"></a>
Come posso creare le mie app di chat? <a href="#create-xdc" class="anchor"></a>
</h3>
@@ -1053,7 +1053,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1065,7 +1065,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1074,7 +1074,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1431,12 +1431,12 @@ la connessione è sicura.</p>
<p>No.</p>
<p>Delta Chat genera chiavi OpenPGP sicure in conformità alle specifiche di Autocrypt 1.1.
Puoi esportare le tue chiavi private ma non puoi importare chiavi private aggiuntive.</p>
<p>In generale, non raccomandiamo o proponiamo agli utenti di gestire manualmente le chiavi.
Noi vogliamo assicurare che gli audits di sicurezza si possano focalizzare su pochi algoritmi crittografici comprovati
invece che sullintera estensione dei possibili algoritmi consentiti con OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
Binary file not shown.

Before

Width:  |  Height:  |  Size: 778 B

+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#ik-wil-graag-meer-weten-over-de-gebruikte-technieken-waar-kan-ik-meer-informatie-vinden">Ik wil graag meer weten over de gebruikte technieken. Waar kan ik meer informatie vinden?</a></li>
</ul>
@@ -649,7 +649,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1055,7 +1055,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1067,7 +1067,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1076,7 +1076,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1435,12 +1435,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+11 -8
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#chcę-zarządzać-własnym-serwerem-dla-delta-chat-co-polecacie">Chcę zarządzać własnym serwerem dla Delta Chat. Co polecacie?</a></li>
<li><a href="#interesują-mnie-szczegóły-techniczne-możesz-powiedzieć-mi-coś-więcej">Interesują mnie szczegóły techniczne. Możesz powiedzieć mi coś więcej?</a></li>
</ul>
@@ -622,7 +622,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -972,7 +972,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -984,7 +984,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -993,7 +993,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1278,9 +1278,12 @@ but an implementation has not been agreed as a priority yet.</p>
<p>Nie.</p>
<p>Delta Chat generuje bezpieczne klucze OpenPGP zgodnie ze specyfikacją Autocrypt 1.1. Możesz wyeksportować swój prywatny klucz, ale nie możesz zaimportować dodatkowych kluczy prywatnych.</p>
<p>Generalnie nie zalecamy ani nie oferujemy użytkownikom wykonywania ręcznego zarządzania kluczami. Chcemy się upewnić, że audyty bezpieczeństwa mogą skupić się na kilku sprawdzonych algorytmach kryptograficznych, a nie na pełnym zakresie możliwych algorytmów dozwolonych w OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#estou-interessado-nos-detalhes-técnicos-pode-me-dizer-mais">Estou interessado nos detalhes técnicos. Pode me dizer mais?</a></li>
</ul>
@@ -646,7 +646,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1053,7 +1053,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1065,7 +1065,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1074,7 +1074,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1433,12 +1433,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+212 -213
View File
@@ -2,13 +2,13 @@
<html lang="ru"><head><meta charset="UTF-8" /><meta name="viewport" content="initial-scale=1.0" /><link rel="stylesheet" href="../help.css" /></head><body><ul id="top">
<li><a href="#что-такое-delta-chat">Что такое Delta Chat?</a>
<ul>
<li><a href="#howtoe2ee">How can I find people to chat with?</a></li>
<li><a href="#why-is-a-chat-marked-as-request">Why is a chat marked as “Request”?</a></li>
<li><a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other">How can I put two of my friends in contact with each other?</a></li>
<li><a href="#howtoe2ee">Как найти людей для общения?</a></li>
<li><a href="#почему-чат-помечен-как-запрос">Почему чат помечен как “Запрос”?</a></li>
<li><a href="#как-я-могу-связать-двух-своих-друзей-друг-с-другом">Как я могу связать двух своих друзей друг с другом?</a></li>
<li><a href="#поддерживает-ли-delta-chat-изображения-видео-и-другие-вложения">Поддерживает ли Delta Chat изображения, видео и другие вложения?</a></li>
<li><a href="#multiple-accounts">Что такое профили? Как я могу переключатся между ними?</a></li>
<li><a href="#кто-видит-изображение-моего-профиля">Кто видит изображение моего профиля?</a></li>
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
<li><a href="#signature">Могу ли я установить статус/подпись в Delta Chat?</a></li>
<li><a href="#что-означают-закрепить-отключить-уведомления-и-отправить-в-архив">Что означают: Закрепить, Отключить уведомления и Отправить в архив?</a></li>
<li><a href="#save">Как работают “Сохраненные сообщения”?</a></li>
<li><a href="#что-означает-зеленая-точка">Что означает зеленая точка?</a></li>
@@ -16,21 +16,21 @@
<li><a href="#edit">Исправление опечаток и удаление сообщений после отправки</a></li>
<li><a href="#ephemeralmsgs">Как работают исчезающие сообщения?</a></li>
<li><a href="#delold">Что произойдет, если я включу функцию “Удалять старые сообщения с устройства”?</a></li>
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
<li><a href="#remove-account">Как удалить свой профиль в чате?</a></li>
</ul>
</li>
<li><a href="#groups">Groups</a>
<li><a href="#groups">Группы</a>
<ul>
<li><a href="#создание-группы">Создание группы</a></li>
<li><a href="#addmembers">Add and remove members</a></li>
<li><a href="#addmembers">Добавление и удаление участников</a></li>
<li><a href="#я-случайно-удалил-самого-себя">Я случайно удалил самого себя.</a></li>
<li><a href="#я-больше-не-хочу-получать-сообщения-группы">Я больше не хочу получать сообщения группы.</a></li>
<li><a href="#cloning-a-group">Cloning a group</a></li>
<li><a href="#клонирование-группы">Клонирование группы</a></li>
</ul>
</li>
<li><a href="#webxdc">In-chat apps</a>
<li><a href="#webxdc">Встроенные приложения чата</a>
<ul>
<li><a href="#where-can-i-get-in-chat-apps">Where can I get in-chat apps?</a></li>
<li><a href="#где-можно-найти-встроенные-приложения">Где можно найти встроенные приложения?</a></li>
<li><a href="#насколько-конфиденциальны-приложения-внутри-чата">Насколько конфиденциальны приложения внутри чата?</a></li>
<li><a href="#create-xdc">Как создать собственные приложения внутри чата?</a></li>
</ul>
@@ -55,9 +55,9 @@
<li><a href="#расширенные">Расширенные</a>
<ul>
<li><a href="#экспериментальные-функции">Экспериментальные функции</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#statssending">Что означает “Отправлять статистику разработчикам Delta Chat”?</a></li>
<li><a href="#могу-ли-я-использовать-обычный-адрес-электронной-почты-с-delta-chat">Могу ли я использовать обычный адрес электронной почты с Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">Как настроить профиль чата с использованием классического адреса электронной почты в качестве транспорта?</a></li>
<li><a href="#я-хочу-управлять-своим-собственным-сервером-для-delta-chat-что-вы-посоветуете">Я хочу управлять своим собственным сервером для Delta Chat. Что вы посоветуете?</a></li>
<li><a href="#меня-интересуют-технические-детали-можете-рассказать-больше">Меня интересуют технические детали. Можете рассказать больше?</a></li>
</ul>
@@ -107,84 +107,84 @@
<ul>
<li>
<p>Instant creation of <strong>private chat profiles</strong>
with secure and interoperable <a href="https://chatmail.at/relays">chatmail relays</a>
that offer instant message delivery, and Push Notifications for iOS and Android devices.</p>
<p>Мгновенное создание <strong>приватных профилей чата</strong>
с безопасными и совместимыми <a href="https://chatmail.at/relays">релеями chatmail</a>
которые обеспечивают мгновенную доставку сообщений, а также Push-уведомления для устройств iOS и Android.</p>
</li>
<li>
<p>Pervasive <a href="#multiple-accounts">multi-profile</a> and
<a href="#multiclient">multi-device</a> support on all platforms
and between different <a href="https://chatmail.at/clients">chatmail apps</a>.</p>
<p>Повсеместная поддержка <a href="#multiple-accounts">мультипрофиля</a> и
поддержка <a href="#multiclient">multi-device</a> на всех платформах
и между различными приложениями <a href="https://chatmail.at/clients">chatmail</a>.</p>
</li>
<li>
<p>Interactive <a href="#webxdc">in-chat apps</a> for gaming and collaboration</p>
<p>Интерактивные <a href="#webxdc">приложения чата</a> для игр и совместной работы</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">Проверенное сквозное шифрование</a>
защита от сетевых и серверных атак.</p>
</li>
<li>
<p>Free and Open Source software, both app and server side,
built on <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Internet Standards</a>.</p>
<p>Бесплатное программное обеспечение с открытым исходным кодом, как на стороне приложений, так и на стороне сервера,
построенное на <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Интернет-стандартах</a>.</p>
</li>
</ul>
<h3 id="howtoe2ee">
How can I find people to chat with? <a href="#howtoe2ee" class="anchor"></a>
Как найти людей для общения? <a href="#howtoe2ee" class="anchor"></a>
</h3>
<p>First, note that Delta Chat is a private messenger.
There is no public discovery, <em>you</em> decide about your contacts.</p>
<p>Во-первых, обратите внимание, что Delta Chat — это приватный мессенджер.
Публичного поиска контактов нет, вы сами решаете, с кем общаться.</p>
<ul>
<li>
<p>If you are <strong>face to face</strong> with your friend or family,
tap the <strong>QR Code</strong> icon <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
on the main screen.<br />
Ask your chat partner to <strong>scan</strong> the QR image
with their Delta Chat app.</p>
<p>Если вы находитесь <strong>рядом</strong> с другом или членом семьи,
нажмите значок <strong>QR-код</strong> <img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" />
на главном экране.<br />
Попросите вашего собеседника <strong>отсканировать</strong> QR-код
с помощью приложения Delta Chat.</p>
</li>
<li>
<p>For a <strong>remote</strong> contact setup,
from the same screen,
click “Copy” or “Share” and send the <strong>invite link</strong>
through another private chat.</p>
<p>Для <strong>удалённой</strong> настройки контакта,
на том же экране,
нажмите “Копировать” или “Поделиться” и отправьте <strong>ссылку-приглашение</strong>
через другой приватный чат.</p>
</li>
</ul>
<p>Now wait while connection gets established.</p>
<p>Теперь подождите, пока устанавливается соединение.</p>
<ul>
<li>
<p>If both sides are online, they will soon see a chat
and can start messaging securely.</p>
<p>Если оба пользователя онлайн, вскоре они увидят чат
и смогут начать безопасное общение.</p>
</li>
<li>
<p>If one side is offline or in bad network,
the ability to chat is delayed until connectivity is restored.</p>
<p>Если один из пользователей не в сети или имеет плохое соединение,
возможность общаться появится после восстановления соединения.</p>
</li>
</ul>
<p>Congratulations!
You now will automatically use <a href="#e2ee">end-to-end encryption</a> with this contact.
If you add each other to <a href="#groups">groups</a>, end-to-end encryption will be established among all members.</p>
<p>Поздравляем!
Теперь вы будете автоматически использовать <a href="#e2ee">сквозное шифрование</a> с этим контактом.
Если вы добавите друг друга в <a href="#groups">группы</a>, сквозное шифрование будет установлено между всеми участниками.</p>
<h3 id="why-is-a-chat-marked-as-request">
<h3 id="почему-чат-помечен-как-запрос">
Why is a chat marked as “Request”? <a href="#why-is-a-chat-marked-as-request" class="anchor"></a>
Почему чат помечен как “Запрос”? <a href="#почему-чат-помечен-как-запрос" class="anchor"></a>
</h3>
<p>As being a private messenger,
only friends and family you <a href="#howtoe2ee">share your QR code or invite link with</a> can write to you.</p>
<p>Поскольку это приватный мессенджер,
писать вам могут только друзья и члены семьи, с которыми вы <a href="#howtoe2ee">поделились QR-кодом или ссылкой-приглашением.</a></p>
<p>Your friends may share your contact with other friends, this appears as a <strong>request</strong>.</p>
<p>Ваши друзья могут поделиться вашим контактом с другими друзьями, это отображается как <strong>запрос</strong>.</p>
<p>— Нужно <strong>принять</strong> запрос, прежде чем ответить.</p>
@@ -196,19 +196,19 @@ only friends and family you <a href="#howtoe2ee">share your QR code or invite li
получать сообщения от этого человека, подумайте о его <strong>блокировке</strong>.</li>
</ul>
<h3 id="how-can-i-put-two-of-my-friends-in-contact-with-each-other">
<h3 id="как-я-могу-связать-двух-своих-друзей-друг-с-другом">
How can I put two of my friends in contact with each other? <a href="#how-can-i-put-two-of-my-friends-in-contact-with-each-other" class="anchor"></a>
Как я могу связать двух своих друзей друг с другом? <a href="#как-я-могу-связать-двух-своих-друзей-друг-с-другом" class="anchor"></a>
</h3>
<p>Attach the first contact to the chat of the second using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → Contact</strong>.
You can also add a little introduction message.</p>
<p>Прикрепите первый контакт к чату второго используя кнопку <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Вложение → Контакт</strong>.
Вы также можете добавить небольшое вступительное сообщение.</p>
<p>The second contact will receive a <strong>card</strong> then
and can tap it to start chatting with the first contact.</p>
<p>Второй контакт получит <strong>карточку</strong>
на которую можно нажать, чтобы начать общение с первым контактом.</p>
<h3 id="поддерживает-ли-delta-chat-изображения-видео-и-другие-вложения">
@@ -220,8 +220,8 @@ and can tap it to start chatting with the first contact.</p>
<ul>
<li>
<p>Да. Images, videos, files, voice messages etc. can be sent using the <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment-</strong>
or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Voice Message</strong> buttons</p>
<p>Да. Изображения, видео, файлы, голосовые сообщения и т.д. можно отправлять с помощью кнопок <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Вложение</strong>
или <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png" alt="Microphone" /> <strong>Голосовое сообщение</strong>.</p>
</li>
<li>
<p>Для лучшей производительности изображения по умолчанию оптимизируются и отправляются в меньшем размере, но вы можете отправить их как “файл”, чтобы сохранить оригинал.</p>
@@ -236,16 +236,16 @@ or <img style="vertical-align:middle; width:0.8em; margin:1px" src="../mic.png"
</h3>
<p>A profile is <strong>a name, a picture</strong> and some additional information for encrypting messages.
A profile lives on your device(s) only
and uses the server only to relay messages.</p>
<p>Профиль - это <strong>имя, фотография</strong> и некоторая дополнительная информация для шифрования сообщений.
Профиль живет только на вашем устройстве (устройствах)
и использует сервер только для передачи сообщений.</p>
<p>При первой установке Delta Chat создаётся первый профиль.</p>
<p>Позже, вы можете нажать на изображение вашего профиля в верхнем левом углу, чтобы <strong>Добавить профили</strong>
или <strong>Сменить профили</strong>.</p>
<p>You may want to use separate profiles for political, family or work related activities.</p>
<p>Возможно, вы захотите использовать разные профили для политической деятельности, общения с семьёй или работы.</p>
<p>Вы также можете изучить <a href="#multiclient">как использовать один и тот же профиль на нескольких устройствах</a>.</p>
@@ -271,15 +271,15 @@ and uses the server only to relay messages.</p>
<h3 id="signature">
Can I set a Bio/Status with Delta Chat? <a href="#signature" class="anchor"></a>
Могу ли я установить статус/подпись в Delta Chat? <a href="#signature" class="anchor"></a>
</h3>
<p>Yes,
you can do so under <strong>Settings → Profile → Bio</strong>.
Once you sent a message to a contact,
they will see it when they view your contact details.</p>
<p>Да,
вы можете сделать это в разделе <strong>Настройки → Профиль → О себе</strong>.
После отправки сообщения контакту,
они увидят его при просмотре ваших контактных данных.</p>
<h3 id="что-означают-закрепить-отключить-уведомления-и-отправить-в-архив">
@@ -353,13 +353,12 @@ they will see it when they view your contact details.</p>
</h3>
<p>You can sometimes see a <strong>green dot</strong> <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" />
next to the avatar of a contact.
It means they were <strong>recently seen by you</strong> in the last 10 minutes,
e.g. because they messaged you or sent a read receipt.</p>
<p>Иногда рядом с аватаром контакта можно увидеть <strong>зелёную точку</strong>. <img style="vertical-align:middle; width:1.2em; margin:1px" src="../green-dot.png" alt="" />
Это означает, что вы <strong>недавно видели</strong> этого человека в течение последних 10 минут,
например, потому что он вам написал или отправил подтверждение прочтения.</p>
<p>So this is not a real time online status
and others will as well not always see that you are “online”.</p>
<p>Таким образом, это не индикатор онлайн-статуса в реальном времени
и другие пользователи не всегда будут видеть, что вы “онлайн”.</p>
<h3 id="что-означают-галочки-рядом-с-исходящими-сообщениями">
@@ -371,21 +370,21 @@ and others will as well not always see that you are “online”.</p>
<ul>
<li>
<p><strong>One tick</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick1.png" alt="" />
means that the message was sent successfully to your provider.</p>
<p><strong>Одна галочка</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick1.png" alt="" />
означает, что сообщение было успешно отправлено вашему провайдеру.</p>
</li>
<li>
<p><strong>Two ticks</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick2.png" alt="" />
mean that at least one recipients device
reported back to having received the message.</p>
<p><strong>Две галочки</strong> <img style="vertical-align:middle; width:1.5em; margin:1px" src="../tick2.png" alt="" />
означают, что по крайней мере одно устройство получателя
сообщило об успешном получении сообщения.</p>
</li>
<li>
<p>Recipients may have disabled read-receipts,
so even if you see only one tick, the message may have been read.</p>
<p>Получатели могли отключить подтверждения прочтения,
поэтому даже если вы видите только одну галочку, сообщение могло быть прочитано.</p>
</li>
<li>
<p>The other way round, two ticks do not automatically mean
that a human has read or understood the message ;)</p>
<p>И наоборот, две галочки не обязательно означают
что человек прочитал или понял сообщение ;)</p>
</li>
</ul>
@@ -430,24 +429,24 @@ that a human has read or understood the message ;)</p>
выбрав временной интервал
от 5 минут до 1 года.</p>
<p>Until the setting is turned off again,
each chat members Delta Chat app takes care
of deleting the messages
after the selected time span.
The time span begins
when the receiver first sees the message in Delta Chat.
The messages are deleted both,
on the servers,
and in the apps itself.</p>
<p>Пока эта настройка не будет отключена,
приложение Delta Chat каждого участника чата позаботится
об удалении сообщений
по истечении выбранного периода времени.
Отсчёт времени начинается
с момента первого просмотра сообщения получателем в Delta Chat.
Сообщения будут удалены
как на серверах,
так и в самих приложениях.</p>
<p>Обратите внимание, что на исчезающие сообщения можно полагаться
только до тех пор, пока вы доверяете своим собеседникам;
злонамеренные собеседники могут делать фотографии,
или иным образом сохранить, скопировать или переслать сообщения перед удалением.</p>
<p>Apart from that,
if one chat partner uninstalls Delta Chat,
the (anyway encrypted) messages may take longer to get deleted from their server.</p>
<p>Кроме того,
если один из собеседников удалит Delta Chat,
(зашифрованные) сообщения могут дольше оставаться на сервере перед удалением.</p>
<h3 id="delold">
@@ -468,39 +467,39 @@ the (anyway encrypted) messages may take longer to get deleted from their server
<h3 id="remove-account">
How can I delete my chat profile? <a href="#remove-account" class="anchor"></a>
Как удалить свой профиль в чате? <a href="#remove-account" class="anchor"></a>
</h3>
<p>If you are using more than one chat profile,
you can remove single ones in the top profile switcher menu (on Android and iOS),
or in the sidebar with a right click (in the Desktop app).
Chat profiles are only removed on the device where deletion was triggered.
Chat profiles on other devices will continue to fully function.</p>
<p>Если вы используете несколько профилей чата,
вы можете удалить отдельные из них в верхнем переключателе профилей (на Android и iOS),
или в боковой панели щелчком правой кнопкой мыши (в настольном приложении).
Профили чата удаляются только с устройства, на котором была запущена операция удаления.
Профили чата на других устройствах будут продолжать полностью функционировать.</p>
<p>If you use a single default chat profile you can simply uninstall the app.
This will still automatically trigger deletion of all associated address data on the chatmail server.
For more info, please refer to <a href="https://nine.testrun.org/info.html#account-deletion">nine.testrun.org address-deletion</a>
or the respective page from your chosen <a href="https://chatmail.at/relays">3rd party chatmail server</a>.</p>
<p>Если вы используете один профиль чата по умолчанию, вы можете просто удалить приложение.
Это автоматически инициирует удаление всех связанных данных об адресе на сервере chatmail.
Подробную информацию смотрите на странице <a href="https://nine.testrun.org/info.html#account-deletion">nine.testrun.org address-deletion</a>
или на соответствующей странице выбранного вами <a href="https://chatmail.at/relays">стороннего сервера chatmail</a>.</p>
<h2 id="groups">
Groups <a href="#groups" class="anchor"></a>
Группы <a href="#groups" class="anchor"></a>
</h2>
<p>Groups let several people chat together privately with <strong>equal rights</strong>.</p>
<p>Группы позволяют нескольким пользователям общаться друг с другом конфиденциально <strong>на равных правах</strong>.</p>
<p>Anyone can
change the group name or avatar,
<a href="#addmembers">add or remove members</a>,
set <a href="#ephemeralmsgs">disappearing messages</a>,
and <a href="#edit">delete their own messages</a> from all members devices.</p>
<p>Любой может
изменить название группы или аватар,
<a href="#addmembers">добавить или удалить участников</a>,
включить <a href="#ephemeralmsgs">исчезающие сообщения</a>,
и <a href="#edit">удалять собственные сообщения</a> со всех устройств участников.</p>
<p>Because all members have the same rights, groups work best among <strong>trusted friends and family</strong>.</p>
<p>Поскольку все участники имеют одинаковые права, группы лучше всего подходят для общения с <strong>проверенными друзьями и семьёй</strong>.</p>
<h3 id="создание-группы">
@@ -519,34 +518,34 @@ and <a href="#edit">delete their own messages</a> from all members devices.</
<h3 id="addmembers">
Add and remove members <a href="#addmembers" class="anchor"></a>
Добавление и удаление участников <a href="#addmembers" class="anchor"></a>
</h3>
<ul>
<li>
<p>All group members have the <strong>same rights</strong>.
For this reason, everyone can delete any member or add new ones.</p>
<p>У всех участников группы <strong>одинаковые права</strong>.
Поэтому каждый может удалить любого участника или добавить новых.</p>
</li>
<li>
<p>To <strong>add or delete members</strong>, tap the group name in the chat and select the member to add or remove.</p>
<p>Чтобы <strong>добавлять или удалять участников</strong>, коснитесь названия группы в чате и выберите участника, которого нужно добавить или удалить.</p>
</li>
<li>
<p>If the member is not yet in your contact list, but <strong>face to face</strong> with you,
from the same screen, show a <strong>QR code</strong>.<br />
Ask your chat partner to <strong>scan</strong> the QR image with their Delta Chat app by tapping
<img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> on the main screen.</p>
<p>Если участника еще нет в вашем списке контактов, но он находится с <strong>вами лично</strong>,
на том же экране покажите <strong>QR-код</strong>.<br />
Попросите его <strong>отсканировать</strong> QR-код приложением Delta Chat, нажав
<img style="vertical-align:middle; height:1.3em; margin:1px" src="../qr-icon.png" /> на главном экране.</p>
</li>
<li>
<p>For a <strong>remote</strong> member addition,
click “Copy” or “Share” and send the <strong>invite link</strong>
through another private chat to the new member.</p>
<p>Для <strong>удалённого</strong> добавления участника,
нажмите “Копировать” или “Поделиться” и отправьте <strong>ссылку-приглашение</strong>
через другой приватный чат новому участнику.</p>
</li>
</ul>
<p>QR code and invite link can be used to add several members.
However, since groups are <a href="#groups">meant for trusted people</a>, avoid sharing them publicly.</p>
<p>QR-код и ссылку-приглашение можно использовать для добавления нескольких участников.
Однако, поскольку группы <a href="#groups">предназначены для проверенных людей</a>, не распространяйте их публично.</p>
<h3 id="я-случайно-удалил-самого-себя">
@@ -579,55 +578,55 @@ However, since groups are <a href="#groups">meant for trusted people</a>, avoid
</li>
</ul>
<h3 id="cloning-a-group">
<h3 id="клонирование-группы">
Cloning a group <a href="#cloning-a-group" class="anchor"></a>
Клонирование группы <a href="#клонирование-группы" class="anchor"></a>
</h3>
<p>You can duplicate a group to start a separate discussion
or to exclude members without them noticing.</p>
<p>Вы можете дублировать группу, чтобы начать отдельное обсуждение
или исключить участников, незаметно для них.</p>
<ul>
<li>
<p>Open the group profile and tap <strong>Clone Chat</strong> (Android/iOS),
or right-click the group in the chat list (Desktop).</p>
<p>Откройте профиль группы и нажмите <strong>Клонировать чат</strong> (Android/iOS),
или щелкните правой кнопкой мыши по группе в списке чатов (приложение для ПК).</p>
</li>
<li>
<p>Set a new name, choose an avatar, and adjust the member list if needed.</p>
<p>Установите новое имя, выберите аватар и при необходимости отредактируйте список участников.</p>
</li>
</ul>
<p>The new group is <strong>fully independent</strong> from the original,
which continues to work as before.</p>
<p>Новая группа <strong>полностью независима</strong> от исходной,
которая продолжает работать как прежде.</p>
<h2 id="webxdc">
In-chat apps <a href="#webxdc" class="anchor"></a>
Встроенные приложения чата <a href="#webxdc" class="anchor"></a>
</h2>
<p>You can send apps to a chat - games, editors, polls and other tools.
This makes Delta Chat a truly extensible messenger.</p>
<p>Вы можете отправлять приложения в чат - игры, редакторы, опросы и другие инструменты.
Это делает Delta Chat по-настоящему расширяемым мессенджером.</p>
<h3 id="where-can-i-get-in-chat-apps">
<h3 id="где-можно-найти-встроенные-приложения">
Where can I get in-chat apps? <a href="#where-can-i-get-in-chat-apps" class="anchor"></a>
Где можно найти встроенные приложения? <a href="#где-можно-найти-встроенные-приложения" class="anchor"></a>
</h3>
<ul>
<li>
<p>In a chat, using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → Apps</strong></p>
<p>В чате используйте кнопку <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Вложение → Приложения</strong>.</p>
</li>
<li>
<p>You can also <a href="#create-xdc">create your own app</a> and attach it using <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Attachment Button → File</strong></p>
<p>Вы также можете <a href="#create-xdc">создать собственное приложение</a> и прикрепить его с помощью кнопки <img style="vertical-align:middle; width:1.0em; margin:1px" src="../paperclip.png" alt="Paperclip" /> <strong>Вложение → Файл</strong>.</p>
</li>
</ul>
@@ -641,19 +640,19 @@ This makes Delta Chat a truly extensible messenger.</p>
<ul>
<li>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
<p>Встроенные приложения не могут отправлять данные в Интернет или что-либо загружать.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
<p>Встроенное приложение может обмениваться данными только внутри чата Delta Chat с его
копиями на устройствах ваших собеседников. В остальном оно полностью
изолировано от Интернета.</p>
</li>
<li>
<p>The privacy an in-chat app offers is the privacy of your chat - as long as you
trust the people you chat with, you can trust the in-chat app as well.</p>
<p>Конфиденциальность встроенного приложения соответствует конфиденциальности вашего чата
— пока вы доверяете людям, с которыми общаетесь, можете доверять и встроенному приложению.</p>
</li>
<li>
<p>This also means: Just like for web links, do not open apps from untrusted contacts.</p>
<p>Это также означает: как и в случае с веб-ссылками, не открывайте приложения от ненадежных контактов.</p>
</li>
</ul>
@@ -667,19 +666,19 @@ trust the people you chat with, you can trust the in-chat app as well.</p>
<ul>
<li>
<p>In-chat apps are zip files with <code class="language-plaintext highlighter-rouge">.xdc</code> extension containing html, css, and javascript code.</p>
<p>Встроенные приложения - это ZIP-файлы с расширением .xdc, содержащие HTML-, CSS- и JavaScript-код.</p>
</li>
<li>
<p>You can extend the <a href="https://github.com/webxdc/hello">Hello World example app</a>
to get started.</p>
<p>Вы можете расширить пример приложения <a href="https://github.com/webxdc/hello">Hello World</a>
чтобы начать работу.</p>
</li>
<li>
<p>All else you need to know is written in the
<a href="https://webxdc.org/docs">Webxdc documentation</a>.</p>
<p>Всю остальную информацию вы найдёте в
<a href="https://webxdc.org/docs">документации Webxdc</a>.</p>
</li>
<li>
<p>If you have question, you can ask others with experience
in the <a href="https://support.delta.chat/c/webxdc/20">Delta Chat Forum</a>.</p>
<p>Если у вас есть вопросы, вы можете обратиться к другим пользователям с опытом
на форуме <a href="https://support.delta.chat/c/webxdc/20">Delta Chat</a>.</p>
</li>
</ul>
@@ -774,9 +773,9 @@ Push-уведомления автоматически активируются
</h3>
<p>Delta Chat Push Notification support avoids leakage of private information.
It does not leak profile data, IP address or message content (not even encrypted)
to any system involved in the delivery of Push Notifications.</p>
<p>Поддержка push-уведомлений в Delta Chat предотвращает утечку личной информации.
Она не передаёт данные профиля, IP-адрес или содержимое сообщений (даже зашифрованных)
ни одной системе, участвующей в доставке уведомлений.</p>
<p>Вот как приложения Delta Chat выполняют доставку Push-уведомлений:</p>
@@ -786,21 +785,21 @@ to any system involved in the delivery of Push Notifications.</p>
на сервере <a href="https://delta.chat/chatmail">chatmail</a>.</p>
</li>
<li>
<p>When a <a href="https://delta.chat/chatmail">chatmail</a> server receives a message for a Delta Chat user
it forwards the encrypted device token to the central Delta Chat notification proxy.</p>
<p>Когда сервер <a href="https://delta.chat/chatmail">chatmail</a> получает сообщение для пользователя Delta Chat,
он пересылает зашифрованный токен устройства центральному прокси-серверу уведомлений Delta Chat.</p>
</li>
<li>
<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 profile data of Delta Chat users.</p>
<p>Центральный прокси-сервер уведомлений Delta Chat расшифровывает токен устройства
и пересылает его соответствующему сервису push-уведомлений (Apple, Google и т.д.),
не зная IP-адреса или данных профиля пользователей Delta Chat.</p>
</li>
<li>
<p>The central Push Service (Apple, Google, etc.)
wakes up the Delta Chat app on your device
to check for new messages in the background.
It does not know about the profile data of the device it wakes up.
The central Apple/Google Push services never see any profile data (sender or receiver)
and also never see any message content (also not in encrypted forms).</p>
<p>Центральный сервис push-уведомлений (Apple, Google и т.д.)
пробуждает приложение Delta Chat на вашем устройстве
для проверки новых сообщений в фоновом режиме.
Он не знает о данных профиля устройства, которое он пробуждает.
Центральные сервисы Apple/Google Push никогда не видят никаких данных профиля (отправителя или получателя),
а также не видят содержимого сообщений (в том числе в зашифрованном виде).</p>
</li>
</ul>
@@ -994,41 +993,41 @@ PIN-код разблокировки экрана, графический кл
</h3>
<p>At <strong>Settings → Advanced → Experimental Features</strong>
you can try out features we are working on.</p>
<p>В разделе <strong>Настройки → Дополнительно → Экспериментальные функции</strong>
вы можете опробовать функции, над которыми мы работаем.</p>
<p>The features may be <strong>unstable</strong> and may be <strong>changed or removed</strong>.</p>
<p>Эти функции могут быть <strong>нестабильными</strong> и могут быть <strong>изменены или удалены</strong>.</p>
<p>You can find more information
and give feedback in the <a href="https://support.delta.chat">Forum</a>.</p>
<p>Вы можете найти дополнительную информацию
и оставить отзыв на <a href="https://support.delta.chat">Форуме</a>.</p>
<h3 id="statssending">
What is “Send statistics to Delta Chats developers”? <a href="#statssending" class="anchor"></a>
Что означает “Отправлять статистику разработчикам Delta Chat”? <a href="#statssending" class="anchor"></a>
</h3>
<p>We would like to improve Delta Chat with your help,
which is why Delta Chat for Android asks whether you want
to send anonymous usage statistics.</p>
<p>Мы хотели бы улучшить Delta Chat с вашей помощью,
поэтому Delta Chat для Android спрашивает, хотите ли вы
отправлять анонимную статистику использования.</p>
<p>You can turn it on and off at
<strong>Settings → Advanced → Send statistics to Delta Chats developers</strong>.</p>
<p>Вы можете включить или отключить эту функцию
в разделе <strong>Настройки → Дополнительно → Отправить статистику разработчикам Delta Chat</strong>.</p>
<p>When you turn it on,
weekly statistics will be automatically sent to a bot.</p>
<p>При включении
еженедельная статистика будет автоматически отправляться боту.</p>
<p>We are interested e.g. in statistics like:</p>
<p>Нас интересует, например, следующая статистика:</p>
<ul>
<li>How many contacts are introduced by personally scanning a QR code?</li>
<li>Which versions of Delta Chat are being used?</li>
<li>How many messages are unencrypted?</li>
<li>Сколько контактов добавляется путём личного сканирования QR-кода?</li>
<li>Какие версии Delta Chat используются?</li>
<li>Сколько сообщений в незашифрованном виде?</li>
</ul>
<p>We will <em>not</em> collect any personally identifiable information about you.</p>
<p>Мы <em>не</em> собираем какую-либо информацию, позволяющую идентифицировать вас лично.</p>
<h3 id="могу-ли-я-использовать-обычный-адрес-электронной-почты-с-delta-chat">
@@ -1038,45 +1037,45 @@ weekly statistics will be automatically sent to a bot.</p>
</h3>
<p>Yes, but only if the email address is used exclusively by <a href="https://chatmail.at/clients">chatmail clients</a>.</p>
<p>Да, но только если адрес электронной почты используется исключительно <a href="https://chatmail.at/clients">chatmail клиентами</a>.</p>
<p>It is not supported to share usage of an email address with non-chatmail apps or web-based mailers,
for the following reasons:</p>
<p>Не поддерживается совместное использование адреса электронной почты с приложениями, не являющимися клиентами chatmail или веб-интерфейсами для работы с почтой,
по следующим причинам:</p>
<ul>
<li>
<p>Non-chatmail apps are largely not accomplishing automatic end-to-end email encryption for their users,
while chatmail apps and relays pervasively enforce end-to-end encryption and security standards.</p>
<p>Приложения, не являющиеся клиентами chatmail, в основном не обеспечивают автоматическое сквозное шифрование электронной почты для своих пользователей,
тогда как приложения и релеи chatmail повсеместно применяют сквозное шифрование и стандарты безопасности.</p>
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
<p>Приложения, не являющиеся клиентами chatmail, используют серверы электронной почты в качестве долгосрочного архива сообщений,
тогда как клиенты chatmail используют почтовые серверы для передачи мгновенных сообщений с коротким сроком жизни.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
would require considerable development and maintenance efforts,
and complicate making chatmail-based messaging more resilient, reliable and fast.</p>
<p>Поддержка всего разнообразия классических настроек электронной почты
потребует значительных усилий по разработке и сопровождению,
а также усложнит повышение устойчивости, надёжности и скорости обмена сообщениями на основе chatmail.</p>
</li>
</ul>
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
Как настроить профиль чата с использованием классического адреса электронной почты в качестве транспорта? <a href="#classic-email" class="anchor"></a>
</h3>
<p>First off, <strong>please do not use the same classic email address also from non-chatmail classic email apps</strong>
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>Прежде всего, <strong>не используйте те же классические адреса электронной почты, которые используются в обычных приложениях для отправки писем</strong>
если вы не готовы к зашифрованным сообщениям во входящих,
двойным уведомлениям, случайному удалению писем или подобным неудобствам.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
A chat profile using a classic email address allows to to send and receive unencrypted messages.
These messages, and the chats they appear in, are marked with an email icon
<p>Вы можете настроить адрес электронной почты для чата в разделе <strong>Новый профиль → Использовать другой сервер → Использовать классическую почту в качестве транспорта</strong>.
Обратите внимание, что классические почтовые провайдеры обычно не поддерживают <a href="#instant-delivery">Push-уведомления</a>
и имеют другие ограничения, см. раздел <a href="https://providers.delta.chat">Обзор провайдеров</a>.
Chatmail использует INBOX по умолчанию для ретрансляции; убедитесь, что провайдер также настроен.
Профиль чата, использующий классический адрес электронной почты, позволяет отправлять и получать незашифрованные сообщения.
Эти сообщения и чаты, в которых они появляются, помечаются значком электронной почты
<img style="vertical-align:middle; width:1.2em; margin:1px" src="../email-icon.png" alt="email" />.</p>
<h3 id="я-хочу-управлять-своим-собственным-сервером-для-delta-chat-что-вы-посоветуете">
@@ -1089,7 +1088,7 @@ These messages, and the chats they appear in, are marked with an email icon
<p>Подойдет любая корректная настройка почтового сервера, за исключением случаев, когда для корректной работы устройств ваших пользователей требуются <a href="#instant-delivery">Push-уведомления</a> Google/Apple.</p>
<p>Мы обычно рекомендуем <a href="https://chatmail.at/doc/relay/getting_started.html">настроить chatmail relay</a>.
<p>Мы обычно рекомендуем <a href="https://chatmail.at/doc/relay/getting_started.html">настроить chatmail релей</a>.
<a href="https://chatmail.at">Chatmail</a> — это проект, поддерживаемый сообществом который охватывает как настройку релеев, так
и <a href="https://github.com/chatmail/core">основные разработки на Rust</a>
которые обеспечивают работу <a href="https://chatmail.at/clients">клиентов chatmail</a> наиболее известным из которых является Delta Chat.</p>
@@ -1163,7 +1162,7 @@ These messages, and the chats they appear in, are marked with an email icon
</h3>
<p>Если вы используете стандартные <a href="https://chatmail.at/relays">ретрансляторы chatmail</a>,
<p>Если вы используете стандартные <a href="https://chatmail.at/relays">релеи chatmail</a>,
невозможно получать или отправлять сообщения без сквозного шифрования.</p>
<p>Если вы вместо этого используете <a href="#classic-email">классический почтовый сервер</a>,
@@ -1429,12 +1428,12 @@ Delta Chat показывает там два отпечатка.
<p>Нет.</p>
<p>Delta Chat генерирует безопасные ключи OpenPGP в соответствии со спецификацией Autocrypt 1.1.
Вы можете экспортировать свой закрытый ключ, но не можете импортировать дополнительные закрытые ключи.</p>
<p>В целом, мы не рекомендуем и не предлагаем пользователям выполнять ручное управление ключами.
Мы стремимся к тому, чтобы аудиты безопасности могли сосредоточиться на нескольких проверенных криптографических алгоритмах,
а не на всем разнообразии возможных алгоритмов, доступных с OpenPGP.</p>
<p>Delta Chat генерирует безопасные ключи OpenPGP в соответствии со спецификацией Autocrypt 1.1.
Мы не рекомендуем и не предлагаем пользователям управлять ключами вручную.
Мы хотим, чтобы аудиты безопасности могли сосредоточиться на нескольких проверенных криптографических алгоритмах
а не на всем многообразии возможных алгоритмов, разрешенных в OpenPGP.
Если вы хотите извлечь свой ключ OpenPGP, существует только экспертный метод:
вам нужно найти его в SQLite-таблице “keypairs” в tar-файле резервной копии профиля.</p>
<h3 id="security-audits">
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#zaujímajú-ma-technické-detaily-môžete-mi-povedať-viac">Zaujímajú ma technické detaily. Môžete mi povedať viac?</a></li>
</ul>
@@ -650,7 +650,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1057,7 +1057,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1069,7 +1069,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1078,7 +1078,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1437,12 +1437,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#më-interesojnë-hollësitë-teknike-mund-të-më-tregoni-diçka-më-tepër">Më interesojnë hollësitë teknike. Mund të më tregoni diçka më tepër?</a></li>
</ul>
@@ -652,7 +652,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1061,7 +1061,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1073,7 +1073,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1082,7 +1082,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1441,12 +1441,12 @@ the connection is safe.</p>
<p>No.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
You can export your private key but you can not import additional private keys.</p>
<p>In general, we do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
+59 -67
View File
@@ -8,7 +8,7 @@
<li><a href="#чи-підтримує-delta-chat-вкладення-у-вигляді-фото-відео-тощо">Чи підтримує Delta Chat вкладення у вигляді фото, відео тощо?</a></li>
<li><a href="#multiple-accounts">Що таке профілі? Як я можу перемикатися між ними?</a></li>
<li><a href="#хто-бачить-моє-зображення-профілю">Хто бачить моє зображення профілю?</a></li>
<li><a href="#signature">Can I set a Bio/Status with Delta Chat?</a></li>
<li><a href="#signature">Чи можу я встановити біографію/статус у Delta Chat?</a></li>
<li><a href="#що-значить-закріплення-приглушення-архівування">Що значить Закріплення, Приглушення, Архівування?</a></li>
<li><a href="#save">Як працюють “Збережені повідомлення”?</a></li>
<li><a href="#що-означає-зелена-точка">Що означає зелена точка?</a></li>
@@ -16,16 +16,15 @@
<li><a href="#edit">Виправлення помилок та видалення повідомлень після надсилання</a></li>
<li><a href="#ephemeralmsgs">Як працюють повідомлення, що зникають?</a></li>
<li><a href="#delold">Що станеться, якщо я ввімкну «Видаляти старі повідомлення з пристрою»?</a></li>
<li><a href="#remove-account">How can I delete my chat profile?</a></li>
</ul>
</li>
<li><a href="#groups">Groups</a>
<li><a href="#groups">Групи</a>
<ul>
<li><a href="#створення-групи">Створення групи</a></li>
<li><a href="#addmembers">Add and remove members</a></li>
<li><a href="#addmembers">Додавання та видалення учасників</a></li>
<li><a href="#я-випадково-себе-видалив">Я випадково себе видалив</a></li>
<li><a href="#я-більше-не-хочу-отримувати-повідомлення-групи">Я більше не хочу отримувати повідомлення групи.</a></li>
<li><a href="#cloning-a-group">Cloning a group</a></li>
<li><a href="#клонування-групи">Клонування групи</a></li>
</ul>
</li>
<li><a href="#webxdc">In-chat apps</a>
@@ -54,10 +53,10 @@
</li>
<li><a href="#advanced">Advanced</a>
<ul>
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#експериментальні-функції">Експериментальні функції</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#я-хочу-керувати-власним-сервером-для-delta-chat-що-ви-порекомендуєте">Я хочу керувати власним сервером для Delta Chat. Що ви порекомендуєте?</a></li>
<li><a href="#мене-цікавлять-технічні-деталі-можете-розповісти-більше">Мене цікавлять технічні деталі. Можете розповісти більше?</a></li>
</ul>
@@ -65,8 +64,8 @@
<li><a href="#e2ee">Шифрування та безпека</a>
<ul>
<li><a href="#які-стандарти-використовуються-для-наскрізного-шифрування">Які стандарти використовуються для наскрізного шифрування?</a></li>
<li><a href="#whene2e">How can I know if messages are end-to-end encrypted?</a></li>
<li><a href="#can-i-still-receive-or-send-messages-without-end-to-end-encryption">Can I still receive or send messages without end-to-end encryption?</a></li>
<li><a href="#whene2e">Як дізнатися, чи повідомлення зашифровано наскрізним шифруванням?</a></li>
<li><a href="#чи-можу-я-отримувати-та-надсилати-пошту-без-наскрізного-шифрування">Чи можу я отримувати та надсилати пошту без наскрізного шифрування?</a></li>
<li><a href="#e2eeguarantee">Що означає зелена галочка в профілі контакту?</a></li>
<li><a href="#чи-зашифровані-наскрізно-вкладення-зображення-файли-аудіо-тощо">Чи зашифровані наскрізно вкладення (зображення, файли, аудіо тощо)?</a></li>
<li><a href="#openpgp-secure">Чи безпечний OpenPGP?</a></li>
@@ -112,20 +111,17 @@
які пропонують миттєву доставку повідомлень та push-сповіщення для пристроїв iOS та Android.</p>
</li>
<li>
<p>Pervasive <a href="#multiple-accounts">multi-profile</a> and
<a href="#multiclient">multi-device</a> support on all platforms
and between different <a href="https://chatmail.at/clients">chatmail apps</a>.</p>
<p>Повсюдна підтримка багатьох <a href="#multiple-accounts">профілів</a> та <a href="#multiclient">пристроїв</a> на всіх платформах та між різними <a href="https://chatmail.at/clients">поштовими програмами</a>.</p>
</li>
<li>
<p>Interactive <a href="#webxdc">in-chat apps</a> for gaming and collaboration</p>
<p>Інтерактивні <a href="https://webxdc.org/">веб-застосунки у чатах</a> для ігор та співпраці</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">Аудитоване наскрізне шифрування</a>
захищене від мережевих та серверних атак.</p>
</li>
<li>
<p>Free and Open Source software, both app and server side,
built on <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Internet Standards</a>.</p>
<p>Вільне програмне забезпечення з відкритим вихідним кодом, як застосунок, так серверна частина, побудоване на основі <a href="https://github.com/chatmail/core/blob/main/standards.md#standards-used-in-delta-chat">Інтернет-стандартів</a>.</p>
</li>
</ul>
@@ -137,8 +133,7 @@ built on <a href="https://github.com/chatmail/core/blob/main/standards.md#standa
</h3>
<p>First, note that Delta Chat is a private messenger.
There is no public discovery, <em>you</em> decide about your contacts.</p>
<p>По-перше, зверніть увагу, що Delta Chat - це приватний месенджер. Тут немає публічного розкриття, <em>ви</em> самі вирішуєте, з ким спілкуватися.</p>
<ul>
<li>
@@ -156,7 +151,7 @@ through another private chat.</p>
</li>
</ul>
<p>Now wait while connection gets established.</p>
<p>Зараз зачекайте, поки встановлюється з’єднання.</p>
<ul>
<li>
@@ -169,9 +164,9 @@ the ability to chat is delayed until connectivity is restored.</p>
</li>
</ul>
<p>Congratulations!
You now will automatically use <a href="#e2ee">end-to-end encryption</a> with this contact.
If you add each other to <a href="#groups">groups</a>, end-to-end encryption will be established among all members.</p>
<p>Вітаємо!
Тепер Ви автоматично використовуватимете <a href="#e2ee">наскрізне шифрування</a> з цим контактом.
Якщо ви додасте один одного у <a href="#groups">групи</a>, наскрізне шифрування буде встановлено між усіма учасниками.</p>
<h3 id="why-is-a-chat-marked-as-request">
@@ -246,7 +241,7 @@ and uses the server only to relay messages.</p>
<p>Пізніше ви можете натиснути на зображення вашого профілю у верхньому лівому кутку, щоб вибрати <strong>Додати профілі</strong> або <strong>Переключити профілі</strong>.</p>
<p>You may want to use separate profiles for political, family or work related activities.</p>
<p>Ви можете використовувати окремі профілі для політичної, сімейної або робочої діяльності.</p>
<p>Ви також можете дізнатися <a href="#multiclient">як використовувати один і той самий профіль на декількох пристроях</a>.</p>
@@ -270,7 +265,7 @@ and uses the server only to relay messages.</p>
<h3 id="signature">
Can I set a Bio/Status with Delta Chat? <a href="#signature" class="anchor"></a>
Чи можу я встановити біографію/статус у Delta Chat? <a href="#signature" class="anchor"></a>
</h3>
@@ -447,14 +442,8 @@ the (anyway encrypted) messages may take longer to get deleted from their server
<li>Щоб увімкнути його, перейдіть до «видалити старі повідомлення з пристрою» в налаштуваннях «Чатів та медіа» . Ви можете встановити часові рамки від «через годину» до «через рік»;
Таким чином, <em>усі</em> повідомлення будуть видалені з вашого пристрою, як тільки вони будуть старішими за це.</li>
</ul>
<h3 id="remove-account">
How can I delete my chat profile? <a href="#remove-account" class="anchor"></a>
</h3>
<p>Як я можу видалити свій профіль у Delta Chat? {#remove-account}</p>
<p>If you are using more than one chat profile,
you can remove single ones in the top profile switcher menu (on Android and iOS),
@@ -470,12 +459,12 @@ or the respective page from your chosen <a href="https://chatmail.at/relays">3rd
<h2 id="groups">
Groups <a href="#groups" class="anchor"></a>
Групи <a href="#groups" class="anchor"></a>
</h2>
<p>Groups let several people chat together privately with <strong>equal rights</strong>.</p>
<p>Групи дозволяють кільком людям спілкуватися у приватному чаті з <strong>рівними правами</strong>.</p>
<p>Anyone can
change the group name or avatar,
@@ -483,7 +472,7 @@ change the group name or avatar,
set <a href="#ephemeralmsgs">disappearing messages</a>,
and <a href="#edit">delete their own messages</a> from all members devices.</p>
<p>Because all members have the same rights, groups work best among <strong>trusted friends and family</strong>.</p>
<p>Оскільки усі учасники мають однакові права, групи найкраще працюють серед <strong>довірених друзів та родичів</strong>.</p>
<h3 id="створення-групи">
@@ -502,15 +491,15 @@ and <a href="#edit">delete their own messages</a> from all members devices.</
<h3 id="addmembers">
Add and remove members <a href="#addmembers" class="anchor"></a>
Додавання та видалення учасників <a href="#addmembers" class="anchor"></a>
</h3>
<ul>
<li>
<p>All group members have the <strong>same rights</strong>.
For this reason, everyone can delete any member or add new ones.</p>
<p>Усі учасники групи мають <strong>однакові права</strong>.
Тому кожен може видалити будь-якого учасника або додати нових.</p>
</li>
<li>
<p>To <strong>add or delete members</strong>, tap the group name in the chat and select the member to add or remove.</p>
@@ -560,10 +549,10 @@ However, since groups are <a href="#groups">meant for trusted people</a>, avoid
</li>
</ul>
<h3 id="cloning-a-group">
<h3 id="клонування-групи">
Cloning a group <a href="#cloning-a-group" class="anchor"></a>
Клонування групи <a href="#клонування-групи" class="anchor"></a>
</h3>
@@ -581,8 +570,8 @@ or right-click the group in the chat list (Desktop).</p>
</li>
</ul>
<p>The new group is <strong>fully independent</strong> from the original,
which continues to work as before.</p>
<p>Нова група є <strong>цілком незалежною</strong> від оригінальної,
котра продовжує працювати як раніше.</p>
<h2 id="webxdc">
@@ -625,7 +614,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -655,8 +644,8 @@ trust the people you chat with, you can trust the in-chat app as well.</p>
to get started.</p>
</li>
<li>
<p>All else you need to know is written in the
<a href="https://webxdc.org/docs">Webxdc documentation</a>.</p>
<p>Все інше, що Вам потрібно знати, написано у
<a href="https://webxdc.org/docs">документації Webxdc</a>.</p>
</li>
<li>
<p>If you have question, you can ask others with experience
@@ -911,10 +900,10 @@ Welcome to the power of the interoperable chatmail relay network :)</p>
</h2>
<h3 id="experimental-features">
<h3 id="експериментальні-функції">
Experimental Features <a href="#experimental-features" class="anchor"></a>
Експериментальні функції <a href="#експериментальні-функції" class="anchor"></a>
</h3>
@@ -922,10 +911,10 @@ Welcome to the power of the interoperable chatmail relay network :)</p>
<p>At <strong>Settings → Advanced → Experimental Features</strong>
you can try out features we are working on.</p>
<p>The features may be <strong>unstable</strong> and may be <strong>changed or removed</strong>.</p>
<p>Ці функції можуть бути <strong>нестабільними</strong> та можуть бути <strong>змінені або видалені</strong>.</p>
<p>You can find more information
and give feedback in the <a href="https://support.delta.chat">Forum</a>.</p>
<p>Ви можете знайти додаткову інформацію
та залишити відгук на <a href="https://support.delta.chat">форумі</a>.</p>
<h3 id="statssending">
@@ -942,8 +931,8 @@ to send anonymous usage statistics.</p>
<p>You can turn it on and off at
<strong>Settings → Advanced → Send statistics to Delta Chats developers</strong>.</p>
<p>When you turn it on,
weekly statistics will be automatically sent to a bot.</p>
<p>Коли Ви увімкнете цю функцію,
щотижнева статистика буде автоматично надсилатися боту.</p>
<p>We are interested e.g. in statistics like:</p>
@@ -953,7 +942,7 @@ weekly statistics will be automatically sent to a bot.</p>
<li>How many messages are unencrypted?</li>
</ul>
<p>We will <em>not</em> collect any personally identifiable information about you.</p>
<p>Ми <em>не</em> будемо збирати жодних персональних даних, які б могли ідентифікувати Вас особисто.</p>
<h3 id="can-i-use-a-classic-email-address-with-delta-chat">
@@ -975,7 +964,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -987,7 +976,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -996,7 +985,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1067,17 +1056,17 @@ that power <a href="https://chatmail.at/clients">chatmail clients</a> of which D
<h3 id="whene2e">
How can I know if messages are end-to-end encrypted? <a href="#whene2e" class="anchor"></a>
Як дізнатися, чи повідомлення зашифровано наскрізним шифруванням? <a href="#whene2e" class="anchor"></a>
</h3>
<p>Всі повідомлення в Delta Chat за замовчуванням <strong>наскрізно зашифровані</strong>. Починаючи з версії 2 Delta Chat (липень 2025 року) на наскрізних зашифрованих повідомленнях більше немає замків або інших подібних маркерів.</p>
<h3 id="can-i-still-receive-or-send-messages-without-end-to-end-encryption">
<h3 id="чи-можу-я-отримувати-та-надсилати-пошту-без-наскрізного-шифрування">
Can I still receive or send messages without end-to-end encryption? <a href="#can-i-still-receive-or-send-messages-without-end-to-end-encryption" class="anchor"></a>
Чи можу я отримувати та надсилати пошту без наскрізного шифрування? <a href="#чи-можу-я-отримувати-та-надсилати-пошту-без-наскрізного-шифрування" class="anchor"></a>
</h3>
@@ -1194,11 +1183,11 @@ even if the message was not end-to-end encrypted.</p>
<p>Servers can therefore only see:</p>
<ul>
<li>the sender and receiver addresses</li>
<li>and the message size.</li>
<li>адреси відправника та одержувача</li>
<li>та розмір повідомлення.</li>
</ul>
<p>By default, the addresses are randomly generated.</p>
<p>За замовчуванням адреси генеруються випадковим чином.</p>
<p>Усі інші метадані повідомлень, контактів і груп містяться в наскрізно зашифрованій частині повідомлень.</p>
@@ -1284,9 +1273,12 @@ but an implementation has not been agreed as a priority yet.</p>
<p>Ні.</p>
<p>Delta Chat генерує безпечні ключі OpenPGP відповідно до специфікації Autocrypt 1.1. Ви можете експортувати свій приватний ключ, але не можете імпортувати додаткові приватні ключі.</p>
<p>Загалом, ми не рекомендуємо і не пропонуємо користувачам керувати ключами вручну. Ми хочемо гарантувати, що аудит безпеки може зосередитися на декількох перевірених криптографічних алгоритмах а не на всій широті можливих алгоритмів, дозволених у OpenPGP.</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
@@ -1345,7 +1337,7 @@ but an implementation has not been agreed as a priority yet.</p>
<p>Some features require certain permissions,
e.g. you need to grant camera permission if you want to <a href="#howtoe2ee">scan an invite QR code</a>.</p>
<p>See <a href="https://delta.chat/en/gdpr#24-app-permissions">Privacy Policy</a> for a detailed overview.</p>
<p>Дивіться <a href="https://delta.chat/en/gdpr#24-app-permissions">політику конфіденційності</a> для детального огляду.</p>
<h3 id="де-мої-друзі-можуть-знайти-delta-chat">
+11 -11
View File
@@ -57,7 +57,7 @@
<li><a href="#experimental-features">Experimental Features</a></li>
<li><a href="#statssending">What is “Send statistics to Delta Chats developers”?</a></li>
<li><a href="#can-i-use-a-classic-email-address-with-delta-chat">Can I use a classic email address with Delta Chat?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as transport?</a></li>
<li><a href="#classic-email">How can I configure a chat profile with a classic email address as relay?</a></li>
<li><a href="#i-want-to-manage-my-own-server-for-delta-chat-what-do-you-recommend">I want to manage my own server for Delta Chat. What do you recommend?</a></li>
<li><a href="#我对技术细节很感兴趣能告诉我更多吗">我对技术细节很感兴趣。能告诉我更多吗?</a></li>
</ul>
@@ -637,7 +637,7 @@ This makes Delta Chat a truly extensible messenger.</p>
<p>In-chat apps can not send data to the Internet, or download anything.</p>
</li>
<li>
<p>An in-chat app can only exchange data within a Delta Chat chat, with its
<p>An in-chat app can only exchange data within a chat, with its
copies on the devices of your chat partners. Other than that, its completely
isolated from the Internet.</p>
</li>
@@ -1033,7 +1033,7 @@ while chatmail apps and relays pervasively enforce end-to-end encryption and sec
</li>
<li>
<p>Non-chatmail apps use email servers as a long-term message archive
while chatmail clients use email servers for ephemeral instant message transport.</p>
while chatmail clients use email servers for ephemeral instant message relay.</p>
</li>
<li>
<p>Supporting the full variety of classic email setups
@@ -1045,7 +1045,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
<h3 id="classic-email">
How can I configure a chat profile with a classic email address as transport? <a href="#classic-email" class="anchor"></a>
How can I configure a chat profile with a classic email address as relay? <a href="#classic-email" class="anchor"></a>
</h3>
@@ -1054,7 +1054,7 @@ and complicate making chatmail-based messaging more resilient, reliable and fast
unless you are prepared to deal with encrypted messages in the inbox,
double notifications, accidentally deleted emails or similar annoyances.</p>
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Transport</strong>.
<p>You can configure a email address for chatting at <strong>New Profile → Use Other Server → Use Classic Mail as Relay</strong>.
Note that classic email providers will generally not support <a href="#instant-delivery">Push Notifications</a>
and have other limitations, see <a href="https://providers.delta.chat">Provider Overview</a>.
Chatmail uses the default INBOX for relay; ensure the provider setup does too.
@@ -1410,12 +1410,12 @@ Delta Chat 在此处显示两个指纹。
<p>不。</p>
<p>Delta Chat 采用 Autocrypt 1.1 标准规范生成 OpenPGP 加密密钥。
用户虽可导出自身私钥进行备份,但系统设计上不支持导入其他私钥。</p>
<p>基于安全考量,系统默认不开放手动密钥管理功能。
此项设计旨在让安全审计工作聚焦于少量成熟加密算法(如 Autocrypt 标准),
避免因支持 OpenPGP 协议所允许的所有算法而增加潜在安全风险。</p>
<p>Delta Chat generates secure OpenPGP keys according to the Autocrypt specification 1.1.
We do not recommend or offer users to perform manual key management.
We want to ensure that security audits can focus on a few proven cryptographic algorithms
instead of the full breadth of possible algorithms allowed with OpenPGP.
If you want to extract your OpenPGP key, there only is an expert method:
you need to look it up in the “keypairs” SQLite table of a profile backup tar-file.</p>
<h3 id="security-audits">
@@ -8,7 +8,7 @@ import com.fasterxml.jackson.annotation.JsonTypeInfo.Id;
import com.fasterxml.jackson.annotation.JsonTypeInfo.As;
@JsonTypeInfo(use=Id.NAME, include=As.PROPERTY, property="kind")
@JsonSubTypes({@Type(value = EventType.Info.class, name="Info"), @Type(value = EventType.SmtpConnected.class, name="SmtpConnected"), @Type(value = EventType.ImapConnected.class, name="ImapConnected"), @Type(value = EventType.SmtpMessageSent.class, name="SmtpMessageSent"), @Type(value = EventType.ImapMessageDeleted.class, name="ImapMessageDeleted"), @Type(value = EventType.ImapMessageMoved.class, name="ImapMessageMoved"), @Type(value = EventType.ImapInboxIdle.class, name="ImapInboxIdle"), @Type(value = EventType.NewBlobFile.class, name="NewBlobFile"), @Type(value = EventType.DeletedBlobFile.class, name="DeletedBlobFile"), @Type(value = EventType.Warning.class, name="Warning"), @Type(value = EventType.Error.class, name="Error"), @Type(value = EventType.ErrorSelfNotInGroup.class, name="ErrorSelfNotInGroup"), @Type(value = EventType.MsgsChanged.class, name="MsgsChanged"), @Type(value = EventType.ReactionsChanged.class, name="ReactionsChanged"), @Type(value = EventType.IncomingReaction.class, name="IncomingReaction"), @Type(value = EventType.IncomingWebxdcNotify.class, name="IncomingWebxdcNotify"), @Type(value = EventType.IncomingMsg.class, name="IncomingMsg"), @Type(value = EventType.IncomingMsgBunch.class, name="IncomingMsgBunch"), @Type(value = EventType.MsgsNoticed.class, name="MsgsNoticed"), @Type(value = EventType.MsgDelivered.class, name="MsgDelivered"), @Type(value = EventType.MsgFailed.class, name="MsgFailed"), @Type(value = EventType.MsgRead.class, name="MsgRead"), @Type(value = EventType.MsgDeleted.class, name="MsgDeleted"), @Type(value = EventType.ChatModified.class, name="ChatModified"), @Type(value = EventType.ChatEphemeralTimerModified.class, name="ChatEphemeralTimerModified"), @Type(value = EventType.ChatDeleted.class, name="ChatDeleted"), @Type(value = EventType.ContactsChanged.class, name="ContactsChanged"), @Type(value = EventType.LocationChanged.class, name="LocationChanged"), @Type(value = EventType.ConfigureProgress.class, name="ConfigureProgress"), @Type(value = EventType.ImexProgress.class, name="ImexProgress"), @Type(value = EventType.ImexFileWritten.class, name="ImexFileWritten"), @Type(value = EventType.SecurejoinInviterProgress.class, name="SecurejoinInviterProgress"), @Type(value = EventType.SecurejoinJoinerProgress.class, name="SecurejoinJoinerProgress"), @Type(value = EventType.ConnectivityChanged.class, name="ConnectivityChanged"), @Type(value = EventType.SelfavatarChanged.class, name="SelfavatarChanged"), @Type(value = EventType.ConfigSynced.class, name="ConfigSynced"), @Type(value = EventType.WebxdcStatusUpdate.class, name="WebxdcStatusUpdate"), @Type(value = EventType.WebxdcRealtimeData.class, name="WebxdcRealtimeData"), @Type(value = EventType.WebxdcRealtimeAdvertisementReceived.class, name="WebxdcRealtimeAdvertisementReceived"), @Type(value = EventType.WebxdcInstanceDeleted.class, name="WebxdcInstanceDeleted"), @Type(value = EventType.AccountsBackgroundFetchDone.class, name="AccountsBackgroundFetchDone"), @Type(value = EventType.ChatlistChanged.class, name="ChatlistChanged"), @Type(value = EventType.ChatlistItemChanged.class, name="ChatlistItemChanged"), @Type(value = EventType.AccountsChanged.class, name="AccountsChanged"), @Type(value = EventType.AccountsItemChanged.class, name="AccountsItemChanged"), @Type(value = EventType.EventChannelOverflow.class, name="EventChannelOverflow"), @Type(value = EventType.IncomingCall.class, name="IncomingCall"), @Type(value = EventType.IncomingCallAccepted.class, name="IncomingCallAccepted"), @Type(value = EventType.OutgoingCallAccepted.class, name="OutgoingCallAccepted"), @Type(value = EventType.CallEnded.class, name="CallEnded")})
@JsonSubTypes({@Type(value = EventType.Info.class, name="Info"), @Type(value = EventType.SmtpConnected.class, name="SmtpConnected"), @Type(value = EventType.ImapConnected.class, name="ImapConnected"), @Type(value = EventType.SmtpMessageSent.class, name="SmtpMessageSent"), @Type(value = EventType.ImapMessageDeleted.class, name="ImapMessageDeleted"), @Type(value = EventType.ImapMessageMoved.class, name="ImapMessageMoved"), @Type(value = EventType.ImapInboxIdle.class, name="ImapInboxIdle"), @Type(value = EventType.NewBlobFile.class, name="NewBlobFile"), @Type(value = EventType.DeletedBlobFile.class, name="DeletedBlobFile"), @Type(value = EventType.Warning.class, name="Warning"), @Type(value = EventType.Error.class, name="Error"), @Type(value = EventType.ErrorSelfNotInGroup.class, name="ErrorSelfNotInGroup"), @Type(value = EventType.MsgsChanged.class, name="MsgsChanged"), @Type(value = EventType.ReactionsChanged.class, name="ReactionsChanged"), @Type(value = EventType.IncomingReaction.class, name="IncomingReaction"), @Type(value = EventType.IncomingWebxdcNotify.class, name="IncomingWebxdcNotify"), @Type(value = EventType.IncomingMsg.class, name="IncomingMsg"), @Type(value = EventType.IncomingMsgBunch.class, name="IncomingMsgBunch"), @Type(value = EventType.MsgsNoticed.class, name="MsgsNoticed"), @Type(value = EventType.MsgDelivered.class, name="MsgDelivered"), @Type(value = EventType.MsgFailed.class, name="MsgFailed"), @Type(value = EventType.MsgRead.class, name="MsgRead"), @Type(value = EventType.MsgDeleted.class, name="MsgDeleted"), @Type(value = EventType.ChatModified.class, name="ChatModified"), @Type(value = EventType.ChatEphemeralTimerModified.class, name="ChatEphemeralTimerModified"), @Type(value = EventType.ChatDeleted.class, name="ChatDeleted"), @Type(value = EventType.ContactsChanged.class, name="ContactsChanged"), @Type(value = EventType.LocationChanged.class, name="LocationChanged"), @Type(value = EventType.ConfigureProgress.class, name="ConfigureProgress"), @Type(value = EventType.ImexProgress.class, name="ImexProgress"), @Type(value = EventType.ImexFileWritten.class, name="ImexFileWritten"), @Type(value = EventType.SecurejoinInviterProgress.class, name="SecurejoinInviterProgress"), @Type(value = EventType.SecurejoinJoinerProgress.class, name="SecurejoinJoinerProgress"), @Type(value = EventType.ConnectivityChanged.class, name="ConnectivityChanged"), @Type(value = EventType.SelfavatarChanged.class, name="SelfavatarChanged"), @Type(value = EventType.ConfigSynced.class, name="ConfigSynced"), @Type(value = EventType.WebxdcStatusUpdate.class, name="WebxdcStatusUpdate"), @Type(value = EventType.WebxdcRealtimeData.class, name="WebxdcRealtimeData"), @Type(value = EventType.WebxdcRealtimeAdvertisementReceived.class, name="WebxdcRealtimeAdvertisementReceived"), @Type(value = EventType.WebxdcInstanceDeleted.class, name="WebxdcInstanceDeleted"), @Type(value = EventType.AccountsBackgroundFetchDone.class, name="AccountsBackgroundFetchDone"), @Type(value = EventType.ChatlistChanged.class, name="ChatlistChanged"), @Type(value = EventType.ChatlistItemChanged.class, name="ChatlistItemChanged"), @Type(value = EventType.AccountsChanged.class, name="AccountsChanged"), @Type(value = EventType.AccountsItemChanged.class, name="AccountsItemChanged"), @Type(value = EventType.EventChannelOverflow.class, name="EventChannelOverflow"), @Type(value = EventType.IncomingCall.class, name="IncomingCall"), @Type(value = EventType.IncomingCallAccepted.class, name="IncomingCallAccepted"), @Type(value = EventType.OutgoingCallAccepted.class, name="OutgoingCallAccepted"), @Type(value = EventType.CallEnded.class, name="CallEnded"), @Type(value = EventType.TransportsModified.class, name="TransportsModified")})
public abstract class EventType {
/**
@@ -409,4 +409,12 @@ public abstract class EventType {
public Integer msg_id;
}
/**
* One or more transports has changed.
* <p>
* This event is used for tests to detect when transport synchronization messages arrives. UIs don't need to use it, it is unlikely that user modifies transports on multiple devices simultaneously.
*/
public static class TransportsModified extends EventType {
}
}
@@ -70,6 +70,9 @@ public class AllMediaDocumentsFragment
this.noMedia = ViewUtil.findById(view, R.id.no_documents);
this.gridManager = new StickyHeaderGridLayoutManager(1);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(recyclerView, true, false, true, true);
this.recyclerView.setAdapter(new AllMediaDocumentsAdapter(getContext(),
new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()),
this));
@@ -66,6 +66,9 @@ public class AllMediaGalleryFragment
this.noMedia = ViewUtil.findById(view, R.id.no_images);
this.gridManager = new StickyHeaderGridLayoutManager(getCols());
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(recyclerView, true, false, true, true);
this.recyclerView.setAdapter(new AllMediaGalleryAdapter(getContext(),
GlideApp.with(this),
new BucketedThreadMediaLoader.BucketedThreadMedia(getContext()),
@@ -45,6 +45,7 @@ import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.SignalProtocolLoggerProvider;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.webxdc.WebxdcGarbageCollectionWorker;
import java.io.File;
import java.io.PrintWriter;
@@ -240,6 +241,18 @@ public class ApplicationContext extends MultiDexApplication {
ExistingPeriodicWorkPolicy.KEEP,
fetchWorkRequest);
}
PeriodicWorkRequest webxdcGarbageCollectionRequest = new PeriodicWorkRequest.Builder(
WebxdcGarbageCollectionWorker.class,
PeriodicWorkRequest.MIN_PERIODIC_INTERVAL_MILLIS,
TimeUnit.MILLISECONDS,
PeriodicWorkRequest.MIN_PERIODIC_FLEX_MILLIS,
TimeUnit.MILLISECONDS)
.build();
WorkManager.getInstance(this).enqueueUniquePeriodicWork(
"WebxdcGarbageCollectionWorker",
ExistingPeriodicWorkPolicy.KEEP,
webxdcGarbageCollectionRequest);
}
public JobManager getJobManager() {
@@ -49,6 +49,7 @@ import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.ScreenLockUtil;
import org.thoughtcrime.securesms.util.ViewUtil;
/**
* The Activity for application preference display and management.
@@ -79,7 +80,9 @@ public class ApplicationPreferencesActivity extends PassphraseRequiredActionBarA
//noinspection ConstantConditions
this.getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.fragment));
if (icicle == null) {
initFragment(R.id.fragment, new ApplicationPreferenceFragment());
@@ -1,5 +1,6 @@
package org.thoughtcrime.securesms;
import android.os.Build;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
@@ -17,6 +18,7 @@ import androidx.fragment.app.Fragment;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.lang.reflect.Field;
@@ -33,9 +35,24 @@ public abstract class BaseActionBarActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
onPreCreate();
EdgeToEdge.enable(this); // docs says to use: WindowCompat.enableEdgeToEdge(getWindow()); but it is not available
super.onCreate(savedInstanceState);
WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView()).setAppearanceLightStatusBars(false); // force white text in status bar
// Only enable Edge-to-Edge on API 30+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
// docs says to use: WindowCompat.enableEdgeToEdge(getWindow());
// but it actually makes things worse, the next takes care of setting the 3-buttons navigation bar background
EdgeToEdge.enable(this);
// force white text in status bar so it visible over background color
WindowCompat.getInsetsController(getWindow(), getWindow().getDecorView()).setAppearanceLightStatusBars(false);
}
}
@Override
protected void onPostCreate(@Nullable Bundle savedInstanceState) {
super.onPostCreate(savedInstanceState);
// Apply adjustments to the toolbar for edge-to-edge display
ViewUtil.adjustToolbarForE2E(this);
}
@Override
@@ -1,10 +1,10 @@
package org.thoughtcrime.securesms;
import static org.thoughtcrime.securesms.util.RelayUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedText;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedUris;
import static org.thoughtcrime.securesms.util.RelayUtil.isForwarding;
import static org.thoughtcrime.securesms.util.RelayUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.getSharedText;
import static org.thoughtcrime.securesms.util.ShareUtil.getSharedUris;
import static org.thoughtcrime.securesms.util.ShareUtil.isForwarding;
import static org.thoughtcrime.securesms.util.ShareUtil.isRelayingMessageContent;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -36,7 +36,7 @@ import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionB
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.connect.DirectShareUtil;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.ShareUtil;
import org.thoughtcrime.securesms.util.SendRelayedMessageUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.task.SnackbarAsyncTask;
@@ -382,7 +382,7 @@ public abstract class BaseConversationListFragment extends Fragment implements A
@Override
public boolean onCreateActionMode(ActionMode mode, Menu menu) {
if (isRelayingMessageContent(getActivity())) {
if (RelayUtil.getSharedContactId(getActivity()) != 0) {
if (ShareUtil.getSharedContactId(getActivity()) != 0) {
return false; // no sharing of a contact to multiple recipients at the same time, we can reconsider when that becomes a real-world need
}
Context context = getContext();
@@ -33,7 +33,6 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
setContentView(R.layout.activity_blocked_contacts);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setTitle(R.string.pref_blocked_contacts);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
initFragment(R.id.fragment, new BlockedAndShareContactsFragment(), getIntent().getExtras());
}
@@ -60,6 +59,10 @@ public class BlockedContactsActivity extends PassphraseRequiredActionBarActivity
View view = inflater.inflate(R.layout.contact_selection_list_fragment, container, false);
recyclerView = ViewUtil.findById(view, R.id.recycler_view);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(recyclerView);
emptyStateView = ViewUtil.findById(view, android.R.id.empty);
emptyStateView.setText(R.string.blocked_empty_hint);
return view;
@@ -17,15 +17,11 @@
package org.thoughtcrime.securesms;
import static org.thoughtcrime.securesms.util.RelayUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.isRelayingMessageContent;
import android.Manifest;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.util.SparseIntArray;
import android.view.LayoutInflater;
import android.view.Menu;
@@ -51,13 +47,11 @@ import com.b44t.messenger.DcEvent;
import org.thoughtcrime.securesms.connect.DcContactsLoader;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.contacts.ContactAccessor;
import org.thoughtcrime.securesms.contacts.ContactSelectionListAdapter;
import org.thoughtcrime.securesms.contacts.ContactSelectionListItem;
import org.thoughtcrime.securesms.contacts.NewContactActivity;
import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.qr.QrActivity;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -112,13 +106,6 @@ public class ContactSelectionListFragment extends Fragment
public void onStart() {
super.onStart();
this.getLoaderManager().initLoader(0, null, this);
if (dcContext.getConfigInt("ui.android.show_system_contacts") != 0 && !dcContext.isChatmail()) {
Permissions.with(this)
.request(Manifest.permission.READ_CONTACTS)
.ifNecessary()
.onAllGranted(this::handleContactPermissionGranted)
.execute();
}
}
@Override
@@ -126,6 +113,10 @@ public class ContactSelectionListFragment extends Fragment
View view = inflater.inflate(R.layout.contact_selection_list_fragment, container, false);
recyclerView = ViewUtil.findById(view, R.id.recycler_view);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(recyclerView, true, false, true, true);
recyclerView.setLayoutManager(new LinearLayoutManager(getActivity()));
actionModeCallback = new ActionMode.Callback() {
@Override
@@ -283,38 +274,6 @@ public class ContactSelectionListFragment extends Fragment
((ContactSelectionListAdapter) recyclerView.getAdapter()).changeData(null);
}
@SuppressLint("StaticFieldLeak")
private void handleContactPermissionGranted() {
new AsyncTask<Void, Void, Void>() {
@Override
protected Void doInBackground(Void... voids) {
loadSystemContacts();
return null;
}
}.execute();
}
private void loadSystemContacts() {
Thread thread = new Thread() {
@Override
public void run() {
try {
ContactAccessor contactAccessor = ContactAccessor.getInstance();
String allSystemContacts = contactAccessor.getAllSystemContactsAsString(getContext());
if (!allSystemContacts.isEmpty()) {
dcContext.addAddressBook(allSystemContacts);
}
} catch (SecurityException e) {
Log.e(TAG, "Caught a weird bug in the Android OS https://github.com/deltachat/deltachat-android/issues/1639: " + e);
e.printStackTrace();
}
}
};
thread.start();
}
private class ListClickListener implements ContactSelectionListAdapter.ItemClickListener {
@Override
public void onItemClick(ContactSelectionListItem contact, boolean handleActionMode)
@@ -17,12 +17,9 @@
package org.thoughtcrime.securesms;
import static org.thoughtcrime.securesms.TransportOption.Type;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedHtml;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedSubject;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedText;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedType;
import static org.thoughtcrime.securesms.util.RelayUtil.isForwarding;
import static org.thoughtcrime.securesms.util.RelayUtil.isSharing;
import static org.thoughtcrime.securesms.util.ShareUtil.getSharedText;
import static org.thoughtcrime.securesms.util.ShareUtil.isForwarding;
import static org.thoughtcrime.securesms.util.ShareUtil.isSharing;
import android.Manifest;
import android.annotation.SuppressLint;
@@ -109,7 +106,7 @@ import org.thoughtcrime.securesms.scribbles.ScribbleActivity;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.ShareUtil;
import org.thoughtcrime.securesms.util.SendRelayedMessageUtil;
import org.thoughtcrime.securesms.util.ServiceUtil;
import org.thoughtcrime.securesms.util.Util;
@@ -748,18 +745,18 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
}
private void handleSharing() {
ArrayList<Uri> uriList = RelayUtil.getSharedUris(this);
int sharedContactId = RelayUtil.getSharedContactId(this);
ArrayList<Uri> uriList = ShareUtil.getSharedUris(this);
int sharedContactId = ShareUtil.getSharedContactId(this);
if (uriList.size() > 1) {
askSendingFiles(uriList, () -> SendRelayedMessageUtil.immediatelyRelay(this, chatId));
} else {
if (sharedContactId != 0) {
addAttachmentContactInfo(sharedContactId);
} else if (getSharedHtml(this) != null || getSharedSubject(this) != null || ("sticker".equals(getSharedType(this)) && !uriList.isEmpty())) {
} else if (ShareUtil.getSharedHtml(this) != null || ShareUtil.getSharedSubject(this) != null || ("sticker".equals(ShareUtil.getSharedType(this)) && !uriList.isEmpty())) {
SendRelayedMessageUtil.immediatelyRelay(this, chatId);
} else {
Uri uri = uriList.isEmpty()? null : uriList.get(0);
dcContext.setDraft(chatId, SendRelayedMessageUtil.createMessage(this, uri, getSharedType(this), null, null, getSharedText(this)));
dcContext.setDraft(chatId, SendRelayedMessageUtil.createMessage(this, uri, ShareUtil.getSharedType(this), null, null, getSharedText(this)));
}
initializeDraft();
}
@@ -775,7 +772,7 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
isEditing = false;
final SettableFuture<Boolean> future = new SettableFuture<>();
DcMsg draft = dcContext.getDraft(chatId);
final String sharedText = RelayUtil.getSharedText(this);
final String sharedText = ShareUtil.getSharedText(this);
if (!draft.isOk()) {
if (TextUtils.isEmpty(sharedText)) {
@@ -883,6 +880,11 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
ImageButton quickCameraToggle = ViewUtil.findById(this, R.id.quick_camera_toggle);
// apply padding top to avoid drawing behind top bar
ViewUtil.applyWindowInsets(findViewById(R.id.fragment_content), false, true, false, false);
// apply padding to root to avoid collision with system bars
ViewUtil.applyWindowInsets(findViewById(R.id.root_layout), true, false, true, true);
container.addOnKeyboardShownListener(this);
container.addOnKeyboardHiddenListener(backgroundView);
container.addOnKeyboardShownListener(backgroundView);
@@ -940,7 +942,6 @@ public class ConversationActivity extends PassphraseRequiredActionBarActivity
supportActionBar.setCustomView(R.layout.conversation_title_view);
supportActionBar.setDisplayShowCustomEnabled(true);
supportActionBar.setDisplayShowTitleEnabled(false);
supportActionBar.setElevation(0); // TODO: use custom toolbar instead
Toolbar parent = (Toolbar) supportActionBar.getCustomView().getParent();
parent.setPadding(0,0,0,0);
@@ -17,7 +17,7 @@
package org.thoughtcrime.securesms;
import static com.b44t.messenger.DcContact.DC_CONTACT_ID_SELF;
import static org.thoughtcrime.securesms.util.RelayUtil.setForwardingMessageIds;
import static org.thoughtcrime.securesms.util.ShareUtil.setForwardingMessageIds;
import android.annotation.SuppressLint;
import android.app.Activity;
@@ -60,13 +60,13 @@ import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.reactions.AddReactionView;
import org.thoughtcrime.securesms.reactions.ReactionsDetailsFragment;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.relay.EditRelayActivity;
import org.thoughtcrime.securesms.util.AccessibilityUtil;
import org.thoughtcrime.securesms.util.Debouncer;
import org.thoughtcrime.securesms.util.StickyHeaderDecoration;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.ConversationAdaptiveActionsToolbar;
import org.thoughtcrime.securesms.calls.CallUtil;
import java.util.Collections;
import java.util.LinkedList;
@@ -785,7 +785,9 @@ public class ConversationFragment extends MessageSelectorFragment
&& messageRecord.getText().contains(self_mail)
&& getListAdapter().getChat().isDeviceTalk()) {
// This is a device message informing the user that the password is wrong
startActivity(new Intent(getActivity(), EditTransportActivity.class));
Intent intent = new Intent(getActivity(), EditRelayActivity.class);
intent.putExtra(EditRelayActivity.EXTRA_ADDR, self_mail);
startActivity(intent);
}
}
}
@@ -20,13 +20,13 @@ import static org.thoughtcrime.securesms.ConversationActivity.CHAT_ID_EXTRA;
import static org.thoughtcrime.securesms.ConversationActivity.STARTING_POSITION_EXTRA;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_URL;
import static org.thoughtcrime.securesms.util.RelayUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.RelayUtil.getDirectSharingChatId;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedTitle;
import static org.thoughtcrime.securesms.util.RelayUtil.isDirectSharing;
import static org.thoughtcrime.securesms.util.RelayUtil.isForwarding;
import static org.thoughtcrime.securesms.util.RelayUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.RelayUtil.resetRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.getDirectSharingChatId;
import static org.thoughtcrime.securesms.util.ShareUtil.getSharedTitle;
import static org.thoughtcrime.securesms.util.ShareUtil.isDirectSharing;
import static org.thoughtcrime.securesms.util.ShareUtil.isForwarding;
import static org.thoughtcrime.securesms.util.ShareUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.resetRelayingMessageContent;
import android.Manifest;
import android.content.Intent;
@@ -76,7 +76,7 @@ import org.thoughtcrime.securesms.search.SearchFragment;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.ShareUtil;
import org.thoughtcrime.securesms.util.SaveAttachmentTask;
import org.thoughtcrime.securesms.util.SendRelayedMessageUtil;
import org.thoughtcrime.securesms.util.StorageUtil;
@@ -159,6 +159,9 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
searchAction = findViewById(R.id.search_action);
fragmentContainer = findViewById(R.id.fragment_container);
// add margin to avoid content hidden behind system bars
ViewUtil.applyWindowInsetsAsMargin(searchToolbar, true, true, true, false);
Bundle bundle = new Bundle();
conversationListFragment = initFragment(R.id.fragment_container, new ConversationListFragment(), bundle);
@@ -360,7 +363,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
if (isRelayingMessageContent(this)) {
inflater.inflate(R.menu.forwarding_menu, menu);
menu.findItem(R.id.menu_export_attachment).setVisible(
RelayUtil.isFromWebxdc(this) && RelayUtil.getSharedUris(this).size() == 1
ShareUtil.isFromWebxdc(this) && ShareUtil.getSharedUris(this).size() == 1
);
} else {
inflater.inflate(R.menu.text_secure_normal, menu);
@@ -470,7 +473,7 @@ public class ConversationListActivity extends PassphraseRequiredActionBarActivit
}
private void performSave() {
ArrayList<Uri> uriList = RelayUtil.getSharedUris(this);
ArrayList<Uri> uriList = ShareUtil.getSharedUris(this);
Uri uri = uriList.get(0);
String mimeType = PersistentBlobProvider.getMimeType(this, uri);
String fileName = PersistentBlobProvider.getFileName(this, uri);
@@ -2,9 +2,9 @@ package org.thoughtcrime.securesms;
import static org.thoughtcrime.securesms.ConversationActivity.CHAT_ID_EXTRA;
import static org.thoughtcrime.securesms.ConversationActivity.FROM_ARCHIVED_CHATS_EXTRA;
import static org.thoughtcrime.securesms.util.RelayUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.RelayUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.RelayUtil.isSharing;
import static org.thoughtcrime.securesms.util.ShareUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.isSharing;
import android.content.Intent;
import android.os.Bundle;
@@ -23,7 +23,6 @@ public class ConversationListArchiveActivity extends PassphraseRequiredActionBar
protected void onCreate(Bundle icicle, boolean ready) {
setContentView(R.layout.activity_conversation_list_archive);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
if (isRelayingMessageContent(this)) {
getSupportActionBar().setTitle(isSharing(this) ? R.string.chat_share_with_title : R.string.forward_to);
getSupportActionBar().setSubtitle(R.string.chat_archived_label);
@@ -48,7 +48,7 @@ import org.thoughtcrime.securesms.mms.GlideApp;
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.ShareUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -108,6 +108,9 @@ public class ConversationListFragment extends BaseConversationListFragment
emptyState = ViewUtil.findById(view, R.id.empty_state);
emptySearch = ViewUtil.findById(view, R.id.empty_search);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(list, true, archive, true, true);
if (archive) {
fab.setVisibility(View.GONE);
TextView emptyTitle = ViewUtil.findById(view, R.id.empty_title);
@@ -115,6 +118,8 @@ public class ConversationListFragment extends BaseConversationListFragment
} else {
fab.setVisibility(View.VISIBLE);
}
// Apply insets to prevent fab from being covered by system bars
ViewUtil.applyWindowInsetsAsMargin(fab);
list.setHasFixedSize(true);
list.setLayoutManager(new LinearLayoutManager(getActivity()));
@@ -259,7 +264,7 @@ public class ConversationListFragment extends BaseConversationListFragment
int listflags = 0;
if (archive) {
listflags |= DcContext.DC_GCL_ARCHIVED_ONLY;
} else if (RelayUtil.isRelayingMessageContent(getActivity())) {
} else if (ShareUtil.isRelayingMessageContent(getActivity())) {
listflags |= DcContext.DC_GCL_FOR_FORWARDING;
} else {
listflags |= DcContext.DC_GCL_ADD_ALLDONE_HINT;
@@ -79,7 +79,6 @@ public class CreateProfileActivity extends BaseActionBarActivity {
getSupportActionBar().setTitle(R.string.pref_profile_info_headline);
getSupportActionBar().setDisplayHomeAsUpEnabled(!this.fromWelcome);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
attachmentManager = new AttachmentManager(this, () -> {});
avatarChanged = false;
@@ -185,6 +184,9 @@ public class CreateProfileActivity extends BaseActionBarActivity {
this.container = ViewUtil.findById(this, R.id.container);
this.statusView = ViewUtil.findById(this, R.id.status_text);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(container);
if (fromWelcome) {
loginSuccessText.setText(R.string.set_name_and_avatar_explain);
ViewUtil.findById(this, R.id.status_text_layout).setVisibility(View.GONE);
@@ -80,7 +80,6 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
unencrypted = getIntent().getBooleanExtra(UNENCRYPTED, false);
Objects.requireNonNull(getSupportActionBar()).setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
groupChatId = getIntent().getIntExtra(EDIT_GROUP_CHAT_ID, 0);
attachmentManager = new AttachmentManager(this, () -> {});
@@ -143,6 +142,11 @@ public class GroupCreateActivity extends PassphraseRequiredActionBarActivity
groupName = ViewUtil.findById(this, R.id.group_name);
TextView chatHints = ViewUtil.findById(this, R.id.chat_hints);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(lv, false, false, false, true);
// apply padding to root to avoid collision with system bars
ViewUtil.applyWindowInsets(findViewById(R.id.root_layout), true, false, true, false);
initializeAvatarView();
SelectedContactsAdapter adapter = new SelectedContactsAdapter(this, GlideApp.with(this), broadcast, unencrypted);
@@ -51,10 +51,12 @@ import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.profiles.AvatarHelper;
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
import org.thoughtcrime.securesms.qr.RegistrationQrActivity;
import org.thoughtcrime.securesms.relay.EditRelayActivity;
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.ViewUtil;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
import java.io.File;
@@ -104,7 +106,6 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
Objects.requireNonNull(getSupportActionBar()).setTitle(R.string.onboarding_create_instant_account);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
boolean fromWelcome = getIntent().getBooleanExtra(FROM_WELCOME, false);
if (DcHelper.getContext(this).isConfigured() == 1) {
@@ -330,6 +331,9 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
this.privacyPolicyBtn = findViewById(R.id.privacy_policy_button);
this.signUpBtn = findViewById(R.id.signup_button);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.container));
privacyPolicyBtn.setOnClickListener(view -> {
if (!isDcLogin) {
IntentUtils.showInBrowser(this, "https://" + providerHost + "/privacy.html");
@@ -342,18 +346,13 @@ public class InstantOnboardingActivity extends BaseActionBarActivity implements
IntentUtils.showInBrowser(this, INSTANCES_URL);
});
findViewById(R.id.login_button).setOnClickListener((v) -> {
startRegistrationActivity();
startActivity(new Intent(this, EditRelayActivity.class));
});
findViewById(R.id.scan_qr_button).setOnClickListener((v) -> {
new IntentIntegrator(this).setCaptureActivity(RegistrationQrActivity.class).initiateScan();
});
}
private void startRegistrationActivity() {
Intent intent = new Intent(this, EditTransportActivity.class);
startActivity(intent);
}
private void updateProvider() {
if (isDcLogin) {
signUpBtn.setText(R.string.login_title);
@@ -36,7 +36,6 @@ public class LogViewActivity extends BaseActionBarActivity {
transaction.commit();
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
}
@Override
@@ -37,12 +37,11 @@ import androidx.annotation.NonNull;
import androidx.core.content.PermissionChecker;
import androidx.fragment.app.Fragment;
import com.b44t.messenger.DcContext;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -55,6 +54,9 @@ import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import chat.delta.rpc.Rpc;
import chat.delta.rpc.RpcException;
public class LogViewFragment extends Fragment {
private EditText logPreview;
@@ -77,6 +79,10 @@ public class LogViewFragment extends Fragment {
super.onViewCreated(view, savedInstanceState);
logPreview = (EditText) getView().findViewById(R.id.log_preview);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(getView().findViewById(R.id.content_container), true, false, true, true);
new PopulateLogcatAsyncTask(this).execute();
}
@@ -124,10 +130,7 @@ public class LogViewFragment extends Fragment {
}
private static String grabLogcat(LogViewFragment fragment) {
String command = "logcat -v threadtime -d -t 10000";
if (!Prefs.isDeveloperModeEnabled(fragment.getActivity())) {
command += " *:I";
}
String command = "logcat -v threadtime -d -t 10000 *:I";
try {
final Process process = Runtime.getRuntime().exec(command);
final BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream()));
@@ -211,7 +214,6 @@ public class LogViewFragment extends Fragment {
PowerManager powerManager = (PowerManager)context.getSystemService(Context.POWER_SERVICE);
final PackageManager pm = context.getPackageManager();
final StringBuilder builder = new StringBuilder();
final DcContext dcContext = DcHelper.getContext(context);
builder.append("device=")
.append(Build.MANUFACTURER).append(" ")
@@ -266,8 +268,16 @@ public class LogViewFragment extends Fragment {
builder.append("Unknown\n");
}
final Rpc rpc = DcHelper.getRpc(context);
final int accId = DcHelper.getContext(context).getAccountId();
builder.append("\n");
builder.append(dcContext.getInfo());
try {
builder.append(rpc.getStorageUsageReportString(accId));
} catch (RpcException e) {
builder.append(e);
}
builder.append(DcHelper.getContext(context).getInfo());
return builder.toString();
}
@@ -18,8 +18,8 @@ package org.thoughtcrime.securesms;
import static org.thoughtcrime.securesms.ConversationActivity.CHAT_ID_EXTRA;
import static org.thoughtcrime.securesms.ConversationActivity.TEXT_EXTRA;
import static org.thoughtcrime.securesms.util.RelayUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.RelayUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.acquireRelayMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.isRelayingMessageContent;
import android.content.Intent;
import android.net.Uri;
@@ -28,7 +28,7 @@ import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.ShareUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -393,9 +393,9 @@ public class ProfileActivity extends PassphraseRequiredActionBarActivity
Intent composeIntent = new Intent();
DcContact dcContact = dcContext.getContact(contactId);
if (dcContact.isKeyContact()) {
RelayUtil.setSharedContactId(composeIntent, contactId);
ShareUtil.setSharedContactId(composeIntent, contactId);
} else {
RelayUtil.setSharedText(composeIntent, dcContact.getAddr());
ShareUtil.setSharedText(composeIntent, dcContact.getAddr());
}
ConversationListRelayingActivity.start(this, composeIntent);
}
@@ -68,6 +68,10 @@ public class ProfileFragment extends Fragment
adapter = new ProfileAdapter(this, GlideApp.with(this), this);
RecyclerView list = ViewUtil.findById(view, R.id.recycler_view);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(list);
list.setAdapter(adapter);
list.setLayoutManager(new LinearLayoutManager(getContext(), LinearLayoutManager.VERTICAL, false));
@@ -39,7 +39,7 @@ import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.util.DynamicNoActionBarTheme;
import org.thoughtcrime.securesms.util.MailtoUtil;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.ShareUtil;
import java.util.ArrayList;
import java.util.List;
@@ -274,7 +274,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
startActivity(composeIntent);
} else {
composeIntent = getBaseShareIntent(ConversationListRelayingActivity.class);
RelayUtil.setIsFromWebxdc(composeIntent, RelayUtil.isFromWebxdc(this));
ShareUtil.setIsFromWebxdc(composeIntent, ShareUtil.isFromWebxdc(this));
ConversationListRelayingActivity.start(this, composeIntent);
}
finish();
@@ -283,11 +283,11 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
private Intent getBaseShareIntent(final @NonNull Class<?> target) {
final Intent intent = new Intent(this, target);
RelayUtil.setSharedTitle(intent, RelayUtil.getSharedTitle(this));
RelayUtil.setSharedType(intent, RelayUtil.getSharedType(this));
RelayUtil.setSharedSubject(intent, RelayUtil.getSharedSubject(this));
RelayUtil.setSharedHtml(intent, RelayUtil.getSharedHtml(this));
RelayUtil.setSharedUris(intent, resolvedExtras);
ShareUtil.setSharedTitle(intent, ShareUtil.getSharedTitle(this));
ShareUtil.setSharedType(intent, ShareUtil.getSharedType(this));
ShareUtil.setSharedSubject(intent, ShareUtil.getSharedSubject(this));
ShareUtil.setSharedHtml(intent, ShareUtil.getSharedHtml(this));
ShareUtil.setSharedUris(intent, resolvedExtras);
String text = getIntent().getStringExtra(Intent.EXTRA_TEXT);
if (text==null) {
@@ -298,7 +298,7 @@ public class ShareActivity extends PassphraseRequiredActionBarActivity implement
}
if (text != null) {
RelayUtil.setSharedText(intent, text.toString());
ShareUtil.setSharedText(intent, text.toString());
}
if (resolvedExtras.size() > 0) {
@@ -26,6 +26,7 @@ import org.thoughtcrime.securesms.qr.QrCodeHandler;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.net.IDN;
@@ -37,6 +38,9 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
protected WebView webView;
/** Return true the window content should display fullscreen/edge-to-edge ex. in the integrated maps app */
protected boolean immersiveMode() { return false; }
protected boolean shouldAskToOpenLink() { return false; }
protected void toggleFakeProxy(boolean enable) {
@@ -62,10 +66,18 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setElevation(0); // TODO: use custom toolbar instead
}
webView = findViewById(R.id.webview);
if(immersiveMode()) {
// set a shadow in the status bar to make it more readable
findViewById(R.id.status_bar_background).setBackgroundResource(R.drawable.search_toolbar_shadow);
} else {
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.content_container));
}
webView.setWebViewClient(new WebViewClient() {
// IMPORTANT: this is will likely not be called inside iframes unless target=_blank is used in the anchor/link tag.
// `shouldOverrideUrlLoading()` is called when the user clicks a URL,
@@ -79,7 +91,20 @@ public class WebViewActivity extends PassphraseRequiredActionBarActivity
// so, to support all systems, for now, using the old one seems to be the simplest way.
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url != null) return openOnlineUrl(url);
if (url != null) {
String schema = url.split(":")[0].toLowerCase();
switch (schema) {
case "http":
case "https":
case "gemini":
case "tel":
case "sms":
case "mailto":
case "openpgp4fpr":
case "geo":
return openOnlineUrl(url);
}
}
return true; // returning `true` aborts loading
}
@@ -127,9 +127,6 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
public static void openWebxdcActivity(Context context, int msgId, boolean hideActionBar, String href) {
if (!Util.isClickedRecently()) {
if (Prefs.isDeveloperModeEnabled(context)) {
WebView.setWebContentsDebuggingEnabled(true);
}
context.startActivity(getWebxdcIntent(context, msgId, hideActionBar, href));
}
}
@@ -160,14 +157,18 @@ public class WebxdcActivity extends WebViewActivity implements DcEventCenter.DcE
.getIntents();
}
@Override
protected boolean immersiveMode() { return hideActionBar; }
@Override
protected void onCreate(Bundle state, boolean ready) {
Bundle b = getIntent().getExtras();
hideActionBar = b.getBoolean(EXTRA_HIDE_ACTION_BAR, false);
super.onCreate(state, ready);
rpc = DcHelper.getRpc(this);
initTTS();
Bundle b = getIntent().getExtras();
hideActionBar = b.getBoolean(EXTRA_HIDE_ACTION_BAR, false);
webView.setWebChromeClient(new WebChromeClient() {
@Override
@@ -25,6 +25,7 @@ import org.thoughtcrime.securesms.util.JsonUtils;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.io.ByteArrayInputStream;
import java.util.HashMap;
@@ -46,11 +47,13 @@ public class WebxdcStoreActivity extends PassphraseRequiredActionBarActivity {
dcContext = DcHelper.getContext(this);
WebView webView = findViewById(R.id.webview);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.content_container));
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setTitle(R.string.webxdc_apps);
actionBar.setElevation(0); // TODO: use custom toolbar instead
}
webView.setWebViewClient(new WebViewClient() {
@@ -39,6 +39,7 @@ import org.thoughtcrime.securesms.service.NotificationController;
import org.thoughtcrime.securesms.util.StorageUtil;
import org.thoughtcrime.securesms.util.StreamUtil;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
import java.io.File;
@@ -63,6 +64,9 @@ public class WelcomeActivity extends BaseActionBarActivity implements DcEventCen
super.onCreate(bundle);
setContentView(R.layout.welcome_activity);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.content_container));
findViewById(R.id.signup_button).setOnClickListener((v) -> startInstantOnboardingActivity());
findViewById(R.id.add_as_second_device_button).setOnClickListener((v) -> startAddAsSecondDeviceActivity());
findViewById(R.id.backup_button).setOnClickListener((v) -> startImportBackup());
@@ -35,7 +35,7 @@ import org.thoughtcrime.securesms.qr.QrActivity;
import org.thoughtcrime.securesms.recipients.Recipient;
import org.thoughtcrime.securesms.util.FileUtils;
import org.thoughtcrime.securesms.util.MediaUtil;
import org.thoughtcrime.securesms.util.RelayUtil;
import org.thoughtcrime.securesms.util.ShareUtil;
import org.thoughtcrime.securesms.util.Util;
import java.io.File;
@@ -299,17 +299,17 @@ public class DcHelper {
public static void sendToChat(Context activity, byte[] data, String type, String fileName, String html, String subject, String text) {
Intent intent = new Intent(activity, ShareActivity.class);
intent.setAction(Intent.ACTION_SEND);
RelayUtil.setIsFromWebxdc(intent, true);
ShareUtil.setIsFromWebxdc(intent, true);
if (data != null) {
String mimeType = "application/octet-stream";
Uri uri = PersistentBlobProvider.getInstance().create(activity, data, mimeType, fileName);
intent.setType(mimeType);
intent.putExtra(Intent.EXTRA_STREAM, uri);
RelayUtil.setSharedType(intent, type);
RelayUtil.setSharedTitle(intent, activity.getString(R.string.send_file_to, fileName));
ShareUtil.setSharedType(intent, type);
ShareUtil.setSharedTitle(intent, activity.getString(R.string.send_file_to, fileName));
} else {
RelayUtil.setSharedTitle(intent, activity.getString(R.string.send_message_to));
ShareUtil.setSharedTitle(intent, activity.getString(R.string.send_message_to));
}
if (text != null) {
@@ -317,13 +317,13 @@ public class DcHelper {
}
if (subject != null) {
RelayUtil.setSharedSubject(intent, subject);
ShareUtil.setSharedSubject(intent, subject);
}
if (html != null) {
String mimeType = "application/octet-stream";
Uri uri = PersistentBlobProvider.getInstance().create(activity, html.getBytes(), mimeType, "index.html");
RelayUtil.setSharedHtml(intent, uri);
ShareUtil.setSharedHtml(intent, uri);
}
activity.startActivity(intent);
@@ -77,11 +77,17 @@ public class KeepAliveService extends Service {
return null;
}
@Override
public void onDestroy() {
Log.i("DeltaChat", "*** KeepAliveService.onDestroy()");
// the service will be restarted due to START_STICKY automatically, there's nothing more to do.
}
@Override
public void onTimeout(int startId, int fgsType) {
stopSelf();
}
static public KeepAliveService getInstance()
{
return s_this; // may be null
@@ -42,9 +42,11 @@ public class NewContactActivity extends PassphraseRequiredActionBarActivity
actionBar.setTitle(R.string.menu_new_classic_contact);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
actionBar.setElevation(0); // TODO: use custom toolbar instead
}
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.content_container));
nameInput = ViewUtil.findById(this, R.id.name_text);
addrInput = ViewUtil.findById(this, R.id.email_text);
addrInput.setText(getIntent().getStringExtra(ADDR_EXTRA));
@@ -7,9 +7,7 @@ import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_MVBOX_MOVE;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ONLY_FETCH_MVBOX;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_SHOW_EMAILS;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_WEBXDC_REALTIME_ENABLED;
import static org.thoughtcrime.securesms.connect.DcHelper.getRpc;
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
@@ -17,7 +15,6 @@ import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.webkit.WebView;
import android.widget.EditText;
import androidx.annotation.NonNull;
@@ -28,12 +25,10 @@ import androidx.preference.ListPreference;
import androidx.preference.Preference;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.ConversationActivity;
import org.thoughtcrime.securesms.LogViewActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.EditTransportActivity;
import org.thoughtcrime.securesms.relay.RelayListActivity;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
import org.thoughtcrime.securesms.util.Prefs;
import org.thoughtcrime.securesms.util.ScreenLockUtil;
@@ -47,8 +42,6 @@ import java.io.InputStream;
import java.io.OutputStream;
import java.util.Objects;
import chat.delta.rpc.RpcException;
public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
implements DcEventCenter.DcEventDelegate
@@ -145,14 +138,6 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
}
updateWebxdcStoreSummary();
Preference developerModeEnabled = this.findPreference("pref_developer_mode_enabled");
if (developerModeEnabled != null) {
developerModeEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
WebView.setWebContentsDebuggingEnabled((Boolean) newValue);
return true;
});
}
Preference proxySettings = this.findPreference("proxy_settings_button");
if (proxySettings != null) {
proxySettings.setOnPreferenceClickListener((preference) -> {
@@ -161,21 +146,19 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
});
}
Preference passwordAndAccount = this.findPreference("password_account_settings_button");
if (passwordAndAccount != null) {
passwordAndAccount.setOnPreferenceClickListener(((preference) -> {
boolean result = ScreenLockUtil.applyScreenLock(requireActivity(), getString(R.string.edit_transport), getString(R.string.enter_system_secret_to_continue), REQUEST_CODE_CONFIRM_CREDENTIALS_ACCOUNT);
Preference relayListBtn = this.findPreference("pref_relay_list_button");
if (relayListBtn != null) {
relayListBtn.setOnPreferenceClickListener(((preference) -> {
boolean result = ScreenLockUtil.applyScreenLock(requireActivity(), getString(R.string.transports), getString(R.string.enter_system_secret_to_continue), REQUEST_CODE_CONFIRM_CREDENTIALS_ACCOUNT);
if (!result) {
openRegistrationActivity();
openRelayListActivity();
}
return true;
}));
}
if (dcContext.isChatmail()) {
showEmails.setVisible(false);
mvboxMoveCheckbox.setVisible(false);
onlyFetchMvboxCheckbox.setVisible(false);
findPreference("pref_category_legacy").setVisible(false);
}
}
@@ -203,7 +186,7 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE_CONFIRM_CREDENTIALS_ACCOUNT) {
openRegistrationActivity();
openRelayListActivity();
}
}
@@ -270,8 +253,8 @@ public class AdvancedPreferenceFragment extends ListSummaryPreferenceFragment
}
}
private void openRegistrationActivity() {
Intent intent = new Intent(requireActivity(), EditTransportActivity.class);
private void openRelayListActivity() {
Intent intent = new Intent(requireActivity(), RelayListActivity.class);
startActivity(intent);
}
@@ -70,9 +70,7 @@ public class ChatBackgroundActivity extends PassphraseRequiredActionBarActivity
actionBar.setTitle(R.string.pref_background);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
actionBar.setElevation(0); // TODO: use custom toolbar instead
}
}
@Override
@@ -30,7 +30,6 @@ public class PrivacyPreferenceFragment extends ListSummaryPreferenceFragment {
private static final String TAG = PrivacyPreferenceFragment.class.getSimpleName();
private CheckBoxPreference readReceiptsCheckbox;
private CheckBoxPreference showSystemContacts;
private ListPreference autoDelDevice;
private ListPreference autoDelServer;
@@ -39,13 +38,6 @@ public class PrivacyPreferenceFragment extends ListSummaryPreferenceFragment {
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
showSystemContacts = (CheckBoxPreference) this.findPreference("pref_show_system_contacts");
showSystemContacts.setOnPreferenceChangeListener((preference, newValue) -> {
boolean enabled = (Boolean) newValue;
dcContext.setConfigInt("ui.android.show_system_contacts", enabled? 1 : 0);
return true;
});
readReceiptsCheckbox = (CheckBoxPreference) this.findPreference("pref_read_receipts");
readReceiptsCheckbox.setOnPreferenceChangeListener(new ReadReceiptToggleListener());
@@ -62,10 +54,6 @@ public class PrivacyPreferenceFragment extends ListSummaryPreferenceFragment {
Preference screenSecurity = this.findPreference(Prefs.SCREEN_SECURITY_PREF);
screenSecurity.setOnPreferenceChangeListener(new ScreenShotSecurityListener());
if (dcContext.isChatmail()) {
showSystemContacts.setVisible(false);
}
}
@Override
@@ -78,7 +66,6 @@ public class PrivacyPreferenceFragment extends ListSummaryPreferenceFragment {
super.onResume();
((ApplicationPreferencesActivity)getActivity()).getSupportActionBar().setTitle(R.string.pref_privacy);
showSystemContacts.setChecked(0!=dcContext.getConfigInt("ui.android.show_system_contacts"));
readReceiptsCheckbox.setChecked(0 != dcContext.getConfigInt("mdns_enabled"));
initAutodelFromCore();
}
@@ -28,35 +28,37 @@ import org.thoughtcrime.securesms.BaseActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.LinkedList;
public class ProxySettingsActivity extends BaseActionBarActivity
implements ProxyListAdapter.ItemClickListener, DcEventCenter.DcEventDelegate {
private final DynamicTheme dynamicTheme = new DynamicTheme();
private SwitchCompat proxySwitch;
private ProxyListAdapter adapter;
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
dynamicTheme.onCreate(this);
setContentView(R.layout.proxy_settings_activity);
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(R.string.proxy_settings);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setElevation(0); // TODO: use custom toolbar instead
}
proxySwitch = findViewById(R.id.proxy_switch);
ListView proxyList = findViewById(R.id.proxy_list);
ViewUtil.applyWindowInsets(proxySwitch, true, false, true, false);
ViewUtil.applyWindowInsets(proxyList, true, false, true, true);
adapter = new ProxyListAdapter(this);
adapter.setItemClickListener(this);
proxySwitch = findViewById(R.id.proxy_switch);
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1);
proxySwitch.setOnClickListener(l -> {
if (proxySwitch.isChecked() && adapter.getCount() == 0) {
@@ -67,7 +69,6 @@ public class ProxySettingsActivity extends BaseActionBarActivity
}
});
ListView proxyList = findViewById(R.id.proxy_list);
proxyList.setAdapter(adapter);
proxyList.addHeaderView(View.inflate(this, R.layout.proxy_list_header, null), null, false);
View footer = View.inflate(this, R.layout.proxy_list_footer, null);
@@ -85,12 +86,6 @@ public class ProxySettingsActivity extends BaseActionBarActivity
handleOpenProxyUrl();
}
@Override
public void onResume() {
super.onResume();
dynamicTheme.onResume(this);
}
@Override
public void onDestroy() {
super.onDestroy();
@@ -24,6 +24,7 @@ import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.service.GenericForegroundService;
import org.thoughtcrime.securesms.service.NotificationController;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
public class BackupTransferActivity extends BaseActionBarActivity {
@@ -85,7 +86,9 @@ public class BackupTransferActivity extends BaseActionBarActivity {
supportActionBar.setDisplayHomeAsUpEnabled(true);
supportActionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
supportActionBar.setTitle(title);
supportActionBar.setElevation(0); // TODO: use custom toolbar instead
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.backup_provider_fragment));
}
@Override
@@ -44,6 +44,8 @@ import java.io.InputStream;
public class QrActivity extends BaseActionBarActivity implements View.OnClickListener {
private final static String TAG = QrActivity.class.getSimpleName();
public final static String EXTRA_SCAN_RELAY = "scan_relay";
private final static int REQUEST_CODE_IMAGE = 46243;
private final static int TAB_SHOW = 0;
private final static int TAB_SCAN = 1;
@@ -51,6 +53,7 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
private TabLayout tabLayout;
private ViewPager viewPager;
private QrShowFragment qrShowFragment;
private boolean scanRelay;
@Override
protected void onPreCreate() {
@@ -61,8 +64,10 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_qr);
scanRelay = getIntent().getBooleanExtra(EXTRA_SCAN_RELAY, false);
qrShowFragment = new QrShowFragment(this);
tabLayout = ViewUtil.findById(this, R.id.tab_layout);
viewPager = ViewUtil.findById(this, R.id.pager);
@@ -71,10 +76,11 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
setSupportActionBar(ViewUtil.findById(this, R.id.toolbar));
assert getSupportActionBar() != null;
getSupportActionBar().setTitle(R.string.menu_new_contact);
getSupportActionBar().setTitle(scanRelay? R.string.add_transport : R.string.menu_new_contact);
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
viewPager.setCurrentItem(TAB_SHOW);
viewPager.setCurrentItem(scanRelay? TAB_SCAN : TAB_SHOW);
if (scanRelay) tabLayout.setVisibility(View.GONE);
viewPager.addOnPageChangeListener(new ViewPager.OnPageChangeListener() {
@Override
@@ -102,7 +108,13 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
.ifNecessary()
.withPermanentDenialDialog(getString(R.string.perm_explain_access_to_camera_denied))
.onAllGranted(() -> ((QrScanFragment) adapter.getItem(TAB_SCAN)).handleQrScanWithPermissions(QrActivity.this))
.onAnyDenied(() -> viewPager.setCurrentItem(TAB_SHOW))
.onAnyDenied(() -> {
if (scanRelay) {
finish();
} else {
viewPager.setCurrentItem(TAB_SHOW);
}
})
.execute();
}
}
@@ -149,7 +161,11 @@ public class QrActivity extends BaseActionBarActivity implements View.OnClickLis
if (permissions.length > 0
&& Manifest.permission.CAMERA.equals(permissions[0])
&& grantResults[0] == PackageManager.PERMISSION_DENIED) {
viewPager.setCurrentItem(TAB_SHOW);
if (scanRelay) {
finish();
} else {
viewPager.setCurrentItem(TAB_SHOW);
}
// Workaround because sometimes something else requested the permissions before this class
// (probably the CameraView) and then this class didn't notice when it was denied
}
@@ -1,7 +1,9 @@
package org.thoughtcrime.securesms.qr;
import android.app.Activity;
import android.content.DialogInterface;
import android.content.Intent;
import android.util.Log;
import android.widget.Toast;
import androidx.annotation.StringRes;
@@ -17,15 +19,25 @@ import org.thoughtcrime.securesms.connect.AccountManager;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.views.ProgressDialog;
import chat.delta.rpc.Rpc;
import chat.delta.rpc.RpcException;
public class QrCodeHandler {
private static final String TAG = QrCodeHandler.class.getSimpleName();
private final Activity activity;
private final DcContext dcContext;
private final Rpc rpc;
private final int accId;
public QrCodeHandler(Activity activity) {
this.activity = activity;
dcContext = DcHelper.getContext(activity);
rpc = DcHelper.getRpc(activity);
accId = dcContext.getAccountId();
}
public void onScanPerformed(IntentResult scanResult) {
@@ -67,10 +79,7 @@ public class QrCodeHandler {
case DcContext.DC_QR_ACCOUNT:
case DcContext.DC_QR_LOGIN:
final String scope = qrParsed.getText1();
builder.setMessage(activity.getString(qrParsed.getState() == DcContext.DC_QR_ACCOUNT ? R.string.qraccount_ask_create_and_login_another : R.string.qrlogin_ask_login_another, scope));
builder.setPositiveButton(R.string.ok, (dialog, which) -> {
AccountManager.getInstance().addAccountFromQr(activity, rawString);
});
setAddTransportDialog(activity, builder, rawString, scope);
builder.setNegativeButton(R.string.cancel, null);
builder.setCancelable(false);
break;
@@ -246,4 +255,43 @@ public class QrCodeHandler {
});
builder.setNegativeButton(android.R.string.cancel, null);
}
private void setAddTransportDialog(Activity activity, AlertDialog.Builder builder, String qrData, String transportName) {
builder.setTitle(R.string.confirm_add_transport);
builder.setMessage(transportName);
builder.setPositiveButton(R.string.ok, (d, w) -> {
ProgressDialog progressDialog = new ProgressDialog(activity);
progressDialog.setMessage(activity.getResources().getString(R.string.one_moment));
progressDialog.setCanceledOnTouchOutside(false);
progressDialog.setCancelable(false);
String cancel = activity.getResources().getString(android.R.string.cancel);
progressDialog.setButton(DialogInterface.BUTTON_NEGATIVE, cancel, (d2, w2) -> {
dcContext.stopOngoingProcess();
});
progressDialog.show();
Util.runOnAnyBackgroundThread(() -> {
String error = null;
try {
rpc.addTransportFromQr(accId, qrData);
} catch (RpcException e) {
Log.w(TAG, e);
error = e.getMessage();
}
final String finalError = error;
Util.runOnMain(() -> {
if (!progressDialog.isShowing()) return; // canceled dialog, nothing to do
if (finalError != null) {
Toast.makeText(activity, finalError, Toast.LENGTH_LONG).show();
}
try {
progressDialog.dismiss();
} catch (IllegalArgumentException e) {
// see https://stackoverflow.com/a/5102572/4557005
Log.w(TAG, e);
}
});
});
});
}
}
@@ -18,6 +18,7 @@ import com.journeyapps.barcodescanner.CompoundBarcodeView;
import com.journeyapps.barcodescanner.DecoratedBarcodeView;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.ViewUtil;
public class QrScanFragment extends Fragment {
@@ -38,6 +39,9 @@ public class QrScanFragment extends Fragment {
barcodeScannerView = view.findViewById(R.id.zxing_barcode_scanner);
barcodeScannerView.setStatusText(getString(R.string.qrscan_hint) + "\n ");
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(barcodeScannerView.getStatusView());
return view;
}
@@ -5,19 +5,17 @@ import android.view.Menu;
import android.view.MenuItem;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import com.b44t.messenger.DcContext;
import org.thoughtcrime.securesms.BaseActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
public class QrShowActivity extends AppCompatActivity {
private final DynamicTheme dynamicTheme = new DynamicTheme();
public class QrShowActivity extends BaseActionBarActivity {
public final static String CHAT_ID = "chat_id";
@@ -29,11 +27,13 @@ public class QrShowActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
dynamicTheme.onCreate(this);
setContentView(R.layout.activity_qr_show);
fragment = (QrShowFragment)getSupportFragmentManager().findFragmentById(R.id.qrScannerFragment);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.qrScannerFragment), false, true, false, false);
dcContext = DcHelper.getContext(this);
dcEventCenter = DcHelper.getEventCenter(this);
@@ -74,12 +74,6 @@ public class QrShowActivity extends AppCompatActivity {
return super.onCreateOptionsMenu(menu);
}
@Override
protected void onResume() {
super.onResume();
dynamicTheme.onResume(this);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
super.onOptionsItemSelected(item);
@@ -19,6 +19,7 @@ import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
public class RegistrationQrActivity extends BaseActionBarActivity {
@@ -42,7 +43,9 @@ public class RegistrationQrActivity extends BaseActionBarActivity {
getSupportActionBar().setTitle(R.string.scan_invitation_code);
}
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
getSupportActionBar().setElevation(0); // TODO: use custom toolbar instead
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.layout_container), true, false, true, true);
barcodeScannerView = findViewById(R.id.zxing_barcode_scanner);
barcodeScannerView.setStatusText(getString(R.string.qrscan_hint) + "\n ");
@@ -1,4 +1,4 @@
package org.thoughtcrime.securesms;
package org.thoughtcrime.securesms.relay;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_PROXY_ENABLED;
import static org.thoughtcrime.securesms.connect.DcHelper.getContext;
@@ -10,6 +10,7 @@ import android.os.Bundle;
import android.text.Editable;
import android.text.TextUtils;
import android.text.TextWatcher;
import android.util.Log;
import android.util.Patterns;
import android.view.Menu;
import android.view.MenuInflater;
@@ -32,11 +33,15 @@ import com.b44t.messenger.DcEvent;
import com.b44t.messenger.DcProvider;
import com.google.android.material.textfield.TextInputEditText;
import org.thoughtcrime.securesms.BaseActionBarActivity;
import org.thoughtcrime.securesms.ConversationListActivity;
import org.thoughtcrime.securesms.LogViewActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.WelcomeActivity;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.permissions.Permissions;
import org.thoughtcrime.securesms.proxy.ProxySettingsActivity;
import org.thoughtcrime.securesms.util.DynamicTheme;
import org.thoughtcrime.securesms.util.IntentUtils;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
@@ -50,7 +55,7 @@ import chat.delta.rpc.types.EnteredCertificateChecks;
import chat.delta.rpc.types.EnteredLoginParam;
import chat.delta.rpc.types.Socket;
public class EditTransportActivity extends BaseActionBarActivity implements DcEventCenter.DcEventDelegate {
public class EditRelayActivity extends BaseActionBarActivity implements DcEventCenter.DcEventDelegate {
private enum VerificationType {
EMAIL,
@@ -58,7 +63,8 @@ public class EditTransportActivity extends BaseActionBarActivity implements DcEv
PORT,
}
private final DynamicTheme dynamicTheme = new DynamicTheme();
private static final String TAG = EditRelayActivity.class.getSimpleName();
public final static String EXTRA_ADDR = "extra_addr";
private TextInputEditText emailInput;
private TextInputEditText passwordInput;
@@ -85,12 +91,15 @@ public class EditTransportActivity extends BaseActionBarActivity implements DcEv
@Override
public void onCreate(Bundle bundle) {
super.onCreate(bundle);
dynamicTheme.onCreate(this);
rpc = DcHelper.getRpc(this);
accId = DcHelper.getContext(this).getAccountId();
setContentView(R.layout.activity_edittransport);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(findViewById(R.id.content_container));
emailInput = findViewById(R.id.email_text);
passwordInput = findViewById(R.id.password_text);
@@ -118,11 +127,26 @@ public class EditTransportActivity extends BaseActionBarActivity implements DcEv
startActivity(new Intent(this, ProxySettingsActivity.class));
});
String addr = getIntent().getStringExtra(EXTRA_ADDR);
EnteredLoginParam config = null;
try {
List<EnteredLoginParam> relays = rpc.listTransports(accId);
if (!relays.isEmpty()) config = relays.get(0);
} catch (RpcException ignored) {}
for (EnteredLoginParam relay : relays) {
if (addr != null && addr.equals(relay.addr)) {
config = relay;
break;
}
}
if (config == null && !relays.isEmpty()) {
Log.e(TAG, "Error got unknown address: " + addr);
finish();
return;
};
} catch (RpcException e) {
Log.e(TAG, "Error calling Rpc.listTransports()", e);
finish();
return;
}
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
@@ -131,7 +155,6 @@ public class EditTransportActivity extends BaseActionBarActivity implements DcEv
);
actionBar.setDisplayHomeAsUpEnabled(true);
actionBar.setHomeAsUpIndicator(R.drawable.ic_close_white_24dp);
actionBar.setElevation(0); // TODO: use custom toolbar instead
}
if (config != null) emailInput.setEnabled(false);
@@ -215,7 +238,6 @@ public class EditTransportActivity extends BaseActionBarActivity implements DcEv
@Override
public void onResume() {
super.onResume();
dynamicTheme.onResume(this);
proxySwitch.setChecked(DcHelper.getInt(this, CONFIG_PROXY_ENABLED) == 1);
}
@@ -0,0 +1,180 @@
package org.thoughtcrime.securesms.relay;
import android.content.Intent;
import android.os.Bundle;
import android.util.Log;
import android.view.MenuItem;
import androidx.annotation.NonNull;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.recyclerview.widget.DividerItemDecoration;
import androidx.recyclerview.widget.LinearLayoutManager;
import androidx.recyclerview.widget.RecyclerView;
import com.b44t.messenger.DcContext;
import com.b44t.messenger.DcEvent;
import com.google.zxing.integration.android.IntentIntegrator;
import com.google.zxing.integration.android.IntentResult;
import org.thoughtcrime.securesms.BaseActionBarActivity;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton;
import org.thoughtcrime.securesms.connect.DcEventCenter;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.qr.QrActivity;
import org.thoughtcrime.securesms.qr.QrCodeHandler;
import org.thoughtcrime.securesms.util.Util;
import org.thoughtcrime.securesms.util.ViewUtil;
import java.util.List;
import chat.delta.rpc.Rpc;
import chat.delta.rpc.RpcException;
import chat.delta.rpc.types.EnteredLoginParam;
public class RelayListActivity extends BaseActionBarActivity
implements RelayListAdapter.OnRelayClickListener, DcEventCenter.DcEventDelegate {
private static final String TAG = RelayListActivity.class.getSimpleName();
private RelayListAdapter adapter;
private Rpc rpc;
private int accId;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_relay_list);
rpc = DcHelper.getRpc(this);
accId = DcHelper.getContext(this).getAccountId();
ActionBar actionBar = getSupportActionBar();
if (actionBar != null) {
actionBar.setTitle(R.string.transports);
actionBar.setDisplayHomeAsUpEnabled(true);
}
RecyclerView recyclerView = findViewById(R.id.relay_list);
PulsingFloatingActionButton fabAdd = findViewById(R.id.fab_add_relay);
// add padding to avoid content hidden behind system bars
ViewUtil.applyWindowInsets(recyclerView);
// Apply insets to prevent fab from being covered by system bars
ViewUtil.applyWindowInsetsAsMargin(fabAdd);
fabAdd.setOnClickListener(v -> {
new IntentIntegrator(this).setCaptureActivity(QrActivity.class).addExtra(QrActivity.EXTRA_SCAN_RELAY, true).initiateScan();
});
LinearLayoutManager layoutManager = new LinearLayoutManager(this);
// Add the default divider (uses the themes `android.R.attr.listDivider`)
DividerItemDecoration divider = new DividerItemDecoration(
recyclerView.getContext(),
layoutManager.getOrientation());
recyclerView.addItemDecoration(divider);
recyclerView.setLayoutManager(layoutManager);
adapter = new RelayListAdapter(this);
recyclerView.setAdapter(adapter);
loadRelays();
DcEventCenter eventCenter = DcHelper.getEventCenter(this);
eventCenter.addObserver(DcContext.DC_EVENT_CONFIGURE_PROGRESS, this);
}
@Override
public void onDestroy() {
super.onDestroy();
DcHelper.getEventCenter(this).removeObservers(this);
}
private void loadRelays() {
Util.runOnAnyBackgroundThread(() -> {
String mainRelayAddr = "";
try {
mainRelayAddr = rpc.getConfig(accId, DcHelper.CONFIG_CONFIGURED_ADDRESS);
} catch (RpcException e) {
Log.e(TAG, "RPC.getConfig() failed", e);
}
String finalMainRelayAddr = mainRelayAddr;
try {
List<EnteredLoginParam> relays = rpc.listTransports(accId);
Util.runOnMain(() -> adapter.setRelays(relays, finalMainRelayAddr));
} catch (RpcException e) {
Log.e(TAG, "RPC.listTransports() failed", e);
Util.runOnMain(() -> adapter.setRelays(null, finalMainRelayAddr));
}
});
}
@Override
public void onRelayClick(EnteredLoginParam relay) {
if (relay.addr != null && !relay.addr.equals(adapter.getMainRelay())) {
Util.runOnAnyBackgroundThread(() -> {
try {
rpc.setConfig(accId, DcHelper.CONFIG_CONFIGURED_ADDRESS, relay.addr);
} catch (RpcException e) {
Log.e(TAG, "RPC.setConfig() failed", e);
}
loadRelays();
});
}
}
@Override
public void onRelayEdit(EnteredLoginParam relay) {
Intent intent = new Intent(this, EditRelayActivity.class);
intent.putExtra(EditRelayActivity.EXTRA_ADDR, relay.addr);
startActivity(intent);
}
@Override
public void onRelayDelete(EnteredLoginParam relay) {
new AlertDialog.Builder(this)
.setTitle(R.string.remove_transport)
.setMessage(getString(R.string.confirm_remove_transport, relay.addr))
.setPositiveButton(R.string.ok, (dialog, which) -> {
try {
rpc.deleteTransport(accId, relay.addr);
loadRelays();
} catch (RpcException e) {
Log.e(TAG, "RPC.deleteTransport() failed", e);
}
})
.setNegativeButton(R.string.cancel, null)
.show();
}
@Override
public boolean onOptionsItemSelected(@NonNull MenuItem item) {
if (item.getItemId() == android.R.id.home) {
finish();
return true;
}
return super.onOptionsItemSelected(item);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == IntentIntegrator.REQUEST_CODE) {
IntentResult scanResult = IntentIntegrator.parseActivityResult(requestCode, resultCode, data);
QrCodeHandler qrCodeHandler = new QrCodeHandler(this);
qrCodeHandler.onScanPerformed(scanResult);
}
}
@Override
public void handleEvent(@NonNull DcEvent event) {
int eventId = event.getId();
if (eventId == DcContext.DC_EVENT_CONFIGURE_PROGRESS && event.getData1Int() == 1000) {
loadRelays();
}
}
}
@@ -0,0 +1,108 @@
package org.thoughtcrime.securesms.relay;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ImageView;
import android.widget.TextView;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.recyclerview.widget.RecyclerView;
import org.thoughtcrime.securesms.R;
import java.util.ArrayList;
import java.util.List;
import chat.delta.rpc.types.EnteredLoginParam;
public class RelayListAdapter extends RecyclerView.Adapter<RelayListAdapter.RelayViewHolder> {
private List<EnteredLoginParam> relays = new ArrayList<>();
private final OnRelayClickListener listener;
private String mainRelayAddr;
public interface OnRelayClickListener {
void onRelayClick(EnteredLoginParam relay);
void onRelayEdit(EnteredLoginParam relay);
void onRelayDelete(EnteredLoginParam relay);
}
public RelayListAdapter(OnRelayClickListener listener) {
this.listener = listener;
}
public String getMainRelay() {
return mainRelayAddr;
}
public void setRelays(@Nullable List<EnteredLoginParam> relays, String mainRelayAddr) {
this.relays = relays != null ? relays : new ArrayList<>();
this.mainRelayAddr = mainRelayAddr;
notifyDataSetChanged();
}
@NonNull
@Override
public RelayViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
View view = LayoutInflater.from(parent.getContext())
.inflate(R.layout.relay_list_item, parent, false);
return new RelayViewHolder(view);
}
@Override
public void onBindViewHolder(@NonNull RelayViewHolder holder, int position) {
EnteredLoginParam relay = relays.get(position);
boolean isMain = relay.addr != null && relay.addr.equals(mainRelayAddr);
holder.bind(relay, isMain, listener);
}
@Override
public int getItemCount() {
return relays.size();
}
public static class RelayViewHolder extends RecyclerView.ViewHolder {
private final TextView titleText;
private final TextView subtitleText;
private final ImageView mainIndicator;
private final ImageView editButton;
private final ImageView deleteButton;
public RelayViewHolder(@NonNull View itemView) {
super(itemView);
titleText = itemView.findViewById(R.id.title);
subtitleText = itemView.findViewById(R.id.subtitle);
mainIndicator = itemView.findViewById(R.id.main_indicator);
editButton = itemView.findViewById(R.id.edit_button);
deleteButton = itemView.findViewById(R.id.delete_button);
}
public void bind(EnteredLoginParam relay, boolean isMain, OnRelayClickListener listener) {
String[] parts = relay.addr.split("@");
titleText.setText(parts.length == 2? parts[1] : parts[0]);
subtitleText.setText(parts.length == 2? parts[0] : "");
mainIndicator.setVisibility(isMain ? View.VISIBLE : View.INVISIBLE);
deleteButton.setVisibility(isMain ? View.GONE : View.VISIBLE);
itemView.setOnClickListener(v -> {
if (listener != null) {
listener.onRelayClick(relay);
}
});
editButton.setOnClickListener(v -> {
if (listener != null) {
listener.onRelayEdit(relay);
}
});
deleteButton.setOnClickListener(v -> {
if (listener != null) {
listener.onRelayDelete(relay);
}
});
}
}
}
@@ -1,7 +1,7 @@
package org.thoughtcrime.securesms.search;
import static org.thoughtcrime.securesms.util.RelayUtil.isRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.isRelayingMessageContent;
import android.content.res.Configuration;
import android.os.Bundle;
@@ -166,10 +166,6 @@ public class Prefs {
return true;
}
public static boolean isDeveloperModeEnabled(Context context) {
return getBooleanPreference(context, "pref_developer_mode_enabled", false);
}
public static boolean isNewBroadcastAvailable(Context context) {
return true;
}
@@ -152,13 +152,32 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask<SaveAttachmentTa
return StorageUtil.getVideoUri();
} else if (contentType.startsWith("audio/")) {
return StorageUtil.getAudioUri();
} else if (contentType.startsWith("image/")) {
} else if (isMediaStoreImageType(contentType)) {
return StorageUtil.getImageUri();
} else {
return StorageUtil.getDownloadUri();
}
}
/**
* Checks if the content type is a standard image format supported by Android's MediaStore.
* Non-standard image formats (like XCF, PSD, etc.) should be saved to Downloads instead.
*/
private boolean isMediaStoreImageType(@NonNull String contentType) {
if (!contentType.startsWith("image/")) {
return false;
}
return contentType.equals("image/jpeg") ||
contentType.equals("image/jpg") ||
contentType.equals("image/png") ||
contentType.equals("image/gif") ||
contentType.equals("image/webp") ||
contentType.equals("image/bmp") ||
contentType.equals("image/heic") ||
contentType.equals("image/heif") ||
contentType.equals("image/avif");
}
private @Nullable File ensureExternalPath(@Nullable File path) {
if (path != null && path.exists()) {
return path;
@@ -197,7 +216,7 @@ public class SaveAttachmentTask extends ProgressDialogAsyncTask<SaveAttachmentTa
storage = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MOVIES);
} else if (contentType.startsWith("audio/")) {
storage = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC);
} else if (contentType.startsWith("image/")) {
} else if (isMediaStoreImageType(contentType)) {
storage = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES);
}
@@ -1,14 +1,11 @@
package org.thoughtcrime.securesms.util;
import static org.thoughtcrime.securesms.util.RelayUtil.getForwardedMessageIDs;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedText;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedSubject;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedHtml;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedType;
import static org.thoughtcrime.securesms.util.RelayUtil.getSharedUris;
import static org.thoughtcrime.securesms.util.RelayUtil.isForwarding;
import static org.thoughtcrime.securesms.util.RelayUtil.isSharing;
import static org.thoughtcrime.securesms.util.RelayUtil.resetRelayingMessageContent;
import static org.thoughtcrime.securesms.util.ShareUtil.getForwardedMessageIDs;
import static org.thoughtcrime.securesms.util.ShareUtil.getSharedText;
import static org.thoughtcrime.securesms.util.ShareUtil.getSharedUris;
import static org.thoughtcrime.securesms.util.ShareUtil.isForwarding;
import static org.thoughtcrime.securesms.util.ShareUtil.isSharing;
import static org.thoughtcrime.securesms.util.ShareUtil.resetRelayingMessageContent;
import android.app.Activity;
import android.content.ContentResolver;
@@ -69,9 +66,9 @@ public class SendRelayedMessageUtil {
} else if (isSharing(activity)) {
ArrayList<Uri> sharedUris = getSharedUris(activity);
String sharedText = getSharedText(activity);
String subject = getSharedSubject(activity);
String sharedHtml = getHtml(activity, getSharedHtml(activity));
String msgType = getSharedType(activity);
String subject = ShareUtil.getSharedSubject(activity);
String sharedHtml = getHtml(activity, ShareUtil.getSharedHtml(activity));
String msgType = ShareUtil.getSharedType(activity);
resetRelayingMessageContent(activity);
Util.runOnAnyBackgroundThread(() -> {
for (long chatId : chatIds) {
@@ -13,7 +13,7 @@ import androidx.annotation.NonNull;
import java.util.ArrayList;
public class RelayUtil {
public class ShareUtil {
private static final String FORWARDED_MESSAGE_IDS = "forwarded_message_ids";
private static final String SHARED_URIS = "shared_uris";
private static final String SHARED_CONTACT_ID = "shared_contact_id";
@@ -41,10 +41,14 @@ import androidx.annotation.IdRes;
import androidx.annotation.LayoutRes;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.graphics.Insets;
import androidx.core.view.ViewCompat;
import androidx.core.view.WindowInsetsCompat;
import androidx.interpolator.view.animation.FastOutSlowInInterpolator;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.util.views.Stub;
import chat.delta.util.ListenableFuture;
@@ -294,4 +298,208 @@ public class ViewUtil {
}
return selection;
}
/**
* Get combined insets from status bar, navigation bar and display cutout areas.
*
* @param windowInsets The window insets to extract from
* @return Combined insets using the maximum values from system bars and display cutout
*/
private static Insets getCombinedInsets(@NonNull WindowInsetsCompat windowInsets) {
Insets systemBars = windowInsets.getInsets(WindowInsetsCompat.Type.systemBars());
Insets displayCutout = windowInsets.getInsets(WindowInsetsCompat.Type.displayCutout());
return Insets.max(systemBars, displayCutout);
}
/**
* Apply window insets to a view by adding margin to avoid drawing it behind system bars.
* Convenience method that applies insets to all sides.
*
* @param view The view to apply insets to
*/
public static void applyWindowInsetsAsMargin(@NonNull View view) {
applyWindowInsetsAsMargin(view, true, true, true, true);
}
/**
* Apply window insets to a view by adding margin to avoid drawing it behind system bars.
*
* This method stores the original margin values in view tags to ensure that
* margin doesn't accumulate on multiple inset applications.
*
* @param view The view to apply insets to
* @param left Whether to apply left inset
* @param top Whether to apply top inset
* @param right Whether to apply right inset
* @param bottom Whether to apply bottom inset
*/
public static void applyWindowInsetsAsMargin(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) {
// Only enable on API 30+ where WindowInsets APIs work correctly
if (Build.VERSION.SDK_INT < VERSION_CODES.R) return;
// Store the original margin as a tag only if not already stored
// This prevents losing the true original margin on subsequent calls
if (view.getTag(R.id.tag_window_insets_margin_left) == null) {
ViewGroup.LayoutParams params = view.getLayoutParams();
if (params instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) params;
view.setTag(R.id.tag_window_insets_margin_left, marginParams.leftMargin);
view.setTag(R.id.tag_window_insets_margin_top, marginParams.topMargin);
view.setTag(R.id.tag_window_insets_margin_right, marginParams.rightMargin);
view.setTag(R.id.tag_window_insets_margin_bottom, marginParams.bottomMargin);
}
}
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
Insets insets = getCombinedInsets(windowInsets);
// Retrieve the original margin values from tags with null checks
Integer leftTag = (Integer) v.getTag(R.id.tag_window_insets_margin_left);
Integer topTag = (Integer) v.getTag(R.id.tag_window_insets_margin_top);
Integer rightTag = (Integer) v.getTag(R.id.tag_window_insets_margin_right);
Integer bottomTag = (Integer) v.getTag(R.id.tag_window_insets_margin_bottom);
int baseMarginLeft = leftTag != null ? leftTag : 0;
int baseMarginTop = topTag != null ? topTag : 0;
int baseMarginRight = rightTag != null ? rightTag : 0;
int baseMarginBottom = bottomTag != null ? bottomTag : 0;
ViewGroup.LayoutParams layoutParams = v.getLayoutParams();
if (layoutParams instanceof ViewGroup.MarginLayoutParams) {
ViewGroup.MarginLayoutParams marginParams = (ViewGroup.MarginLayoutParams) layoutParams;
marginParams.leftMargin = baseMarginLeft + insets.left;
marginParams.topMargin = baseMarginTop + insets.top;
marginParams.rightMargin = baseMarginRight + insets.right;
marginParams.bottomMargin = baseMarginBottom + insets.bottom;
v.setLayoutParams(marginParams);
}
return windowInsets;
});
// Request the initial insets to be dispatched if the view is attached
if (view.isAttachedToWindow()) {
ViewCompat.requestApplyInsets(view);
}
}
/**
* Apply window insets to a view by adding padding to avoid drawing elements behind system bars.
* Convenience method that applies insets to all sides.
*
* @param view The view to apply insets to
*/
public static void applyWindowInsets(@NonNull View view) {
applyWindowInsets(view, true, true, true, true);
}
/**
* Apply window insets to a view by adding padding to avoid drawing elements behind system bars.
*
* This method stores the original padding values in view tags to ensure that
* padding doesn't accumulate on multiple inset applications.
*
* @param view The view to apply insets to
* @param left Whether to apply left inset
* @param top Whether to apply top inset
* @param right Whether to apply right inset
* @param bottom Whether to apply bottom inset
*/
public static void applyWindowInsets(@NonNull View view, boolean left, boolean top, boolean right, boolean bottom) {
// Only enable on API 30+ where WindowInsets APIs work correctly
if (Build.VERSION.SDK_INT < VERSION_CODES.R) return;
// Store the original padding as a tag only if not already stored
// This prevents losing the true original padding on subsequent calls
if (view.getTag(R.id.tag_window_insets_padding_left) == null) {
view.setTag(R.id.tag_window_insets_padding_left, view.getPaddingLeft());
view.setTag(R.id.tag_window_insets_padding_top, view.getPaddingTop());
view.setTag(R.id.tag_window_insets_padding_right, view.getPaddingRight());
view.setTag(R.id.tag_window_insets_padding_bottom, view.getPaddingBottom());
}
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
Insets insets = getCombinedInsets(windowInsets);
// Retrieve the original padding values from tags with null checks
Integer leftTag = (Integer) v.getTag(R.id.tag_window_insets_padding_left);
Integer topTag = (Integer) v.getTag(R.id.tag_window_insets_padding_top);
Integer rightTag = (Integer) v.getTag(R.id.tag_window_insets_padding_right);
Integer bottomTag = (Integer) v.getTag(R.id.tag_window_insets_padding_bottom);
int basePaddingLeft = leftTag != null ? leftTag : 0;
int basePaddingTop = topTag != null ? topTag : 0;
int basePaddingRight = rightTag != null ? rightTag : 0;
int basePaddingBottom = bottomTag != null ? bottomTag : 0;
v.setPadding(
left ? basePaddingLeft + insets.left : basePaddingLeft,
top ? basePaddingTop + insets.top : basePaddingTop,
right ? basePaddingRight + insets.right : basePaddingRight,
bottom ? basePaddingBottom + insets.bottom : basePaddingBottom
);
return windowInsets;
});
// Request the initial insets to be dispatched if the view is attached
if (view.isAttachedToWindow()) {
ViewCompat.requestApplyInsets(view);
}
}
/**
* Apply the top status bar inset as the height of a view.
*/
private static void applyTopInsetAsHeight(@NonNull View view) {
ViewCompat.setOnApplyWindowInsetsListener(view, (v, windowInsets) -> {
Insets insets = getCombinedInsets(windowInsets);
android.view.ViewGroup.LayoutParams params = v.getLayoutParams();
if (params != null) {
params.height = insets.top;
v.setLayoutParams(params);
}
return windowInsets;
});
// Request the initial insets to be dispatched if the view is attached
if (view.isAttachedToWindow()) {
ViewCompat.requestApplyInsets(view);
}
}
/**
* Apply adjustments to the activity's custom toolbar or set height of R.id.status_bar_background for proper Edge-to-Edge display.
*
* @param activity The activity to apply the adjustments to
*/
public static void adjustToolbarForE2E(@NonNull AppCompatActivity activity) {
// Only enable on API 30+ where WindowInsets APIs work correctly
if (Build.VERSION.SDK_INT < VERSION_CODES.R) return;
// The toolbar/app bar should extend behind the status bar with padding applied
View toolbar = activity.findViewById(R.id.toolbar);
if (toolbar != null) {
// Check if toolbar is inside an AppBarLayout
View parent = (View) toolbar.getParent();
if (parent instanceof com.google.android.material.appbar.AppBarLayout) {
ViewUtil.applyWindowInsets(parent, true, true, true, false);
} else {
ViewUtil.applyWindowInsets(toolbar, true, true, true, false);
}
}
// For activities without a custom toolbar, apply insets to status_bar_background view
View statusBarBackground = activity.findViewById(R.id.status_bar_background);
if (statusBarBackground != null) {
ViewUtil.applyTopInsetAsHeight(statusBarBackground);
ActionBar actionBar = activity.getSupportActionBar();
if (actionBar != null) {
// elevation is set via status_bar_background view
// otherwise there is a drop-shadow at the top
actionBar.setElevation(0);
}
}
}
}
@@ -0,0 +1,76 @@
package org.thoughtcrime.securesms.webxdc;
import android.content.Context;
import android.util.Log;
import android.webkit.WebStorage;
import androidx.annotation.NonNull;
import androidx.concurrent.futures.CallbackToFutureAdapter;
import androidx.work.ListenableWorker;
import androidx.work.WorkerParameters;
import chat.delta.rpc.Rpc;
import chat.delta.rpc.RpcException;
import com.google.common.util.concurrent.ListenableFuture;
import java.util.Collections;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.thoughtcrime.securesms.connect.DcHelper;
public class WebxdcGarbageCollectionWorker extends ListenableWorker {
private static final String TAG = WebxdcGarbageCollectionWorker.class.getSimpleName();
private Rpc rpc;
public WebxdcGarbageCollectionWorker(Context context, WorkerParameters params) {
super(context, params);
rpc = DcHelper.getRpc(context);
}
@Override
public @NonNull ListenableFuture<Result> startWork() {
Log.i(TAG, "Running Webxdc storage garbage collection...");
final Pattern WEBXDC_URL_PATTERN =
Pattern.compile("^https?://acc(\\d+)-msg(\\d+)\\.localhost/?");
return CallbackToFutureAdapter.getFuture(completer -> {
WebStorage webStorage = WebStorage.getInstance();
webStorage.getOrigins((origins) -> {
if (origins == null || origins.isEmpty()) {
Log.i(TAG, "Done, no WebView origins found.");
completer.set(Result.success());
return;
}
for (Object key : origins.keySet()) {
String url = (String)key;
Matcher m = WEBXDC_URL_PATTERN.matcher(url);
if (m.matches()) {
int accId = Integer.parseInt(m.group(1));
int msgId = Integer.parseInt(m.group(2));
try {
if (rpc.getExistingMsgIds(accId, Collections.singletonList(msgId)).isEmpty()) {
webStorage.deleteOrigin(url);
Log.i(TAG, String.format("Deleted webxdc origin: %s", url));
} else {
Log.i(TAG, String.format("Existing webxdc origin: %s", url));
}
} catch (RpcException e) {
Log.e(TAG, "error calling rpc.getExistingMsgIds()", e);
completer.set(Result.failure());
return;
}
} else { // old webxdc URL schemes, etc
webStorage.deleteOrigin(url);
Log.i(TAG, String.format("Deleted unknown origin: %s", url));
}
}
Log.i(TAG, "Done running Webxdc storage garbage collection.");
completer.set(Result.success());
});
return "Webxdc Garbage Collector";
});
}
}
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:id="@+id/fragment" />
</RelativeLayout>
</FrameLayout>
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:id="@+id/fragment" />
</RelativeLayout>
</FrameLayout>
@@ -1,15 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:id="@+id/fragment" />
</RelativeLayout>
</FrameLayout>
@@ -1,21 +1,21 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
android:layout_height="match_parent">
android:layout_height="match_parent"
tools:context=".EditTransportActivity">
<include layout="@layout/status_bar_background"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="?android:attr/windowBackground"
tools:context=".EditTransportActivity">
android:fillViewport="true">
<androidx.constraintlayout.widget.ConstraintLayout
android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:animateLayoutChanges="true">
@@ -395,4 +395,4 @@
</ScrollView>
</RelativeLayout>
</FrameLayout>
+1 -4
View File
@@ -3,14 +3,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
+4 -4
View File
@@ -1,15 +1,15 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<fragment xmlns:android="http://schemas.android.com/apk/res/android"
android:name="org.thoughtcrime.securesms.qr.QrShowFragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:id="@+id/qrScannerFragment" />
</RelativeLayout>
</FrameLayout>
@@ -1,18 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:orientation="vertical"
android:gravity="center_horizontal">
<include layout="@layout/status_bar_background"/>
<LinearLayout
android:id="@+id/top_text"
android:layout_width="match_parent"
@@ -94,4 +90,4 @@
</LinearLayout>
</RelativeLayout>
</FrameLayout>
@@ -1,18 +1,14 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_container"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:orientation="vertical"
android:gravity="center_horizontal">
<include layout="@layout/status_bar_background"/>
<androidx.legacy.widget.Space
android:layout_weight="2"
android:layout_width="match_parent"
@@ -40,5 +36,3 @@
android:layout_height="0dp"/>
</LinearLayout>
</RelativeLayout>
@@ -0,0 +1,31 @@
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<androidx.recyclerview.widget.RecyclerView
android:id="@+id/relay_list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:clipToPadding="false"
android:paddingBottom="88dp"
android:scrollbars="vertical"
tools:listitem="@layout/relay_list_item" />
<org.thoughtcrime.securesms.components.registration.PulsingFloatingActionButton
android:id="@+id/fab_add_relay"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="bottom|end"
android:layout_margin="16dp"
app:backgroundTint="?attr/fab_color"
android:src="@drawable/ic_add_white_24dp"
android:focusable="true"
android:contentDescription="@string/add_transport"/>
</FrameLayout>
@@ -2,11 +2,11 @@
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/layout_container"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<org.thoughtcrime.securesms.components.ScaleStableImageView
android:id="@+id/preview"
android:scaleType="centerCrop"
@@ -45,4 +45,4 @@
</LinearLayout>
</FrameLayout>
</FrameLayout>
+1 -4
View File
@@ -3,14 +3,11 @@
xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_height="match_parent"
android:layout_width="match_parent"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"
xmlns:app="http://schemas.android.com/apk/res-auto">
<com.google.android.material.appbar.AppBarLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
app:elevation="0dp">
android:layout_height="wrap_content">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
@@ -1,11 +1,11 @@
<?xml version="1.0" encoding="UTF-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
@@ -2,15 +2,13 @@
<LinearLayout android:layout_gravity="center"
android:layout_height="fill_parent"
android:layout_width="fill_parent"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"
android:orientation="vertical"
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto">
<org.thoughtcrime.securesms.components.ContactFilterToolbar
android:id="@+id/toolbar"
android:layout_height="?attr/actionBarSize"
android:layout_height="wrap_content"
android:layout_width="match_parent"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
@@ -18,16 +16,9 @@
android:theme="?attr/actionBarStyle"
app:contentInsetStartWithNavigation="0dp"/>
<FrameLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground">
<fragment android:id="@+id/contact_selection_list_fragment"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:name="org.thoughtcrime.securesms.ContactSelectionListFragment" />
</FrameLayout>
</LinearLayout>
</LinearLayout>
@@ -2,10 +2,12 @@
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:fitsSystemWindows="true"
android:background="?attr/colorPrimary"
android:id="@+id/root_layout"
android:background="?attr/input_panel_bg_color"
android:layout_height="match_parent" android:layout_width="match_parent">
<include layout="@layout/status_bar_background"/>
<org.thoughtcrime.securesms.components.ScaleStableImageView
android:id="@+id/conversation_background"
android:layout_width="match_parent"
@@ -4,111 +4,105 @@
xmlns:tools="http://schemas.android.com/tools"
android:id="@id/container"
android:orientation="vertical"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="?attr/actionBarSize"
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetStart="0dp"
app:contentInsetLeft="0dp"
android:elevation="4dp"
android:theme="?attr/actionBarStyle">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/avatar_and_title"
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_weight="1"
android:paddingStart="14dp"
android:layout_height="match_parent"
android:layout_marginEnd="10dp">
<RelativeLayout
android:id="@+id/self_avatar_container"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="45dp">
<org.thoughtcrime.securesms.components.AvatarView
android:id="@+id/self_avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:clickable="true"
app:inverted="true"
android:contentDescription="@string/pref_profile_info_headline" />
<ImageView android:id="@+id/unread_indicator"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="16dp"
android:contentDescription="@null"
android:visibility="gone"
/>
</RelativeLayout>
<androidx.appcompat.widget.AppCompatTextView
style="@style/TextSecure.TitleTextStyle"
android:id="@+id/toolbar_title"
android:layout_width="0dp"
<androidx.appcompat.widget.Toolbar
android:id="@+id/toolbar"
android:layout_alignParentTop="true"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:paddingRight="10dp"
android:ellipsize="end"
android:maxLines="1"/>
android:minHeight="?attr/actionBarSize"
android:background="?attr/colorPrimary"
app:contentInsetStart="0dp"
app:contentInsetLeft="0dp"
android:elevation="4dp"
android:theme="?attr/actionBarStyle">
<LinearLayout
android:orientation="horizontal"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
android:id="@+id/avatar_and_title"
android:orientation="horizontal"
android:layout_width="0dp"
android:layout_weight="1"
android:paddingStart="14dp"
android:layout_height="match_parent"
android:layout_marginEnd="10dp">
<RelativeLayout
android:id="@+id/self_avatar_container"
android:orientation="vertical"
android:layout_width="wrap_content"
android:layout_height="45dp">
<org.thoughtcrime.securesms.components.AvatarView
android:id="@+id/self_avatar"
android:layout_width="35dp"
android:layout_height="35dp"
android:layout_marginRight="10dp"
android:layout_marginEnd="10dp"
android:layout_marginTop="5dp"
android:layout_marginBottom="5dp"
android:clickable="true"
app:inverted="true"
android:contentDescription="@string/pref_profile_info_headline" />
<ImageView android:id="@+id/unread_indicator"
android:layout_width="20dp"
android:layout_height="20dp"
android:layout_marginLeft="20dp"
android:layout_marginStart="20dp"
app:layout_constraintTop_toTopOf="parent"
android:layout_marginBottom="16dp"
android:contentDescription="@null"
android:visibility="gone"
/>
</RelativeLayout>
<androidx.appcompat.widget.AppCompatTextView
style="@style/TextSecure.TitleTextStyle"
android:id="@+id/toolbar_title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:text="@string/app_name"
android:layout_weight="1"
android:layout_gravity="center_vertical"
android:paddingRight="10dp"
android:ellipsize="end"
android:maxLines="1"/>
</LinearLayout>
<ImageView
android:id="@+id/search_action"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/ic_search_white_24dp"
android:paddingRight="12dp"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingStart="12dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_gravity="center_vertical"
android:contentDescription="@string/search"/>
<ImageView android:id="@+id/search_action"
android:layout_width="wrap_content"
android:layout_height="match_parent"
android:src="@drawable/ic_search_white_24dp"
android:paddingRight="12dp"
android:paddingEnd="12dp"
android:paddingLeft="12dp"
android:paddingStart="12dp"
android:layout_marginTop="4dp"
android:layout_marginBottom="4dp"
android:layout_gravity="center_vertical"
android:contentDescription="@string/search"/>
</LinearLayout>
</LinearLayout>
</androidx.appcompat.widget.Toolbar>
</androidx.appcompat.widget.Toolbar>
<FrameLayout
android:id="@+id/fragment_container"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
/>
<FrameLayout android:id="@+id/fragment_container"
android:layout_below="@id/toolbar"
android:layout_width="match_parent"
android:layout_height="match_parent"/>
<org.thoughtcrime.securesms.components.SearchToolbar
android:id="@+id/search_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:elevation="4dp"
android:visibility="invisible"
tools:visibility="visible"/>
<org.thoughtcrime.securesms.components.SearchToolbar
android:id="@+id/search_toolbar"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_alignParentTop="true"
android:elevation="4dp"
android:visibility="invisible"
tools:visibility="visible"/>
</RelativeLayout>
@@ -45,6 +45,8 @@
android:id="@+id/list"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="88dp"
android:clipToPadding="false"
android:scrollbars="vertical"
android:nextFocusDown="@+id/fab"
android:nextFocusForward="@+id/fab"
+5 -2
View File
@@ -6,12 +6,15 @@
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<ScrollView
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="2">
<LinearLayout android:layout_width="match_parent"
<LinearLayout android:id="@+id/content_container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
@@ -29,4 +32,4 @@
</LinearLayout>
</ScrollView>
</LinearLayout>
</LinearLayout>
+7 -10
View File
@@ -1,17 +1,14 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<LinearLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="@+id/root_layout"
android:background="?android:attr/windowBackground"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="?android:attr/windowBackground"
android:orientation="vertical">
<include layout="@layout/status_bar_background"/>
<LinearLayout
android:id="@+id/group_image_holder"
android:layout_width="fill_parent"
@@ -53,7 +50,9 @@
android:textSize="18sp"
android:text="@string/chat_new_channel_hint" />
<!-- clipToPadding is needed so ViewUtil.applyWindowInsets() works properly -->
<ListView android:id="@+id/selected_contacts_list"
android:clipToPadding="false"
android:layout_marginTop="16dp"
android:layout_width="match_parent"
android:layout_height="wrap_content"
@@ -61,5 +60,3 @@
android:divider="@null" />
</LinearLayout>
</RelativeLayout>
@@ -1,19 +1,18 @@
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout
<FrameLayout
xmlns:android="http://schemas.android.com/apk/res/android"
android:background="?attr/colorPrimary"
android:fitsSystemWindows="true"
android:layout_width="match_parent"
android:layout_height="match_parent">
<include layout="@layout/status_bar_background"/>
<ScrollView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:fillViewport="true"
android:background="?android:attr/windowBackground"
>
android:fillViewport="true">
<LinearLayout
android:id="@+id/container"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingStart="16dp"
@@ -145,4 +144,4 @@
</ScrollView>
</RelativeLayout>
</FrameLayout>

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